diff --git a/Libraries/Core/Core.csproj b/Libraries/Core/Core.csproj
index b3ff2b83..f23d1684 100644
--- a/Libraries/Core/Core.csproj
+++ b/Libraries/Core/Core.csproj
@@ -7,10 +7,6 @@
Library
-
-
-
-
diff --git a/Libraries/Core/Generators/BotWeaponGenerator.cs b/Libraries/Core/Generators/BotWeaponGenerator.cs
index 7a625bda..7746a9dd 100644
--- a/Libraries/Core/Generators/BotWeaponGenerator.cs
+++ b/Libraries/Core/Generators/BotWeaponGenerator.cs
@@ -33,7 +33,7 @@ public class BotWeaponGenerator(
IEnumerable inventoryMagGenComponents
)
{
- protected List _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents);
+ protected IEnumerable _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents);
protected BotConfig _botConfig = _configServer.GetConfig();
protected PmcConfig _pmcConfig = _configServer.GetConfig();
protected RepairConfig _repairConfig = _configServer.GetConfig();
@@ -42,13 +42,8 @@ public class BotWeaponGenerator(
private static List MagGenSetUp(IEnumerable components)
{
var inventoryMagGens = components.ToList();
- inventoryMagGens.ToList()
- .Sort(
- (a, b) =>
- a.GetPriority() -
- b.GetPriority()
- );
- return inventoryMagGens.ToList();
+ inventoryMagGens.Sort((a, b) => a.GetPriority() - b.GetPriority());
+ return inventoryMagGens;
}
///
@@ -398,7 +393,7 @@ public class BotWeaponGenerator(
return;
}
-
+ var isInternalMag = magTemplate.Properties.ReloadMagType == "InternalMagazine";
var ammoTemplate = _itemHelper.GetItem(generatedWeaponResult.ChosenAmmoTemplate).Value;
if (ammoTemplate is null)
{
@@ -722,7 +717,6 @@ public class BotWeaponGenerator(
/// Weapon items list to amend
/// Magazine item details we're adding cartridges to
/// Cartridge to put into the magazine
- /// How many cartridges should go into the magazine
/// Magazines db template
protected void AddOrUpdateMagazinesChildWithAmmo(List- weaponWithMods, Item magazine, string chosenAmmoTpl, TemplateItem magazineTemplate)
{
@@ -736,8 +730,7 @@ public class BotWeaponGenerator(
}
// Create array with just magazine
- List
- magazineWithCartridges = new();
- magazineWithCartridges.AddRange(magazine);
+ List
- magazineWithCartridges = [magazine];
// Add full cartridge child items to above array
_itemHelper.FillMagazineWithCartridge(magazineWithCartridges, magazineTemplate, chosenAmmoTpl, 1);
diff --git a/Libraries/Core/Helpers/BotGeneratorHelper.cs b/Libraries/Core/Helpers/BotGeneratorHelper.cs
index 410bfc86..2da6c971 100644
--- a/Libraries/Core/Helpers/BotGeneratorHelper.cs
+++ b/Libraries/Core/Helpers/BotGeneratorHelper.cs
@@ -530,13 +530,17 @@ public class BotGeneratorHelper(
foreach (var slotGrid in value?.Properties?.Grids ?? [])
{
// Grid is empty, skip or item size is bigger than grid
- if (slotGrid.Props?.CellsH == 0 || slotGrid.Props?.CellsV == 0 || itemSize[0] * itemSize[1] > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH)
+ if (slotGrid.Props?.CellsH == 0 ||
+ slotGrid.Props?.CellsV == 0 ||
+ itemSize[0] * itemSize[1] > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH)
+ {
continue;
+ }
// Can't put item type in grid, skip all grids as we're assuming they have the same rules
if (!ItemAllowedInContainer(slotGrid, rootItemTplId))
{
- // Multiple containers, maybe next one allows item, only break out of loop for this containers grids
+ // Multiple containers, maybe next one allows item, only break out of loop for the containers grids
break;
}
@@ -548,44 +552,22 @@ public class BotGeneratorHelper(
// Get root items in container we can iterate over to find out what space is free
var containerItemsToCheck = existingContainerItems.Where(x => x.SlotId == slotGrid.Name);
- var itemsToRemove = new List
- ();
- var itemsToAdd = new List
- ();
- foreach (var item in containerItemsToCheck)
- {
- // Check item in contain for children, store for later insertion into `containerItemsToCheck`
- // (used later when figuring out how much space weapon takes up)
- var itemWithChildItems = _itemHelper.FindAndReturnChildrenAsItems(inventory.Items, item.Id);
- if (itemWithChildItems.Count <= 1) continue;
+ var containerItemsWithChildren = GetContainerItemsWithChildren(containerItemsToCheck, inventory.Items);
-
- // Store replaced item + new Child items to add later as we can't modify a collecting while looking over it
- itemsToRemove.Add(item);
- itemsToAdd.AddRange(itemsToAdd);
- }
-
- // Remove the base items flagged above
- foreach (var item in itemsToRemove)
- {
- existingContainerItems.Remove(item);
- }
-
- // Add item back with its child items
- existingContainerItems.AddRange(itemsToAdd);
-
- // Get rid of items free/used spots in current grid
if (slotGrid.Props is not null)
{
+ // Get rid of an items free/used spots in current grid
var slotGridMap = _inventoryHelper.GetContainerMap(
slotGrid.Props.CellsH.GetValueOrDefault(),
slotGrid.Props.CellsV.GetValueOrDefault(),
- existingContainerItems,
+ containerItemsWithChildren,
container.Id
);
// Try to fit item into grid
var findSlotResult = _containerHelper.FindSlotForItem(slotGridMap, itemSize[0], itemSize[1]);
- // Open slot found, add item to inventory
+ // Free slot found, add item
if (findSlotResult.Success ?? false)
{
var parentItem = itemWithChildren.FirstOrDefault((i) => i.Id == rootItemId);
@@ -633,6 +615,28 @@ public class BotGeneratorHelper(
return ItemAddedResult.NO_SPACE;
}
+ ///
+ /// Take a list of items and check if they need children + add them
+ ///
+ ///
+ ///
+ ///
+ protected List
- GetContainerItemsWithChildren(IEnumerable
- containerItems, List
- inventoryItems)
+ {
+ var result = new List
- ();
+ foreach (var item in containerItems)
+ {
+ // Check item in container for children, store for later insertion into `containerItemsToCheck`
+ // (used later when figuring out how much space weapon takes up)
+ var itemWithChildItems = _itemHelper.FindAndReturnChildrenAsItems(inventoryItems, item.Id);
+
+ // Item had children, replace existing data with item + its children
+ result.AddRange(itemWithChildItems);
+ }
+
+ return result;
+ }
+
///
/// Is the provided item allowed inside a container
///
diff --git a/Libraries/Core/Helpers/ProfileHelper.cs b/Libraries/Core/Helpers/ProfileHelper.cs
index e507e2b4..47b5a085 100644
--- a/Libraries/Core/Helpers/ProfileHelper.cs
+++ b/Libraries/Core/Helpers/ProfileHelper.cs
@@ -510,7 +510,7 @@ public class ProfileHelper(
/// True if account is developer
public bool IsDeveloperAccount(string sessionID)
{
- return GetFullProfile(sessionID)?.ProfileInfo?.Edition?.ToLower().StartsWith("spt developer") == false;
+ return GetFullProfile(sessionID)?.ProfileInfo?.Edition?.ToLower().StartsWith("spt developer") ?? false;
}
///
diff --git a/Libraries/Core/Services/CreateProfileService.cs b/Libraries/Core/Services/CreateProfileService.cs
index 09c4b116..8681ea4f 100644
--- a/Libraries/Core/Services/CreateProfileService.cs
+++ b/Libraries/Core/Services/CreateProfileService.cs
@@ -32,13 +32,16 @@ public class CreateProfileService(
SaveServer _saveServer,
EventOutputHolder _eventOutputHolder,
PlayerScavGenerator _playerScavGenerator,
- ICloner _cloner
+ ICloner _cloner,
+ MailSendService _mailSendService
)
{
public string CreateProfile(string sessionId, ProfileCreateRequestData request)
{
var account = _saveServer.GetProfile(sessionId).ProfileInfo;
- var profileTemplate = _cloner.Clone(_databaseService.GetProfiles()?.GetByJsonProp(account.Edition)?.GetByJsonProp(request.Side.ToLower()));
+ var profileTemplate = _cloner.Clone(
+ _databaseService.GetProfiles()?.GetByJsonProp(account.Edition)?.GetByJsonProp(request.Side.ToLower())
+ );
var pmcData = profileTemplate.Character;
// Delete existing profile
@@ -439,18 +442,17 @@ public class CreateProfileService(
QuestStatusEnum.Started,
sessionID,
response
- );
+ ).ToList();
- /* TODO:
- _mailSendService.sendLocalisedNpcMessageToPlayer(
- sessionID,
- this.traderHelper.getTraderById(questFromDb.traderId),
- MessageType.QUEST_START,
- messageId,
- itemRewards,
- this.timeUtil.getHoursAsSeconds(100),
- );
- */
+
+ _mailSendService.SendLocalisedNpcMessageToPlayer(
+ sessionID,
+ questFromDb.TraderId,
+ MessageType.QUEST_START,
+ messageId,
+ itemRewards,
+ _timeUtil.GetHoursAsSeconds(100)
+ );
}
}
}
diff --git a/Libraries/Core/Services/InMemoryCacheService.cs b/Libraries/Core/Services/InMemoryCacheService.cs
index 8dd02a2a..ebee155c 100644
--- a/Libraries/Core/Services/InMemoryCacheService.cs
+++ b/Libraries/Core/Services/InMemoryCacheService.cs
@@ -5,9 +5,9 @@ namespace Core.Services;
[Injectable(InjectionType.Singleton)]
public class InMemoryCacheService(
- ICloner _cloner)
+ ICloner _cloner
+)
{
-
protected Dictionary _cacheData = new();
// Store data into an in-memory object
diff --git a/Libraries/Core/Services/LegacyLocationLifecycleService.cs b/Libraries/Core/Services/LegacyLocationLifecycleService.cs
deleted file mode 100644
index aacea37e..00000000
--- a/Libraries/Core/Services/LegacyLocationLifecycleService.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using SptCommon.Annotations;
-using Core.Models.Eft.Common;
-using Core.Models.Eft.Match;
-
-namespace Core.Services;
-
-[Injectable(InjectionType.Singleton)]
-public class LegacyLocationLifecycleService
-{
- ///
- /// Handle client/match/offline/end
- ///
- public void endOfflineRaid(EndOfflineRaidRequestData info, string sessionId)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Handle when a player extracts using a car - Add rep to fence
- ///
- /// name of the extract used
- /// Player profile
- /// Session id
- protected void handleCarExtract(string extractName, PmcData pmcData, string sessionId)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Get the fence rep gain from using a car or coop extract
- ///
- /// Profile
- /// amount gained for the first extract
- /// Number of times extract was taken
- /// Fence standing after taking extract
- protected int getFenceStandingAfterExtract(PmcData pmcData, int baseGain, int extractCount)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Was extract by car
- ///
- /// name of extract
- /// true if car extract
- protected bool extractWasViaCar(string extractName)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Did player take a COOP extract
- ///
- /// Name of extract player took
- /// True if coop extract
- protected bool extractWasViaCoop(string extractName)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Handle when a player extracts using a coop extract - add rep to fence
- ///
- /// Session/player id
- /// Profile
- /// Name of extract taken
- protected void handleCoopExtract(string sessionId, PmcData pmcData, string extractName)
- {
- throw new NotImplementedException();
- }
-
- protected void sendCoopTakenFenceMessage(string sessionId)
- {
- throw new NotImplementedException();
- }
-}
diff --git a/Libraries/Core/Services/NotificationService.cs b/Libraries/Core/Services/NotificationService.cs
index 27c25554..b1c91755 100644
--- a/Libraries/Core/Services/NotificationService.cs
+++ b/Libraries/Core/Services/NotificationService.cs
@@ -8,19 +8,22 @@ public class NotificationService
{
protected Dictionary> _messageQueue = new();
- public Dictionary> GetMessageQueue()
+ public Dictionary> GetMessageQueue()
{
- throw new NotImplementedException();
+ return _messageQueue;
}
- public List
public WsNotificationEvent Pop(string sessionID)
{
- throw new NotImplementedException();
+ var result = Get(sessionID).First();
+ Get(sessionID).Remove(result);
+ return result;
}
///
diff --git a/Libraries/Core/Services/ProfileFixerService.cs b/Libraries/Core/Services/ProfileFixerService.cs
index 616f685d..a16fe39f 100644
--- a/Libraries/Core/Services/ProfileFixerService.cs
+++ b/Libraries/Core/Services/ProfileFixerService.cs
@@ -93,15 +93,6 @@ public class ProfileFixerService(
}
}
- ///
- /// Find issues in the scav profile data that may cause issues
- ///
- /// profile to check and fix
- public void CheckForAndFixScavProfileIssues(PmcData scavProfile)
- {
- return;
- }
-
///
/// Attempt to fix common item issues that corrupt profiles
///
diff --git a/Libraries/Core/Services/RaidWeatherService.cs b/Libraries/Core/Services/RaidWeatherService.cs
index 73b4e0c4..bde35e25 100644
--- a/Libraries/Core/Services/RaidWeatherService.cs
+++ b/Libraries/Core/Services/RaidWeatherService.cs
@@ -12,8 +12,6 @@ namespace Core.Services;
[Injectable(InjectionType.Singleton)]
public class RaidWeatherService(
- ISptLogger _logger,
- DatabaseService _databaseService,
TimeUtil _timeUtil,
WeatherGenerator _weatherGenerator,
SeasonalEventService _seasonalEventService,
diff --git a/Libraries/Core/Services/SeasonalEventService.cs b/Libraries/Core/Services/SeasonalEventService.cs
index 4015da54..74a92196 100644
--- a/Libraries/Core/Services/SeasonalEventService.cs
+++ b/Libraries/Core/Services/SeasonalEventService.cs
@@ -897,7 +897,21 @@ public class SeasonalEventService(
///
protected void EnableDancingTree()
{
- throw new NotImplementedException();
+ var maps = _databaseService.GetLocations();
+ List mapsToCheck = ["hideout", "base", "privatearea"];
+ foreach (KeyValuePair map in maps.GetAllPropsAsDict())
+ {
+ // Skip maps that have no tree
+ if (mapsToCheck.Contains(map.Key)) {
+ continue;
+ }
+
+ var mapData = map.Value as Location;
+ if (mapData.Base?.Events?.Khorovod?.Chance is not null) {
+ mapData.Base.Events.Khorovod.Chance = 100;
+ mapData.Base.BotLocationModifier.KhorovodChance = 100;
+ }
+ }
}
///
@@ -905,12 +919,69 @@ public class SeasonalEventService(
///
protected void AddGifterBotToMaps()
{
- throw new NotImplementedException();
+ var gifterSettings = _seasonalEventConfig.GifterSettings;
+ var maps = _databaseService.GetLocations().GetAllPropsAsDict();
+ foreach (var gifterMapSettings in gifterSettings) {
+ Location mapData = maps.FirstOrDefault(x => x.Key == gifterMapSettings.Map).Value as Location;
+ // Dont add gifter to map twice
+ if (mapData.Base.BossLocationSpawn.Any((boss) => boss.BossName == "gifter")) {
+ continue;
+ }
+
+ mapData.Base.BossLocationSpawn.Add(new BossLocationSpawn {
+ BossName = "gifter",
+ BossChance = gifterMapSettings.SpawnChance,
+ BossZone = gifterMapSettings.Zones,
+ IsBossPlayer = false,
+ BossDifficulty = "normal",
+ BossEscortType = "gifter",
+ BossEscortDifficulty = "normal",
+ BossEscortAmount = "0",
+ ForceSpawn = true,
+ SpawnMode = ["regular", "pve"],
+ Time = -1,
+ TriggerId = "",
+ TriggerName = "",
+ Delay = 0,
+ IsRandomTimeSpawn = false,
+ });
+ }
}
protected void HandleModEvent(SeasonalEvent seasonalEvent, Config globalConfig)
{
- throw new NotImplementedException();
+ if (seasonalEvent.Settings?.EnableChristmasHideout ?? false) {
+ globalConfig.EventType = globalConfig.EventType.Where((x) => x != "None").ToList();
+ globalConfig.EventType.Add("Christmas");
+ }
+
+ if (seasonalEvent.Settings?.EnableHalloweenHideout ?? false) {
+ globalConfig.EventType = globalConfig.EventType.Where((x) => x != "None").ToList();
+ globalConfig.EventType.Add("Halloween");
+ globalConfig.EventType.Add("HalloweenIllumination");
+ }
+
+ if (seasonalEvent.Settings?.AddEventGearToBots ?? false) {
+ AddEventGearToBots(seasonalEvent.Type);
+ }
+ if (seasonalEvent.Settings?.AddEventLootToBots ?? false) {
+ AddEventLootToBots(seasonalEvent.Type);
+ }
+
+ if (seasonalEvent.Settings?.EnableSummoning ?? false) {
+ EnableHalloweenSummonEvent();
+ AddEventBossesToMaps("halloweensummon");
+ }
+ if (seasonalEvent.Settings?.ZombieSettings?.Enabled ?? false) {
+ ConfigureZombies(seasonalEvent.Settings.ZombieSettings);
+ }
+ if (seasonalEvent.Settings?.ForceSeason is not null) {
+ _weatherConfig.OverrideSeason = seasonalEvent.Settings.ForceSeason;
+ }
+
+ if (seasonalEvent.Settings?.AdjustBotAppearances ?? false) {
+ AdjustBotAppearanceValues(seasonalEvent.Type);
+ }
}
///