diff --git a/ExampleMods/Mods/EditConfigs.cs b/ExampleMods/Mods/EditConfigs.cs new file mode 100644 index 00000000..a5f1e9bd --- /dev/null +++ b/ExampleMods/Mods/EditConfigs.cs @@ -0,0 +1,76 @@ +using Core.Annotations; +using Core.Models.Enums; +using Core.Models.Spt.Config; +using Core.Servers; + +namespace ExampleMods.Mods +{ + [Injectable] + public class EditConfigs + { + private readonly ConfigServer _configServer; + private readonly BotConfig _botConfig; + private readonly HideoutConfig _hideoutConfig; + private readonly WeatherConfig _weatherConfig; + private readonly AirdropConfig _airdropConfig; + private readonly PmcChatResponse _pmcChatResponseConfig; + private readonly QuestConfig _questConfig; + private readonly PmcConfig _pmcConfig; + + // We access configs via ConfigServer + public EditConfigs( + ConfigServer configServer) + { + _configServer = configServer; + + // We get the bot config by calling GetConfig and passing the configs 'type' within the diamond brackets + _botConfig = _configServer.GetConfig(); + _hideoutConfig = _configServer.GetConfig(); + _weatherConfig = _configServer.GetConfig(); + _airdropConfig = _configServer.GetConfig(); + _pmcChatResponseConfig = _configServer.GetConfig(); + _questConfig = _configServer.GetConfig(); + _pmcConfig = _configServer.GetConfig(); + + Run(); + } + + public void Run() + { + // Let's edit the weather config to make the season winter + _weatherConfig.OverrideSeason = Season.WINTER; + + // Let's edit the hideout config to Make all crafts take 60 seconds + _hideoutConfig.OverrideCraftTimeSeconds = 60; + + // Let's edit the hideout config to Make all upgrades take 60 seconds + _hideoutConfig.OverrideBuildTimeSeconds = 60; + + // Let's edit the airdrop config to Make weapon/armor drops really common + _airdropConfig.AirdropTypeWeightings[SptAirdropTypeEnum.weaponArmor] = 999; + + // Let's edit the airdrop config to Make weapon/armor drops always have 3 sealed weapon crates + var weaponCrateMinMax = _airdropConfig.Loot["weaponArmor"].WeaponCrateCount; + weaponCrateMinMax.Min = 3; + weaponCrateMinMax.Max = 3; + + // Let's make PMCs always mail you when they kill you + _pmcChatResponseConfig.Killer.ResponseChancePercent = 100; + + // Let's make quest rewards sent to you via mail last for over a week if you have an unheard profile + _questConfig.MailRedeemTimeHours["unheard_edition"] = 168; + + // Let's make the interchange bot cap huge + _botConfig.MaxBotCap["interchange"] = 50; + + // Let's disable loot on scavs + _botConfig.DisableLootOnBotTypes.Add("assault"); + + // Let's make the conversion rate of scavs to pmcs 100% on factory day + var factory4DayConversionSettings = _pmcConfig.ConvertIntoPmcChance["factory4_day"]; + var assaultConversionSettings = factory4DayConversionSettings["assault"]; + assaultConversionSettings.Min = 100; + assaultConversionSettings.Max = 100; + } + } +} diff --git a/ExampleMods/Mods/EditDatabaseValues.cs b/ExampleMods/Mods/EditDatabaseValues.cs new file mode 100644 index 00000000..a2c86d46 --- /dev/null +++ b/ExampleMods/Mods/EditDatabaseValues.cs @@ -0,0 +1,200 @@ +using Core.Annotations; +using Core.Models.Eft.Hideout; +using Core.Models.Enums; +using Core.Models.Utils; +using Core.Services; + +namespace ExampleMods.Mods +{ + [Injectable] + public class EditDatabaseValues + { + private readonly DatabaseService _databaseService; + + public EditDatabaseValues( + DatabaseService databaseService) + { + _databaseService = databaseService; + + Run(); + } + + public void Run() + { + // When SPT starts, it stores all the data found in (SPT_Data\Server\database) in memory + // We can use the '_databaseService' we injected to access this data, this includes files from EFT and SPT + + // Lets edit some globals settings to make the game easier + EditGlobals(); + + // Lets edit the BTR to have the christmas tarcola skin + EditBtr(); + + // Let's edit the hideout so it's easier to upgrade the lavatory + EditHideout(); + + // Lets edit the default scav to + EditScavSettings(); + + // Lets edit Customs + EditCustoms(); + } + + private void EditGlobals() + { + // Let's edit settings in the GLOBALS file (database/globals.json) + var globals = _databaseService.GetGlobals(); + + // Let's edit the scav cooldown to be 1 second + globals.Configuration.SavagePlayCooldown = 1; + + + // Now lets try editing the ragfair unlock level, lets get the ragfair settings first + var ragfairSettings = globals.Configuration.RagFair; + + // Lets set the level you need to be to access flea to be 1 + ragfairSettings.MinUserLevel = 1; + + + // Now lets increase the number of offers you can have listed at one time + // The max is stored in a list, different flea ratings give different offer amounts + + // We loop over all the settings, setting all of them to be 20 + foreach (var offerCountSettings in ragfairSettings.MaxActiveOfferCount) + { + offerCountSettings.Count = 20; + } + } + + private void EditBtr() + { + // BTR setting can be found in the GLOBALS file too + var globals = _databaseService.GetGlobals(); + + // We get the BTR settings from globals first + var btrSettings = globals.Configuration.BTRSettings; + + // Let's get the settings for woods specifically, we use 'tryGetValue' for this, the settings will be stored in 'woodsBtrSettings' + btrSettings.MapsConfigs.TryGetValue("Woods", out var woodsBtrSettings); + + // Lets set the BTR to use the christmas skin + woodsBtrSettings.BtrSkin = "Tarcola"; + } + + private void EditHideout() + { + // Hideout data can be found in (SPT_Data\Server\database\hideout) + Core.Models.Spt.Hideout.Hideout hideout = _databaseService.GetHideout(); + + // We want the areas, they're stored in a list + List? hideoutAreas = hideout.Areas; + + // We find the toilet, we use 'firstOrDefault', if we cant find the lavatory, 'lavatoryArea' will be null + HideoutArea? lavatoryArea = hideoutAreas.FirstOrDefault(area => area.Type == HideoutAreas.LAVATORY); + + + + // Now we have the toilet, we can find the requirements to craft, all data is stored by stage + var toiletStages = lavatoryArea.Stages; + + // Stages are stored in a dictionary, a dictionary has a 'key' and a 'value' + // In this case, the 'key' is the upgrade stage, e.g. "1", or "2" + // We reference to each stage as a 'stageKvP' this means 'Key value Pair', every key has a value (key = stage number, value = data for that stage) + foreach (var stageKvP in toiletStages) + { + // while we're here, we can make the stages craft really fast (60 seconds) + stageKvP.Value.ConstructionTime = 60; + + // Let's get the stage requirements, they're a list + var stageRequirements = stageKvP.Value.Requirements; + + // We empty the requirements out, now it can be built straight away + stageRequirements.Clear(); + } + } + + private void EditScavSettings() + { + var bots = _databaseService.GetBots(); + + // Same as the above example, we use 'TryGetValue' to get the 'assault' bot (assault is the internal name for scavs) + bots.Types.TryGetValue("assault", out var assaultBot); + + // Let's make the chance to get a good backpack really high + assaultBot.BotInventory.Equipment.TryGetValue(EquipmentSlots.Backpack, out Dictionary backPacks); + + // We access the backpacks dictionary by key directly using square brackets, we use ItemTpl to get the items ID + // Alternately, we could have typed backPacks["59e763f286f7742ee57895da"] and done the same thing, ItemTpl makes it easier to read + backPacks[ItemTpl.BACKPACK_PILGRIM_TOURIST] = 999999; + + + + + // Now lets make them always have an M4A1 + assaultBot.BotInventory.Equipment.TryGetValue(EquipmentSlots.FirstPrimaryWeapon, out Dictionary primaryWeapons); + + // We edit the weight value (pick chance) that is already there to be massive, making the item more likely to be picked + primaryWeapons[ItemTpl.ASSAULTRIFLE_COLT_M4A1_556X45_ASSAULT_RIFLE] = 999999; + + + + + // Now lets make them always have the first name of Gary + // We start by removing all the existing names + assaultBot.FirstNames.Clear(); + + // We add the new name Gary, very menacing + assaultBot.FirstNames.Add("Gary"); + } + + private void EditCustoms() + { + // Let's get all the maps (called locations) + var locations = _databaseService.GetLocations(); + + // Customs is called 'bigmap' in eft + var customs = locations.Bigmap; + + // Lets get the exits and make them all 100% chance to appear + var exits = customs.Base.Exits; + + // They're stored as a list so we can loop over them + foreach (var exit in exits) + { + // I can't remember which one is used, you'd assume ChancePVE is used in pve, but this is BSG we're dealing with + // So we set both + exit.Chance = 100; + exit.ChancePVE = 100; + } + + + + // Lets try editing the airdrops on customs to be better + var airdropSettings = customs.Base.AirdropParameters; + + // They're stored in an array but there's only one bunch of settings, it means we have to get the first item from the list, + // An alternate way to access the first item is done by using square brackets with the 'index' of the item we want, + // indexes start at 0 so we want to type "[0]" to access the first item in the list, + var actualAirdropSettings = airdropSettings.First(); + + // Make it spawn 100% + actualAirdropSettings.PlaneAirdropChance = 1; // Number between 0 and 1 + + // Make it spawn as early as start of raid + actualAirdropSettings.PlaneAirdropStartMin = 1; + + + + // Let's make bosses spawn 100% of the time + + // We get all the bosses, they're stored in a list + var bosses = customs.Base.BossLocationSpawn; + + // Let's get Reshala, we use "FirstOrDefault" and look for the first boss with the name "bossBully" + var reshala = bosses.FirstOrDefault(boss => boss.BossName == "bossBully"); + + // Set him to 100% + reshala.BossChance = 100; + } + } +} diff --git a/ExampleMods/Mods/Logging.cs b/ExampleMods/Mods/Logging.cs new file mode 100644 index 00000000..5ecd1763 --- /dev/null +++ b/ExampleMods/Mods/Logging.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Core.Annotations; +using Core.Models.Logging; +using Core.Models.Utils; + +namespace ExampleMods.Mods +{ + [Injectable] + public class Logging + { + private readonly ISptLogger _logger; + + // Constructor - Inject a 'ISptLogger' with your mods Class in the diamond brackets + public Logging( + ISptLogger logger) + { + // Save the logger we're injecting into a private variable that is scoped to this class (only this class has access to it) + _logger = logger; + + // Not 100% necessary but let's split our code out into a method to make it easier to read + Run(); + } + + public void Run() + { + // We can access the logger to assigned in the constructor here + _logger.Success("This is a success message"); + _logger.Warning("This is a warning message"); + _logger.Error("This is an error message"); + _logger.Info("This is an info message"); + _logger.Critical("this is a critical message"); + + // Logging with colors requires you to 'pass' the text color and background color + _logger.LogWithColor("This is a message with custom colors", LogTextColor.Red, LogBackgroundColor.Black); + _logger.Debug("This is a debug message that gets written to the log file, not the console"); + } + } +} diff --git a/ExampleMods/Mods/Override/WatermarkOverride.cs b/ExampleMods/Mods/Override/WatermarkOverride.cs index 848f4768..45c92ea6 100644 --- a/ExampleMods/Mods/Override/WatermarkOverride.cs +++ b/ExampleMods/Mods/Override/WatermarkOverride.cs @@ -16,7 +16,7 @@ public class WatermarkOverride( { public override void Initialize() { - Console.WriteLine("This is a watermark mod override!"); + _logger.Success("This is a watermark mod override!"); base.Initialize(); }