diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6996302..1e6596d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,4 +45,6 @@ jobs: run: tcli publish --config-path ./ClientUI/thunderstore.toml --token ${{ secrets.THUNDERSTORE_KEY }} --file ./dist/XPRising-ClientUI-${RELEASE_TAG:1}.zip - name: Set release as latest - run: gh release edit ${{ env.RELEASE_TAG }} --draft=false --latest \ No newline at end of file + run: gh release edit ${{ env.RELEASE_TAG }} --draft=false --latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index ab59cbf..9794844 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Fixed` for any bug fixes. - `Security` in case of vulnerabilities. +## [0.4.9] - 2025-05-30 + +### Changed + +- Updated documentation for bloodline mastery to make it match current behaviour and describe it clearer + +### Fixed + +- Fixed issue that would double apply growth reduction for bloodline mastery when feeding on V Bloods +- Fixed configuration folder normalisation to ensure folder paths are more consistent/usable + ## [0.4.8] - 2025-05-30 ### Changed diff --git a/Documentation.md b/Documentation.md index ce93e4c..b71d082 100644 --- a/Documentation.md +++ b/Documentation.md @@ -24,12 +24,19 @@ Weapon/spell mastery will increase when the weapon/spell is used to damage a cre ### Blood Mastery Feeding on enemies will progress the mastery of that bloodline. If the feeding is cancelled, to kill your victim, a smaller amount of mastery is granted. -Note that your victim will need to have a higher quality of blood than your mastery level to gain mastery. - -Bloodline mastery for blood types that don't match your current blood will still be applied at a greatly reduced amount. -V Bloods will give increased mastery improvements. There is configuration to have this apply to X number of random bloodlines, all bloodlines, or just the current player bloodline. - -To enable being able to gain mastery on all kills, not just feeding kills, you will need to disable `Merciless bloodlines`. When this is disabled: players will get extra bloodline mastery when making a feeding kill as the mob death will generate a base amount in addition to the standard feeding mastery gain. +V Bloods will give increase mastery improvements. + +#### Configuration + +| Option | Value | Documentation | +|-------------------------------|-------|-----------------------------------------------------------------------------------------------------------------| +| Merciless Bloodlines | true | Victim blood quality needs to be of a higher value than blood mastery to gain mastery | +| | false | Mastery always improves when the level is less than 100% | +| V Blood improves X bloodlines | 0 | Player's current blood type is used to determine what blood mastery to increase when feeding on a V Blood | +| | 10 | All blood types gain mastery when feeding on a V Blood | +| | X | X randomly chosen blood types gain mastery when feeding on a V Blood (for who knows what the V Blood contains?) | +| Mastery Gain Multiplier | X | Mastery gain is multiplied by this value. Can be used to increase/decrease mastery gain. | +| VBlood Mastery Multiplier | X | Bonus V Blood mastery multiplier (this applies to weapon mastery as well) | ### Mastery buff configuration The buffs provided by the mastery system can be configured two ways: there are some preset options for quick configuration, or there is the custom configuration which allows great flexibility. diff --git a/XPRising/Configuration/DebugLoggingConfig.cs b/XPRising/Configuration/DebugLoggingConfig.cs index 8960c0c..cd7490d 100644 --- a/XPRising/Configuration/DebugLoggingConfig.cs +++ b/XPRising/Configuration/DebugLoggingConfig.cs @@ -13,6 +13,7 @@ public static class DebugLoggingConfig public static void Initialize() { var configPath = AutoSaveSystem.ConfirmFile(AutoSaveSystem.ConfigPath, "DebugLoggingConfig.cfg"); + Plugin.Log(Plugin.LogSystem.Core, LogLevel.Info, $"config folder path: \"{AutoSaveSystem.ConfigPath}\""); _configFile = new ConfigFile(configPath, true); // Currently, we are never updating and saving the config file in game, so just load the values. diff --git a/XPRising/Configuration/GlobalMasteryConfig.cs b/XPRising/Configuration/GlobalMasteryConfig.cs index 61ac677..fc23422 100644 --- a/XPRising/Configuration/GlobalMasteryConfig.cs +++ b/XPRising/Configuration/GlobalMasteryConfig.cs @@ -31,7 +31,7 @@ public static void Initialize() WeaponMasterySystem.MasteryGainMultiplier = _configFile.Bind("Mastery - Weapon", "Mastery Gain Multiplier", 1.0, "Multiply the gained mastery value by this amount.").Value; // Blood mastery specific config - BloodlineSystem.MercilessBloodlines = _configFile.Bind("Mastery - Blood", "Merciless Bloodlines", BloodlineSystem.MercilessBloodlines, "Causes blood mastery to only grow when you kill something with a matching blood type of that has a quality higher than the current blood mastery").Value; + BloodlineSystem.MercilessBloodlines = _configFile.Bind("Mastery - Blood", "Merciless Bloodlines", BloodlineSystem.MercilessBloodlines, "Causes blood mastery to only grow when you kill something that has a quality higher than the current blood mastery. V Bloods count as 100% quality.").Value; BloodlineSystem.VBloodAddsXTypes = _configFile.Bind("Mastery - Blood", "V Blood improves X bloodlines", BloodlineSystem.BloodTypeCount, "Causes consuming a V Blood to improve X random blood masteries. Default value is \"all\" bloodlines. Set to 0 to only do the current bloodline.").Value; BloodlineSystem.MasteryGainMultiplier = _configFile.Bind("Mastery - Blood", "Mastery Gain Multiplier", 1.0, "Multiply the gained mastery value by this amount.").Value; } diff --git a/XPRising/Plugin.cs b/XPRising/Plugin.cs index c142526..83f84dd 100644 --- a/XPRising/Plugin.cs +++ b/XPRising/Plugin.cs @@ -199,9 +199,7 @@ public static void Initialize() // Pre-initialise some constants Helper.Initialise(); - var configFolderName = string.Join("_", - ("XPRising_" + SettingsManager.ServerHostSettings.Name).Split(Path.GetInvalidFileNameChars())); - AutoSaveSystem.ConfigFolder = configFolderName; + AutoSaveSystem.ConfigFolder = AutoSaveSystem.NormaliseConfigFolder(SettingsManager.ServerHostSettings.Name); // Ensure that internal settings are consistent with server settings var serverSettings = Plugin.Server.GetExistingSystemManaged(); diff --git a/XPRising/Systems/BloodlineSystem.cs b/XPRising/Systems/BloodlineSystem.cs index ead2c6a..4d859c9 100644 --- a/XPRising/Systems/BloodlineSystem.cs +++ b/XPRising/Systems/BloodlineSystem.cs @@ -61,32 +61,36 @@ public static void UpdateBloodline(Entity killer, Entity victim, bool killOnly) GlobalMasterySystem.MasteryType victimBloodType; float victimBloodQuality; bool isVBlood; + var growthModifier = killOnly ? 0.4 : 1.0; if (_em.TryGetComponentData(victim, out var victimBlood)) { victimBloodQuality = victimBlood.BloodQuality; isVBlood = Helper.IsVBlood(victimBlood); if (isVBlood) { + victimBloodQuality = 100f; + growthModifier = VBloodMultiplier; // When running the kill only step for VBloods, only add to the current bloodline, not multi-bloodlines if (VBloodAddsXTypes > 0 && !killOnly) { - var baseGrowthVal = growthVal * 0.05 * MasteryGainMultiplier * VBloodMultiplier; var pmd = Database.PlayerMastery[steamID]; if (VBloodAddsXTypes >= BloodTypeCount) { - Plugin.Log(LogSystem.Bloodline, LogLevel.Info, $"Adding V Blood bonus ({baseGrowthVal}) to all blood types"); + Plugin.Log(LogSystem.Bloodline, LogLevel.Info, () => $"Adding V Blood bonus to all blood types."); foreach (var bloodType in BuffToBloodTypeMap.Values) { - GlobalMasterySystem.BankMastery(steamID, victim, bloodType, baseGrowthVal * pmd[killerBloodType].Growth); + var bloodTypeGrowth = growthVal * BloodGrowthMultiplier(growthModifier, victimBloodQuality); + GlobalMasterySystem.BankMastery(steamID, victim, bloodType, ApplyMasteryMultiplier(bloodType, bloodTypeGrowth)); } } else { var selectedBloodTypes = BuffToBloodTypeMap.Values.OrderBy(x => _random.Next()).Take(VBloodAddsXTypes); - Plugin.Log(LogSystem.Bloodline, LogLevel.Info, () => $"Adding V Blood bonus ({baseGrowthVal}) to {VBloodAddsXTypes} blood types: {string.Join(",", selectedBloodTypes)}"); + Plugin.Log(LogSystem.Bloodline, LogLevel.Info, () => $"Adding V Blood bonus to {VBloodAddsXTypes} blood types: {string.Join(",", selectedBloodTypes)}"); foreach (var bloodType in selectedBloodTypes) { - GlobalMasterySystem.BankMastery(steamID, victim, bloodType, baseGrowthVal * pmd[killerBloodType].Growth); + var bloodTypeGrowth = growthVal * BloodGrowthMultiplier(growthModifier, victimBloodQuality); + GlobalMasterySystem.BankMastery(steamID, victim, bloodType, ApplyMasteryMultiplier(bloodType, bloodTypeGrowth)); } } return; @@ -94,7 +98,6 @@ public static void UpdateBloodline(Entity killer, Entity victim, bool killOnly) else { victimBloodType = killerBloodType; - victimBloodQuality = 100f; } } else @@ -114,11 +117,9 @@ public static void UpdateBloodline(Entity killer, Entity victim, bool killOnly) return; } - var growthModifier = killOnly ? 0.4 : isVBlood ? VBloodMultiplier : 1.0; - var playerMasterydata = Database.PlayerMastery[steamID]; var bloodlineMastery = playerMasterydata[victimBloodType]; - growthVal *= bloodlineMastery.Growth * growthModifier * (victimBloodQuality * 0.01f); + growthVal *= BloodGrowthMultiplier(growthModifier, victimBloodQuality); if (MercilessBloodlines && victimBloodQuality <= bloodlineMastery.Mastery) { @@ -146,10 +147,8 @@ public static void UpdateBloodline(Entity killer, Entity victim, bool killOnly) Plugin.Log(LogSystem.Bloodline, LogLevel.Info, $"Bonus bloodline mastery {bonusMastery:F3}]"); } - - Plugin.Log(LogSystem.Bloodline, LogLevel.Info, - () => $"Blood growth {Enum.GetName(victimBloodType)}: [{growthVal:F3} * 0.05 * {MasteryGainMultiplier:F3} => {growthVal * 0.05 * MasteryGainMultiplier:F3}]"); - growthVal *= 0.05 * MasteryGainMultiplier; + + growthVal = ApplyMasteryMultiplier(victimBloodType, growthVal); GlobalMasterySystem.BankMastery(steamID, victim, victimBloodType, growthVal); } @@ -177,5 +176,17 @@ private static bool GuidToBloodType(PrefabGUID guid, out GlobalMasterySystem.Mas bloodType = (GlobalMasterySystem.MasteryType)guid.GuidHash; return true; } + + private static double BloodGrowthMultiplier(double modifier, double quality) + { + return modifier * quality * 0.01f; + } + + private static double ApplyMasteryMultiplier(GlobalMasterySystem.MasteryType bloodType, double mastery) + { + Plugin.Log(LogSystem.Bloodline, LogLevel.Info, + () => $"Blood growth {Enum.GetName(bloodType)}: [{mastery:F3} * 0.05 * {MasteryGainMultiplier:F3} => {mastery * 0.05 * MasteryGainMultiplier:F3}]"); + return mastery * 0.05 * MasteryGainMultiplier; + } } } diff --git a/XPRising/Systems/GlobalMasterySystem.cs b/XPRising/Systems/GlobalMasterySystem.cs index f09463f..6769c74 100644 --- a/XPRising/Systems/GlobalMasterySystem.cs +++ b/XPRising/Systems/GlobalMasterySystem.cs @@ -389,8 +389,7 @@ public static void ExitCombat(ulong steamID) { if (!_masteryBank.TryRemove(steamID, out var data)) return; - var lostMastery = data.Aggregate(0d, (a, b) => a + b.Value.Aggregate(0d, (c, d) => c + d.Value)); - Plugin.Log(Plugin.LogSystem.Mastery, LogLevel.Info, $"Mastery lost on combat exit: {steamID}: {lostMastery}"); + Plugin.Log(Plugin.LogSystem.Mastery, LogLevel.Info, () => $"Mastery lost on combat exit: {steamID}: {data.Aggregate(0d, (a, b) => a + b.Value.Aggregate(0d, (c, d) => c + d.Value))}"); } /// @@ -414,6 +413,7 @@ private static double ModMastery(ulong steamID, LazyDictionary Path.Combine(BasePath, ConfigFolder); public static string SavesPath => Path.Combine(BasePath, ConfigFolder, "Data"); public static string BackupsPath => Path.Combine(BasePath, ConfigFolder, SavesPath, "Backup"); + + private static Regex _folderValidation = new Regex(@"([^\w]+)"); // Config files private const string PowerUpJson = "powerUp.json"; @@ -67,6 +70,11 @@ public static class AutoSaveSystem } }; + public static string NormaliseConfigFolder(string serverName) + { + return _folderValidation.Replace("XPRising_" + serverName.Trim(), "_"); + } + private enum LoadMethod { Both,