using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.DI; using SPTarkov.Server.Core.Helpers; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Eft.Common.Tables; using SPTarkov.Server.Core.Models.Logging; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Models.Spt.Server; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils; using System.Reflection; using System.Text; using Path = System.IO.Path; namespace mcaddweapon; public record ModMetadata : AbstractModMetadata { public override string ModGuid { get; init; } = "com.mightycondor.mxlr"; public override string Name { get; init; } = "MC-MXLR"; public override string Author { get; init; } = "Mighty_Condor"; public override List? Contributors { get; init; } public override SemanticVersioning.Version Version { get; init; } = new("1.1.0"); public override SemanticVersioning.Range SptVersion { get; init; } = new("~4.0.0"); public override List? Incompatibilities { get; init; } public override Dictionary? ModDependencies { get; init; } public override string? Url { get; init; } public override bool? IsBundleMod { get; init; } = true; public override string? License { get; init; } = "MIT"; } [Injectable(TypePriority = OnLoadOrder.PostDBModLoader + 1)] public class AddWeapon( ISptLogger logger, DatabaseService databaseService, ModHelper modHelper, JsonUtil jsonUtil) : IOnLoad { public string modFolderName = "MC-MXLR"; public string modFullName = "Marlin MXLR .308 ME lever-action rifle"; public Task OnLoad() { //Trader IDs var tradersDict = new Dictionary { { "prapor", "54cb50c76803fa8b248b4571" }, { "therapist", "54cb57776803fa99248b456e" }, { "skier", "58330581ace78e27b8b10cee" }, { "peacekeeper", "5935c25fb3acc3127c3d8cd9" }, { "mechanic", "5a7c2eca46aef81a7ca2145d" }, { "ragman", "5ac3b934156ae10c4430e83c" }, { "jaeger", "5c0647fdd443bc2504c2d371" } }; logger.LogWithColor("Loading: " + modFullName, LogTextColor.White, LogBackgroundColor.Magenta); //Get the server database and custom database var db = databaseService.GetTables(); var mydb = loadDb(); //logger.Info(modFolderName + ": Databases loaded successfully."); //Locales addLocales(mydb, db); //logger.Info(modFolderName + ": Locales loaded successfully."); //Items foreach (var item in mydb.Templates.Items) { db.Templates.Items[item.Key] = item.Value; } //logger.Info(modFolderName + ": Items loaded successfully."); //Handbook & Flea Prices foreach (var item in mydb.Templates.Handbook.Items) { db.Templates.Handbook.Items.Add(item); //db.Templates.Prices[item.Id] = ((Double)item.Price); } //logger.Info(modFolderName + ": Handbook loaded successfully."); //Presets foreach (var preset in mydb.Globals.ItemPresets) { db.Globals.ItemPresets[preset.Key] = preset.Value; } //logger.Info(modFolderName + ": Presets loaded successfully."); //Traders foreach (var traderID in tradersDict.Values) { addTraderAssort(traderID, mydb, db); } //logger.Info(modFolderName + ": Traders loaded successfully."); //Mod Compatibility/Conflicts //logger.Info(modFolderName + ": Mod compats and conflicts loaded successfully."); //Mastery var newMastering = db.Globals.Configuration.Mastering.ToList(); foreach (var weapon in mydb.Globals.config.Mastering) { newMastering.Add(weapon); } db.Globals.Configuration.Mastering = newMastering.ToArray(); //logger.Info(modFolderName + ": Mastery loaded successfully."); //Add lever-action to Shooter Born foreach (var location in db.Templates.Quests["5c0bde0986f77479cf22c2f8"].Conditions.AvailableForFinish) { if (location.ConditionType == "CounterCreator") { foreach (var condition in location.Counter.Conditions) { if (condition.ConditionType == "Kills") condition.Weapon.Add("67c6de3ce39861860909e8e5"); } } } //logger.Info(modFolderName + ": MXLR added to Shooter Born in Heaven."); // Inform server we have finished return Task.CompletedTask; } private CustomDatabaseTables loadDb() { //Mod path var pathToMod = modHelper.GetAbsolutePathToModFolder(Assembly.GetExecutingAssembly()); //Load Items string itemsPath = Path.Combine(pathToMod, "database", "templates", "items.json"); string itemsString = File.ReadAllText(itemsPath); Dictionary Items = jsonUtil.Deserialize>(itemsString); //Load Handbook string handbookPath = Path.Combine(pathToMod, "database", "templates", "handbook.json"); string handbookString = File.ReadAllText(handbookPath); CustomHandbookBase Handbook = jsonUtil.Deserialize(handbookString); //Combine Items and Handbook into Templates object CustomTemplates Templates = new CustomTemplates() { Items = Items, Handbook = Handbook }; //Load Locales var Global = new Dictionary>(); foreach (string filepath in Directory.EnumerateFiles(Path.Combine(pathToMod, "database", "locales", "global"))) { string localeString = File.ReadAllText(filepath); string localeName = Path.GetFileNameWithoutExtension(filepath); Dictionary locale = jsonUtil.Deserialize>(localeString); Global.Add(localeName, locale); } CustomLocaleBase Locales = new CustomLocaleBase() { Global = Global }; //Load Traders var Traders = new Dictionary(); foreach (string directorypath in Directory.EnumerateDirectories(Path.Combine(pathToMod, "database", "traders"))) { string traderAssortString = File.ReadAllText(Path.Combine(directorypath, "assort.json")); string traderID = Path.GetFileName(directorypath); TraderAssort Assort = jsonUtil.Deserialize(traderAssortString); CustomTrader trader = new CustomTrader() { Assort = Assort }; Traders.Add(traderID, trader); } //Load globals string globalsPath = Path.Combine(pathToMod, "database", "globals.json"); string jsonString = File.ReadAllText(globalsPath); CustomGlobals Globals = jsonUtil.Deserialize(jsonString); CustomDatabaseTables mydb = new CustomDatabaseTables() { Locales = Locales, Templates = Templates, Traders = Traders, Globals = Globals, }; return mydb; } private void addTraderAssort(string traderID, CustomDatabaseTables mydb, DatabaseTables db) { //Items foreach (var item in mydb.Traders[traderID].Assort.Items) { db.Traders[traderID].Assort.Items.Add(item); } //Barter Scheme foreach (var item in mydb.Traders[traderID].Assort.BarterScheme) { db.Traders[traderID].Assort.BarterScheme[item.Key] = item.Value; } //Loyalty Levels foreach (var item in mydb.Traders[traderID].Assort.LoyalLevelItems) { db.Traders[traderID].Assort.LoyalLevelItems[item.Key] = item.Value; } } private void addLocales(CustomDatabaseTables mydb, DatabaseTables db) { var locales = db.Locales.Global; var localesToAdd = mydb.Locales.Global; foreach (var (localeName, localeDict) in locales) { //If the locale is included in the mod, add it if (mydb.Locales.Global.ContainsKey(localeName)) { foreach (var entry in localesToAdd[localeName]) { localeDict.AddTransformer(lazyloadedLocaleData => { lazyloadedLocaleData.Add(entry.Key, entry.Value); return lazyloadedLocaleData; }); } } } } private void addItemCompatibilities() { } private void addItemConflicts() { } } public record CustomDatabaseTables { public virtual required CustomLocaleBase Locales { get; init; } public virtual required CustomTemplates Templates { get; init; } public virtual required Dictionary Traders { get; init; } public virtual required CustomGlobals Globals { get; init; } } public record CustomLocaleBase { public virtual required Dictionary> Global { get; init; } } public record CustomGlobal { public virtual required Dictionary en { get; init; } public virtual Dictionary ru { get; init; } } public record CustomTemplates { public virtual required Dictionary Items { get; init; } public virtual required CustomHandbookBase Handbook { get; init; } } public record CustomTrader { public virtual required TraderAssort Assort { get; set; } } public record CustomGlobals { public virtual required Dictionary ItemPresets { get; init; } public virtual required CustomConfig config { get; init; } } public record CustomConfig { public virtual required Mastering[] Mastering { get; set; } } public record CustomHandbookBase { public virtual required List Items { get; init; } }