namespace Aeshnidae.Healing;
///
/// Heals that keep up with the vital they heal (Tom, 2026-09-29: "Can we flip all this stuff to be
/// percentage based ... If health ever gets into the thousands those healing spells become useless";
/// "Let's not touch harm yet. But definitely healing/stam kits/spells").
///
/// Every heal this covers is its retail amount times max(1, the target's maximum of that vital /
/// the reference for it) - "retail or a percentage, whichever is larger". At or below the reference
/// nothing changes from retail; above it, the heal grows with the vital, so the same kit or spell
/// always restores the same share of it. The references sit just above a fully buffed level-275
/// character (live shard, 2026-09-29: Endurance 250, Self 200-290, 196 ranks in each vital - about
/// 350-420 health, ~500 stamina, ~550 mana), so every character playing today heals exactly as in
/// retail; the heal only grows once a pool passes that. `/healing` lists every online player's pools.
///
/// Enabled the switch; off = every heal is retail
/// ReferenceHealth the maximum health at which a heal is its retail amount
/// ReferenceStamina the same for stamina (kits and Revitalize)
/// ReferenceMana the same for mana, if ScaleMana
/// ScaleKits healing and stamina kits (Healer): the amount, and the success check
/// measured against the scaled-down missing vital so the odds stay retail
/// ScaleSpells Heal / Revitalize spells (positive Boost spells); harm and drain never
/// ScaleMana mana kits and Mana Boost spells too (Tom asked health and stamina)
/// ScaleMonsterHeals heals landing on a monster or NPC, whoever casts them - off: tier-scaled
/// monsters keep retail self-heals, and a player healing a monster heals it retail
/// MaxFactor the most a heal is ever multiplied by; 0 = no limit
///
public class Settings
{
public const string FileName = "Settings.json";
public bool Enabled { get; set; } = true;
public double ReferenceHealth { get; set; } = 400;
public double ReferenceStamina { get; set; } = 500;
public double ReferenceMana { get; set; } = 500;
public bool ScaleKits { get; set; } = true;
public bool ScaleSpells { get; set; } = true;
public bool ScaleMana { get; set; }
public bool ScaleMonsterHeals { get; set; }
public double MaxFactor { get; set; }
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true,
};
public static Settings Load(string modPath)
{
var path = Path.Combine(modPath, FileName);
try
{
if (File.Exists(path))
return JsonSerializer.Deserialize(File.ReadAllText(path), JsonOptions) ?? new Settings();
var defaults = new Settings();
defaults.Save(modPath);
ModManager.Log($"[{Mod.Name}] wrote default settings to {path}");
return defaults;
}
catch (Exception ex)
{
ModManager.Log($"[{Mod.Name}] could not read {path}, using defaults: {ex.Message}", ModManager.LogLevel.Warn);
return new Settings();
}
}
public void Save(string modPath)
{
try
{
File.WriteAllText(Path.Combine(modPath, FileName), JsonSerializer.Serialize(this, JsonOptions));
}
catch (Exception ex)
{
ModManager.Log($"[{Mod.Name}] could not save settings: {ex.Message}", ModManager.LogLevel.Error);
}
}
}