.NET Format Style Fixes

This commit is contained in:
refringe
2025-06-18 17:09:20 +00:00
committed by Format Bot
parent ca0a7d6345
commit 6e01428b2b
774 changed files with 23507 additions and 40003 deletions
@@ -23,10 +23,7 @@ public class AchievementController(
/// <returns></returns>
public virtual GetAchievementsResponse GetAchievements(string sessionID)
{
return new GetAchievementsResponse
{
Elements = databaseService.GetAchievements()
};
return new GetAchievementsResponse { Elements = databaseService.GetAchievements() };
}
/// <summary>
@@ -37,12 +34,21 @@ public class AchievementController(
public virtual CompletedAchievementsResponse GetAchievementStatics(string sessionId)
{
var stats = new Dictionary<string, int>();
var profiles = profileHelper.GetProfiles()
.Where(kvp => !coreConfig.Features.AchievementProfileIdBlacklist.Contains(kvp.Value.ProfileInfo.ProfileId))
var profiles = profileHelper
.GetProfiles()
.Where(kvp =>
!coreConfig.Features.AchievementProfileIdBlacklist.Contains(
kvp.Value.ProfileInfo.ProfileId
)
)
.ToDictionary();
var achievements = databaseService.GetAchievements();
foreach (var achievementId in achievements.Select(achievement => achievement.Id).Where(achievementId => !string.IsNullOrEmpty(achievementId)))
foreach (
var achievementId in achievements
.Select(achievement => achievement.Id)
.Where(achievementId => !string.IsNullOrEmpty(achievementId))
)
{
var profilesHaveAchievement = 0;
foreach (var (profileId, profile) in profiles)
@@ -63,15 +69,13 @@ public class AchievementController(
var percentage = 0;
if (profiles.Count > 0)
{
percentage = (int)Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
percentage = (int)
Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
}
stats.Add(achievementId, percentage);
}
return new CompletedAchievementsResponse
{
Elements = stats
};
return new CompletedAchievementsResponse { Elements = stats };
}
}
@@ -1,7 +1,7 @@
using System.Diagnostics;
using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Constants;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Constants;
using SPTarkov.Server.Core.Generators;
using SPTarkov.Server.Core.Helpers;
using SPTarkov.Server.Core.Models.Common;
@@ -50,7 +50,9 @@ public class BotController(
{
if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
{
_logger.Warning(_localisationService.GetText("bot-bot_preset_count_value_missing", type));
_logger.Warning(
_localisationService.GetText("bot-bot_preset_count_value_missing", type)
);
return 10;
}
@@ -78,23 +80,38 @@ public class BotController(
/// <param name="raidConfig">OPTIONAL - applicationContext Data stored at start of raid</param>
/// <param name="ignoreRaidSettings">OPTIONAL - should raid settings chosen pre-raid be ignored</param>
/// <returns>Difficulty object</returns>
public DifficultyCategories GetBotDifficulty(string sessionId, string type, string diffLevel, bool ignoreRaidSettings = false)
public DifficultyCategories GetBotDifficulty(
string sessionId,
string type,
string diffLevel,
bool ignoreRaidSettings = false
)
{
var difficulty = diffLevel.ToLower();
var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
var raidConfig = _profileActivityService
.GetProfileActivityRaidData(sessionId)
?.RaidConfiguration;
if (!(raidConfig != null || ignoreRaidSettings))
{
_logger.Error(_localisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION"));
_logger.Error(
_localisationService.GetText(
"bot-missing_application_context",
"RAID_CONFIGURATION"
)
);
}
// Check value chosen in pre-raid difficulty dropdown
// If value is not 'asonline', change requested difficulty to be what was chosen in dropdown
var botDifficultyDropDownValue = raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLower() ?? "asonline";
var botDifficultyDropDownValue =
raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLower() ?? "asonline";
if (botDifficultyDropDownValue != "asonline")
{
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(
botDifficultyDropDownValue
);
}
var botDb = _databaseService.GetBots();
@@ -130,7 +147,9 @@ public class BotController(
result[botTypeLower] = result[Roles.Assault];
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Unable to find bot: {botTypeLower} in db, copying '{Roles.Assault}'");
_logger.Debug(
$"Unable to find bot: {botTypeLower} in db, copying '{Roles.Assault}'"
);
}
continue;
@@ -139,7 +158,9 @@ public class BotController(
if (botDetails?.BotDifficulty is null)
{
// Bot has no difficulty values, skip
_logger.Warning($"Unable to find bot: {botTypeLower} difficulty values in db, skipping");
_logger.Warning(
$"Unable to find bot: {botTypeLower} difficulty values in db, skipping"
);
continue;
}
@@ -153,7 +174,11 @@ public class BotController(
}
// Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/impossible
result[botNameKey].Add(difficultyName, GetBotDifficulty(string.Empty, botNameKey, difficultyName, true));
result[botNameKey]
.Add(
difficultyName,
GetBotDifficulty(string.Empty, botNameKey, difficultyName, true)
);
}
}
@@ -180,7 +205,11 @@ public class BotController(
/// <param name="pmcProfile">Player generating bots</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>List of generated bots</returns>
protected List<BotBase> GenerateBotWaves(GenerateBotsRequestData request, PmcData? pmcProfile, string sessionId)
protected List<BotBase> GenerateBotWaves(
GenerateBotsRequestData request,
PmcData? pmcProfile,
string sessionId
)
{
var generatedBotList = new List<BotBase>();
var raidSettings = GetMostRecentRaidSettings(sessionId);
@@ -191,23 +220,36 @@ public class BotController(
var stopwatch = Stopwatch.StartNew();
// Map conditions to promises for bot generation
Task.WaitAll((request.Conditions ?? [])
.Select(condition => Task.Factory.StartNew(() =>
{
var botWaveGenerationDetails = GetBotGenerationDetailsForWave(
condition,
pmcProfile,
allPmcsHaveSameNameAsPlayer,
raidSettings);
Task.WaitAll(
(request.Conditions ?? [])
.Select(condition =>
Task.Factory.StartNew(() =>
{
var botWaveGenerationDetails = GetBotGenerationDetailsForWave(
condition,
pmcProfile,
allPmcsHaveSameNameAsPlayer,
raidSettings
);
GenerateBotWave(condition, botWaveGenerationDetails, generatedBotList, sessionId);
})).ToArray());
GenerateBotWave(
condition,
botWaveGenerationDetails,
generatedBotList,
sessionId
);
})
)
.ToArray()
);
stopwatch.Stop();
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
_logger.Debug(
$"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()"
);
}
return generatedBotList;
@@ -225,9 +267,13 @@ public class BotController(
GenerateCondition generateRequest,
BotGenerationDetails botGenerationDetails,
List<BotBase> botList,
string sessionId)
string sessionId
)
{
var isEventBot = generateRequest.Role?.Contains("event", StringComparison.OrdinalIgnoreCase);
var isEventBot = generateRequest.Role?.Contains(
"event",
StringComparison.OrdinalIgnoreCase
);
if (isEventBot.GetValueOrDefault(false))
{
// Add eventRole data + reassign role property to be base type
@@ -241,45 +287,55 @@ public class BotController(
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}");
_logger.Debug(
$"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}"
);
}
Parallel.For(0, botGenerationDetails.BotCountToGenerate.Value, (i) =>
{
BotBase bot = null;
try
Parallel.For(
0,
botGenerationDetails.BotCountToGenerate.Value,
(i) =>
{
bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(botGenerationDetails));
}
catch (Exception e)
{
_logger.Error(
$"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}");
return;
}
BotBase bot = null;
// The client expects the Side for PMCs to be `Savage`
// We do this here so it's after we cache the bot in the match details lookup, as when you die, they will have the right side
if (bot.Info.Side is Sides.Bear or Sides.Usec)
{
bot.Info.Side = Sides.Savage;
}
try
{
bot = _botGenerator.PrepareAndGenerateBot(
sessionId,
_cloner.Clone(botGenerationDetails)
);
}
catch (Exception e)
{
_logger.Error(
$"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}"
);
return;
}
lock (_botListLock)
{
botList.Add(bot);
}
// The client expects the Side for PMCs to be `Savage`
// We do this here so it's after we cache the bot in the match details lookup, as when you die, they will have the right side
if (bot.Info.Side is Sides.Bear or Sides.Usec)
{
bot.Info.Side = Sides.Savage;
}
// Store bot details in cache so post-raid PMC messages can use data
_matchBotDetailsCacheService.CacheBot(bot);
});
lock (_botListLock)
{
botList.Add(bot);
}
// Store bot details in cache so post-raid PMC messages can use data
_matchBotDetailsCacheService.CacheBot(bot);
}
);
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
$"Generated: {botGenerationDetails.BotCountToGenerate} {botGenerationDetails.Role}" +
$"({botGenerationDetails.EventRole ?? botGenerationDetails.Role ?? ""}) {botGenerationDetails.BotDifficulty} bots"
$"Generated: {botGenerationDetails.BotCountToGenerate} {botGenerationDetails.Role}"
+ $"({botGenerationDetails.EventRole ?? botGenerationDetails.Role ?? ""}) {botGenerationDetails.BotDifficulty} bots"
);
}
}
@@ -290,11 +346,15 @@ public class BotController(
/// <returns>GetRaidConfigurationRequestData if it exists</returns>
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(string sessionId)
{
var raidConfiguration = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
var raidConfiguration = _profileActivityService
.GetProfileActivityRaidData(sessionId)
?.RaidConfiguration;
if (raidConfiguration is null)
{
_logger.Warning(_localisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext"));
_logger.Warning(
_localisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext")
);
}
return raidConfiguration;
@@ -307,7 +367,10 @@ public class BotController(
/// <returns>MinMax values</returns>
protected MinMax<int> GetPmcLevelRangeForMap(string? location)
{
return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(location?.ToLower() ?? "", null);
return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(
location?.ToLower() ?? "",
null
);
}
/// <summary>
@@ -322,24 +385,30 @@ public class BotController(
GenerateCondition condition,
PmcData? pmcProfile,
bool allPmcsHaveSameNameAsPlayer,
GetRaidConfigurationRequestData? raidSettings)
GetRaidConfigurationRequestData? raidSettings
)
{
var generateAsPmc = _botHelper.IsBotPmc(condition.Role);
return new BotGenerationDetails
{
IsPmc = generateAsPmc,
Side = generateAsPmc ? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty) : "Savage",
Side = generateAsPmc
? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty)
: "Savage",
Role = condition.Role,
PlayerLevel = pmcProfile?.Info?.Level ?? 1,
PlayerName = pmcProfile?.Info?.Nickname,
BotRelativeLevelDeltaMax = _pmcConfig.BotRelativeLevelDeltaMax,
BotRelativeLevelDeltaMin = _pmcConfig.BotRelativeLevelDeltaMin,
BotCountToGenerate = Math.Max(GetBotPresetGenerationLimit(condition.Role), condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
BotCountToGenerate = Math.Max(
GetBotPresetGenerationLimit(condition.Role),
condition.Limit
), // Choose largest between value passed in from request vs what's in bot.config
BotDifficulty = condition.Difficulty,
LocationSpecificPmcLevelOverride = GetPmcLevelRangeForMap(raidSettings?.Location), // Min/max levels for PMCs to generate within
IsPlayerScav = false,
AllPmcsHaveSameNameAsPlayer = allPmcsHaveSameNameAsPlayer
AllPmcsHaveSameNameAsPlayer = allPmcsHaveSameNameAsPlayer,
};
}
@@ -359,7 +428,10 @@ public class BotController(
if (location == "default")
{
_logger.Warning(
_localisationService.GetText("bot-no_bot_cap_found_for_location", location.ToLower())
_localisationService.GetText(
"bot-no_bot_cap_found_for_location",
location.ToLower()
)
);
}
@@ -376,7 +448,7 @@ public class BotController(
{
PmcType = _pmcConfig.PmcType,
Assault = _botConfig.AssaultBrainType,
PlayerScav = _botConfig.PlayerScavBrainType
PlayerScav = _botConfig.PlayerScavBrainType,
};
}
}
@@ -384,23 +456,11 @@ public class BotController(
public record AiBotBrainTypes
{
[JsonPropertyName("pmc")]
public Dictionary<string, Dictionary<string, Dictionary<string, double>>> PmcType
{
get;
set;
}
public Dictionary<string, Dictionary<string, Dictionary<string, double>>> PmcType { get; set; }
[JsonPropertyName("assault")]
public Dictionary<string, Dictionary<string, int>> Assault
{
get;
set;
}
public Dictionary<string, Dictionary<string, int>> Assault { get; set; }
[JsonPropertyName("playerScav")]
public Dictionary<string, Dictionary<string, int>> PlayerScav
{
get;
set;
}
public Dictionary<string, Dictionary<string, int>> PlayerScav { get; set; }
}
@@ -42,30 +42,37 @@ public class BuildController(
{
EquipmentBuilds = [],
WeaponBuilds = [],
MagazineBuilds = []
MagazineBuilds = [],
};
}
// Ensure the secure container in the default presets match what the player has equipped
var defaultEquipmentPresetsClone = _cloner.Clone(_databaseService.GetTemplates().DefaultEquipmentPresets)
var defaultEquipmentPresetsClone = _cloner
.Clone(_databaseService.GetTemplates().DefaultEquipmentPresets)
.ToList();
// Get players secure container
var playerSecureContainer = profile?.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId
);
var playerSecureContainer =
profile?.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x =>
x.SlotId == secureContainerSlotId
);
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone?
.FirstOrDefault()
?.Items?
.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone
?.FirstOrDefault()
?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
if (playerSecureContainer is not null && playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template)
// Default equipment presets' secure container tpl doesn't match players secure container tpl
if (
playerSecureContainer is not null
&& playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template
)
// Default equipment presets' secure container tpl doesn't match players secure container tpl
{
foreach (var defaultPreset in defaultEquipmentPresetsClone)
{
// Find presets secure container
var secureContainer = defaultPreset.Items?.FirstOrDefault(item => item.SlotId == secureContainerSlotId);
var secureContainer = defaultPreset.Items?.FirstOrDefault(item =>
item.SlotId == secureContainerSlotId
);
if (secureContainer is not null)
{
secureContainer.Template = playerSecureContainer.Template;
@@ -102,7 +109,7 @@ public class BuildController(
Id = body.Id,
Name = body.Name,
Root = body.Root,
Items = body.Items
Items = body.Items,
};
var profile = _profileHelper.GetFullProfile(sessionId);
@@ -132,8 +139,9 @@ public class BuildController(
var profile = _profileHelper.GetFullProfile(sessionID);
var pmcData = profile.CharacterData.PmcData;
var existingSavedEquipmentBuilds =
_saveServer.GetProfile(sessionID).UserBuildData.EquipmentBuilds;
var existingSavedEquipmentBuilds = _saveServer
.GetProfile(sessionID)
.UserBuildData.EquipmentBuilds;
// Replace duplicate ID's. The first item is the base item.
// Root ID and the base item ID need to match.
@@ -145,10 +153,11 @@ public class BuildController(
Name = request.Name,
BuildType = EquipmentBuildType.Custom,
Root = request.Items[0].Id,
Items = request.Items
Items = request.Items,
};
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build => build.Name == request.Name || build.Id == request.Id
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build =>
build.Name == request.Name || build.Id == request.Id
);
if (existingBuild is not null)
{
@@ -190,7 +199,7 @@ public class BuildController(
Caliber = request.Caliber,
TopCount = request.TopCount,
BottomCount = request.BottomCount,
Items = request.Items
Items = request.Items,
};
var profile = _profileHelper.GetFullProfile(sessionId);
@@ -198,7 +207,9 @@ public class BuildController(
profile.UserBuildData.MagazineBuilds ??= [];
// Check if template with desired name already exists and remove it
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item => item.Name == request.Name);
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item =>
item.Name == request.Name
);
if (magazineBuildToRemove is not null)
{
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
@@ -222,7 +233,9 @@ public class BuildController(
var magazineBuilds = profile.UserBuildData.MagazineBuilds;
// Check for id in weapon array first
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild => weaponBuild.Id == idToRemove);
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild =>
weaponBuild.Id == idToRemove
);
if (matchingWeaponBuild is not null)
{
weaponBuilds.Remove(matchingWeaponBuild);
@@ -231,7 +244,9 @@ public class BuildController(
}
// Id not found in weapons, try equipment
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild => equipmentBuild.Id == idToRemove);
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild =>
equipmentBuild.Id == idToRemove
);
if (matchingEquipmentBuild is not null)
{
equipmentBuilds.Remove(matchingEquipmentBuild);
@@ -240,7 +255,9 @@ public class BuildController(
}
// Id not found in weapons/equipment, try mags
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild => magBuild.Id == idToRemove);
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild =>
magBuild.Id == idToRemove
);
if (matchingMagazineBuild is not null)
{
magazineBuilds.Remove(matchingMagazineBuild);
@@ -7,9 +7,7 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
public class ClientLogController(
ISptLogger<ClientLogController> _logger
)
public class ClientLogController(ISptLogger<ClientLogController> _logger)
{
/// <summary>
/// Handle /singleplayer/log
@@ -44,16 +44,18 @@ public class CustomizationController(
var suits = _databaseService.GetTrader(traderId).Suits;
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId!)).ToList();
matchingSuits = matchingSuits?.Where(s => clothing[s.SuiteId ?? string.Empty]
?.Properties?.Side?
.Contains(pmcData?.Info?.Side ?? string.Empty) ??
false
matchingSuits = matchingSuits
?.Where(s =>
clothing[s.SuiteId ?? string.Empty]
?.Properties?.Side?.Contains(pmcData?.Info?.Side ?? string.Empty) ?? false
)
.ToList();
if (matchingSuits == null)
{
throw new Exception(_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId));
throw new Exception(
_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId)
);
}
return matchingSuits;
@@ -70,7 +72,8 @@ public class CustomizationController(
public ItemEventRouterResponse BuyCustomisation(
PmcData pmcData,
BuyClothingRequestData buyClothingRequest,
string sessionId)
string sessionId
)
{
var output = _eventOutputHolder.GetOutput(sessionId);
@@ -78,7 +81,10 @@ public class CustomizationController(
if (traderOffer is null)
{
_logger.Error(
_localisationService.GetText("customisation-unable_to_find_suit_by_id", buyClothingRequest.Offer)
_localisationService.GetText(
"customisation-unable_to_find_suit_by_id",
buyClothingRequest.Offer
)
);
return output;
}
@@ -90,11 +96,7 @@ public class CustomizationController(
_logger.Error(
_localisationService.GetText(
"customisation-item_already_purchased",
new
{
itemId = suitDetails?.Id,
itemName = suitDetails?.Name
}
new { itemId = suitDetails?.Id, itemName = suitDetails?.Name }
)
);
@@ -111,7 +113,7 @@ public class CustomizationController(
{
Id = suitId,
Source = CustomisationSource.UNLOCKED_IN_GAME,
Type = CustomisationType.SUITE
Type = CustomisationType.SUITE,
};
profile.CustomisationUnlocks.Add(rewardToStore);
@@ -130,7 +132,9 @@ public class CustomizationController(
var fullProfile = _profileHelper.GetFullProfile(sessionId);
// Check if clothing can be found by id
return fullProfile.CustomisationUnlocks.Exists(customisation => Equals(customisation.Id, suitId));
return fullProfile.CustomisationUnlocks.Exists(customisation =>
Equals(customisation.Id, suitId)
);
}
/// <summary>
@@ -144,7 +148,9 @@ public class CustomizationController(
var foundSuit = GetAllTraderSuits(sessionId).FirstOrDefault(s => s.Id == offerId);
if (foundSuit is null)
{
_logger.Error(_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId));
_logger.Error(
_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId)
);
}
return foundSuit;
@@ -157,9 +163,12 @@ public class CustomizationController(
/// <param name="pmcData">Player profile</param>
/// <param name="itemsToPayForClothingWith">Clothing purchased</param>
/// <param name="output">Client response</param>
protected void PayForClothingItems(string sessionId, PmcData pmcData,
protected void PayForClothingItems(
string sessionId,
PmcData pmcData,
List<PaymentItemForClothing>? itemsToPayForClothingWith,
ItemEventRouterResponse output)
ItemEventRouterResponse output
)
{
if (itemsToPayForClothingWith is null || itemsToPayForClothingWith.Count == 0)
{
@@ -175,15 +184,15 @@ public class CustomizationController(
new IdWithCount
{
Count = inventoryItemToProcess.Count.Value,
Id = inventoryItemToProcess.Id
}
Id = inventoryItemToProcess.Id,
},
],
TransactionId = Traders.RAGMAN,
Action = "BuyCustomization",
Type = "",
ItemId = "",
Count = 0,
SchemeId = 0
SchemeId = 0,
};
_paymentService.PayMoney(pmcData, options, sessionId, output);
@@ -202,7 +211,10 @@ public class CustomizationController(
foreach (var trader in traders)
{
if (trader.Value.Base?.CustomizationSeller is not null && trader.Value.Base.CustomizationSeller.Value)
if (
trader.Value.Base?.CustomizationSeller is not null
&& trader.Value.Base.CustomizationSeller.Value
)
{
result.AddRange(GetTraderSuits(trader.Key, sessionId));
}
@@ -226,10 +238,11 @@ public class CustomizationController(
/// </summary>
/// <param name="sessionId">Session/Player id</param>
/// <returns></returns>
public List<CustomisationStorage> GetCustomisationStorage(
string sessionId)
public List<CustomisationStorage> GetCustomisationStorage(string sessionId)
{
var customisationResultsClone = _cloner.Clone(_databaseService.GetTemplates().CustomisationStorage);
var customisationResultsClone = _cloner.Clone(
_databaseService.GetTemplates().CustomisationStorage
);
var profile = _profileHelper.GetFullProfile(sessionId);
if (profile is null)
@@ -249,7 +262,11 @@ public class CustomizationController(
/// <param name="request"></param>
/// <param name="pmcData">Players PMC profile</param>
/// <returns></returns>
public ItemEventRouterResponse SetCustomisation(string sessionId, CustomizationSetRequest request, PmcData pmcData)
public ItemEventRouterResponse SetCustomisation(
string sessionId,
CustomizationSetRequest request,
PmcData pmcData
)
{
foreach (var customisation in request.Customizations)
{
@@ -37,13 +37,17 @@ public class DialogueController(
{
if (_dialogueChatBots.Any(cb => cb.GetChatBot().Id == chatBot.GetChatBot().Id))
{
_logger.Error(_localisationService.GetText("dialog-chatbot_id_already_exists", chatBot.GetChatBot().Id));
_logger.Error(
_localisationService.GetText(
"dialog-chatbot_id_already_exists",
chatBot.GetChatBot().Id
)
);
}
_dialogueChatBots.Add(chatBot);
}
/// <summary>
/// Handle onUpdate spt event
/// </summary>
@@ -80,7 +84,7 @@ public class DialogueController(
{
Id = friendProfile.Id,
Aid = friendProfile.Aid,
Info = friendProfile.Info
Info = friendProfile.Info,
}
);
}
@@ -91,7 +95,7 @@ public class DialogueController(
{
Friends = friends,
Ignore = [],
InIgnoreList = []
InIgnoreList = [],
};
}
@@ -144,9 +148,7 @@ public class DialogueController(
/// <param name="dialogueId">Dialog id</param>
/// <param name="sessionId">Session Id</param>
/// <returns>DialogueInfo</returns>
public virtual DialogueInfo? GetDialogueInfo(
string? dialogueId,
string sessionId)
public virtual DialogueInfo? GetDialogueInfo(string? dialogueId, string sessionId)
{
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
var dialogue = dialogs!.GetValueOrDefault(dialogueId);
@@ -164,7 +166,7 @@ public class DialogueController(
New = dialogue?.New,
AttachmentsNew = dialogue?.AttachmentsNew,
Pinned = dialogue?.Pinned,
Users = GetDialogueUsers(dialogue, dialogue?.Type, sessionId)
Users = GetDialogueUsers(dialogue, dialogue?.Type, sessionId),
};
return result;
@@ -180,14 +182,19 @@ public class DialogueController(
public virtual List<UserDialogInfo> GetDialogueUsers(
Dialogue? dialog,
MessageType? messageType,
string sessionId)
string sessionId
)
{
var profile = _saveServer.GetProfile(sessionId);
// User to user messages are special in that they need the player to exist in them, add if they don't
if (messageType == MessageType.UserMessage &&
dialog?.Users is not null &&
dialog.Users.All(userDialog => userDialog.Id != profile.CharacterData?.PmcData?.SessionId))
if (
messageType == MessageType.UserMessage
&& dialog?.Users is not null
&& dialog.Users.All(userDialog =>
userDialog.Id != profile.CharacterData?.PmcData?.SessionId
)
)
{
dialog.Users.Add(
new UserDialogInfo
@@ -200,8 +207,12 @@ public class DialogueController(
Nickname = profile.CharacterData?.PmcData?.Info?.Nickname,
Side = profile.CharacterData?.PmcData?.Info?.Side,
MemberCategory = profile.CharacterData?.PmcData?.Info?.MemberCategory,
SelectedMemberCategory = profile.CharacterData?.PmcData?.Info?.SelectedMemberCategory
}
SelectedMemberCategory = profile
.CharacterData
?.PmcData
?.Info
?.SelectedMemberCategory,
},
}
);
}
@@ -220,7 +231,8 @@ public class DialogueController(
/// <returns>GetMailDialogViewResponseData object</returns>
public virtual GetMailDialogViewResponseData GenerateDialogueView(
GetMailDialogViewRequestData request,
string sessionId)
string sessionId
)
{
var dialogueId = request.DialogId;
var fullProfile = _saveServer.GetProfile(sessionId);
@@ -232,7 +244,7 @@ public class DialogueController(
{
Messages = [],
Profiles = [],
HasMessagesWithRewards = false
HasMessagesWithRewards = false,
};
}
@@ -246,7 +258,7 @@ public class DialogueController(
{
Messages = dialogue.Messages,
Profiles = GetProfilesForMail(fullProfile, dialogue.Users),
HasMessagesWithRewards = MessagesHaveUncollectedRewards(dialogue.Messages!)
HasMessagesWithRewards = MessagesHaveUncollectedRewards(dialogue.Messages!),
};
}
@@ -258,11 +270,16 @@ public class DialogueController(
/// <returns>Dialogue</returns>
protected Dialogue GetDialogByIdFromProfile(
SptProfile profile,
GetMailDialogViewRequestData request)
GetMailDialogViewRequestData request
)
{
if (profile.DialogueRecords is null || profile.DialogueRecords.ContainsKey(request.DialogId!))
if (
profile.DialogueRecords is null
|| profile.DialogueRecords.ContainsKey(request.DialogId!)
)
{
return profile.DialogueRecords?[request.DialogId!] ?? throw new NullReferenceException();
return profile.DialogueRecords?[request.DialogId!]
?? throw new NullReferenceException();
}
profile.DialogueRecords[request.DialogId!] = new Dialogue
@@ -272,7 +289,7 @@ public class DialogueController(
Pinned = false,
Messages = [],
New = 0,
Type = request.Type
Type = request.Type,
};
if (request.Type != MessageType.UserMessage)
@@ -282,7 +299,9 @@ public class DialogueController(
var dialogue = profile.DialogueRecords[request.DialogId!];
dialogue.Users = [];
var chatBot = _dialogueChatBots.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId);
var chatBot = _dialogueChatBots.FirstOrDefault(cb =>
cb.GetChatBot().Id == request.DialogId
);
if (chatBot is null)
{
@@ -301,11 +320,14 @@ public class DialogueController(
/// <param name="fullProfile">Player profile</param>
/// <param name="userDialogs">The participants of the mail</param>
/// <returns>UserDialogInfo list</returns>
protected List<UserDialogInfo> GetProfilesForMail(SptProfile fullProfile, List<UserDialogInfo>? userDialogs)
protected List<UserDialogInfo> GetProfilesForMail(
SptProfile fullProfile,
List<UserDialogInfo>? userDialogs
)
{
List<UserDialogInfo> result = [];
if (userDialogs is null)
// Nothing to add
// Nothing to add
{
return result;
}
@@ -330,8 +352,8 @@ public class DialogueController(
Side = pmcProfile?.Info?.Side,
Level = pmcProfile?.Info?.Level,
MemberCategory = pmcProfile?.Info?.MemberCategory,
SelectedMemberCategory = pmcProfile?.Info?.SelectedMemberCategory
}
SelectedMemberCategory = pmcProfile?.Info?.SelectedMemberCategory,
},
}
);
@@ -344,15 +366,16 @@ public class DialogueController(
/// <param name="sessionId">Session id</param>
/// <param name="dialogueId">Dialog id</param>
/// <returns>Count of messages with attachments</returns>
protected int GetUnreadMessagesWithAttachmentsCount(
string sessionId,
string dialogueId)
protected int GetUnreadMessagesWithAttachmentsCount(string sessionId, string dialogueId)
{
var newAttachmentCount = 0;
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
foreach (var message in activeMessages)
{
if (message.HasRewards.GetValueOrDefault(false) && !message.RewardCollected.GetValueOrDefault(false))
if (
message.HasRewards.GetValueOrDefault(false)
&& !message.RewardCollected.GetValueOrDefault(false)
)
{
newAttachmentCount++;
}
@@ -372,11 +395,13 @@ public class DialogueController(
var timeNow = _timeUtil.GetTimeStamp();
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
return dialogs[dialogueId].Messages?.Where(message =>
{
var checkTime = message.DateTime + (message.MaxStorageTime ?? 0);
return timeNow < checkTime;
}).ToList() ?? [];
return dialogs[dialogueId]
.Messages?.Where(message =>
{
var checkTime = message.DateTime + (message.MaxStorageTime ?? 0);
return timeNow < checkTime;
})
.ToList() ?? [];
}
/// <summary>
@@ -395,9 +420,7 @@ public class DialogueController(
/// </summary>
/// <param name="dialogueId">id of the dialog to remove</param>
/// <param name="sessionId">Player id</param>
public virtual void RemoveDialogue(
string? dialogueId,
string sessionId)
public virtual void RemoveDialogue(string? dialogueId, string sessionId)
{
var profile = _saveServer.GetProfile(sessionId);
if (!profile.DialogueRecords.ContainsKey(dialogueId))
@@ -405,11 +428,7 @@ public class DialogueController(
_logger.Error(
_localisationService.GetText(
"dialogue-unable_to_find_in_profile",
new
{
sessionId,
dialogueId
}
new { sessionId, dialogueId }
)
);
@@ -433,11 +452,7 @@ public class DialogueController(
_logger.Error(
_localisationService.GetText(
"dialogue-unable_to_find_in_profile",
new
{
sessionId,
dialogueId
}
new { sessionId, dialogueId }
)
);
@@ -461,10 +476,7 @@ public class DialogueController(
_logger.Error(
_localisationService.GetText(
"dialogue-unable_to_find_dialogs_in_profile",
new
{
sessionId
}
new { sessionId }
)
);
@@ -491,9 +503,7 @@ public class DialogueController(
var dialog = dialogs.TryGetValue(dialogueId, out var dialogInfo);
if (!dialog)
{
_logger.Error(
_localisationService.GetText("dialogue-unable_to_find_in_profile")
);
_logger.Error(_localisationService.GetText("dialogue-unable_to_find_in_profile"));
return null;
}
@@ -508,7 +518,7 @@ public class DialogueController(
{
Messages = messagesWithAttachments,
Profiles = [],
HasMessagesWithRewards = MessagesHaveUncollectedRewards(messagesWithAttachments)
HasMessagesWithRewards = MessagesHaveUncollectedRewards(messagesWithAttachments),
};
}
@@ -518,18 +528,15 @@ public class DialogueController(
/// <param name="sessionId">Session/Player id</param>
/// <param name="request"></param>
/// <returns></returns>
public virtual string SendMessage(
string sessionId,
SendMessageRequest request)
public virtual string SendMessage(string sessionId, SendMessageRequest request)
{
_mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId!, request.Text!);
return (_dialogueChatBots.FirstOrDefault(cb =>
cb.GetChatBot().Id == request.DialogId
)
?.HandleMessage(sessionId, request) ??
request.DialogId) ??
string.Empty;
return (
_dialogueChatBots
.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId)
?.HandleMessage(sessionId, request) ?? request.DialogId
) ?? string.Empty;
}
/// <summary>
@@ -592,7 +599,10 @@ public class DialogueController(
/// <param name="sessionID">Session/player id</param>
/// <param name="request">Sent friend request</param>
/// <returns></returns>
public virtual FriendRequestSendResponse SendFriendRequest(string sessionID, FriendRequestData request)
public virtual FriendRequestSendResponse SendFriendRequest(
string sessionID,
FriendRequestData request
)
{
// To avoid needing to jump between profiles, auto-accept all friend requests
var friendProfile = _profileHelper.GetFullProfile(request.To);
@@ -602,7 +612,7 @@ public class DialogueController(
{
Status = BackendErrorCodes.PlayerProfileNotFound,
RequestId = "", // Unused in an error state
RetryAfter = 600
RetryAfter = 600,
};
}
@@ -620,7 +630,9 @@ public class DialogueController(
var notification = new WsFriendsListAccept
{
EventType = NotificationEventType.friendListRequestAccept,
Profile = _profileHelper.GetChatRoomMemberFromPmcProfile(friendProfile.CharacterData.PmcData)
Profile = _profileHelper.GetChatRoomMemberFromPmcProfile(
friendProfile.CharacterData.PmcData
),
};
_notificationSendHelper.SendMessage(sessionID, notification);
},
@@ -633,7 +645,7 @@ public class DialogueController(
{
Status = BackendErrorCodes.None,
RequestId = friendProfile.ProfileInfo.Aid.ToString(),
RetryAfter = 600
RetryAfter = 600,
};
}
@@ -662,7 +674,9 @@ public class DialogueController(
var profile = _saveServer.GetProfile(sessionId);
if (!profile.DialogueRecords.TryGetValue(request.DialogId, out var dialogToClear))
{
_logger.Warning($"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}");
_logger.Warning(
$"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}"
);
return;
}
@@ -15,7 +15,6 @@ using SPTarkov.Server.Core.Utils.Cloners;
using SPTarkov.Server.Core.Utils.Json;
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
@@ -81,7 +80,7 @@ public class GameController(
fullProfile.SptData ??= new Spt
{
//TODO: complete
Version = "Replace_me"
Version = "Replace_me",
};
fullProfile.SptData.Migrations ??= new Dictionary<string, long>();
fullProfile.FriendProfileIds ??= [];
@@ -91,8 +90,14 @@ public class GameController(
return;
}
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<string, int>(new Dictionary<string, int>(), []);
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<string, int>(new Dictionary<string, int>(), []);
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<string, int>(
new Dictionary<string, int>(),
[]
);
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<string, int>(
new Dictionary<string, int>(),
[]
);
if (fullProfile.DialogueRecords is not null)
{
@@ -101,7 +106,9 @@ public class GameController(
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}");
_logger.Debug(
$"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}"
);
}
var pmcProfile = fullProfile.CharacterData.PmcData;
@@ -133,7 +140,12 @@ public class GameController(
_hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
// Handle if player has been inactive for a long time, catch up on hideout update before the user goes to his hideout
if (!_profileActivityService.ActiveWithinLastMinutes(sessionId, _hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes))
if (
!_profileActivityService.ActiveWithinLastMinutes(
sessionId,
_hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes
)
)
{
_hideoutHelper.UpdatePlayerHideout(sessionId);
}
@@ -167,10 +179,12 @@ public class GameController(
public GameConfigResponse GetGameConfig(string sessionId)
{
var profile = _profileHelper.GetPmcProfile(sessionId);
var gameTime = profile?.Stats?.Eft?.OverallCounters?.Items?
.FirstOrDefault(c => c.Key!.Contains("LifeTime") && c.Key.Contains("Pmc"))
?.Value ??
0D;
var gameTime =
profile
?.Stats?.Eft?.OverallCounters?.Items?.FirstOrDefault(c =>
c.Key!.Contains("LifeTime") && c.Key.Contains("Pmc")
)
?.Value ?? 0D;
var config = new GameConfigResponse
{
@@ -188,18 +202,14 @@ public class GameController(
Trading = _httpServerHelper.GetBackendUrl(),
Messaging = _httpServerHelper.GetBackendUrl(),
Main = _httpServerHelper.GetBackendUrl(),
RagFair = _httpServerHelper.GetBackendUrl()
RagFair = _httpServerHelper.GetBackendUrl(),
},
UseProtobuf = false,
UtcTime = _timeUtil.GetTimeStamp(),
TotalInGame = gameTime,
SessionMode = "pve",
PurchasedGames = new PurchasedGames
{
IsEftPurchased = true,
IsArenaPurchased = false
},
IsGameSynced = true
PurchasedGames = new PurchasedGames { IsEftPurchased = true, IsArenaPurchased = false },
IsGameSynced = true,
};
return config;
@@ -211,14 +221,12 @@ public class GameController(
/// <param name="sessionId">Session/Player id</param>
/// <param name="requestData"></param>
/// <returns></returns>
public GameModeResponse GetGameMode(
string sessionId,
GameModeRequestData requestData)
public GameModeResponse GetGameMode(string sessionId, GameModeRequestData requestData)
{
return new GameModeResponse
{
GameMode = "pve",
BackendUrl = _httpServerHelper.GetBackendUrl()
BackendUrl = _httpServerHelper.GetBackendUrl(),
};
}
@@ -229,14 +237,7 @@ public class GameController(
/// <returns></returns>
public List<ServerDetails> GetServer(string sessionId)
{
return
[
new ServerDetails
{
Ip = _httpConfig.BackendIp,
Port = _httpConfig.BackendPort
}
];
return [new ServerDetails { Ip = _httpConfig.BackendIp, Port = _httpConfig.BackendPort }];
}
/// <summary>
@@ -246,13 +247,9 @@ public class GameController(
/// <returns></returns>
public CurrentGroupResponse GetCurrentGroup(string sessionId)
{
return new CurrentGroupResponse
{
Squad = []
};
return new CurrentGroupResponse { Squad = [] };
}
/// <summary>
/// Handle client/checkVersion
/// </summary>
@@ -263,7 +260,7 @@ public class GameController(
return new CheckVersionResponse
{
IsValid = true,
LatestVersion = _coreConfig.CompatibleTarkovVersion
LatestVersion = _coreConfig.CompatibleTarkovVersion,
};
}
@@ -275,11 +272,7 @@ public class GameController(
public GameKeepAliveResponse GetKeepAlive(string sessionId)
{
_profileActivityService.SetActivityTimestamp(sessionId);
return new GameKeepAliveResponse
{
Message = "OK",
UtcTime = _timeUtil.GetTimeStamp()
};
return new GameKeepAliveResponse { Message = "OK", UtcTime = _timeUtil.GetTimeStamp() };
}
/// <summary>
@@ -311,7 +304,9 @@ public class GameController(
var botReloadSkill = _profileHelper.GetSkillFromProfile(pmcProfile, SkillTypes.BotReload);
if (botReloadSkill?.Progress > 0)
{
_logger.Warning(_localisationService.GetText("server_start_player_active_botreload_skill"));
_logger.Warning(
_localisationService.GetText("server_start_player_active_botreload_skill")
);
}
}
@@ -337,23 +332,25 @@ public class GameController(
var hpRegenPerHour = 456.6;
// Set new values, whatever is smallest
energyRegenPerHour += pmcProfile.Bonuses!
.Where(bonus => bonus.Type == BonusType.EnergyRegeneration)
energyRegenPerHour += pmcProfile
.Bonuses!.Where(bonus => bonus.Type == BonusType.EnergyRegeneration)
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
hydrationRegenPerHour += pmcProfile.Bonuses!
.Where(bonus => bonus.Type == BonusType.HydrationRegeneration)
hydrationRegenPerHour += pmcProfile
.Bonuses!.Where(bonus => bonus.Type == BonusType.HydrationRegeneration)
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
hpRegenPerHour += pmcProfile.Bonuses!
.Where(bonus => bonus.Type == BonusType.HealthRegeneration)
hpRegenPerHour += pmcProfile
.Bonuses!.Where(bonus => bonus.Type == BonusType.HealthRegeneration)
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
// Player has energy deficit
if (pmcProfile.Health?.Energy?.Current - pmcProfile.Health?.Energy?.Maximum <= _deviation)
{
// Set new value, whatever is smallest
pmcProfile.Health!.Energy!.Current += Math.Round(energyRegenPerHour * (diffSeconds!.Value / 3600));
pmcProfile.Health!.Energy!.Current += Math.Round(
energyRegenPerHour * (diffSeconds!.Value / 3600)
);
if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum)
{
pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum;
@@ -361,9 +358,14 @@ public class GameController(
}
// Player has hydration deficit
if (pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum <= _deviation)
if (
pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum
<= _deviation
)
{
pmcProfile.Health!.Hydration!.Current += Math.Round(hydrationRegenPerHour * (diffSeconds!.Value / 3600));
pmcProfile.Health!.Hydration!.Current += Math.Round(
hydrationRegenPerHour * (diffSeconds!.Value / 3600)
);
if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum)
{
pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum;
@@ -383,10 +385,15 @@ public class GameController(
/// <param name="pmcProfile">Player</param>
/// <param name="hpRegenPerHour"></param>
/// <param name="diffSeconds"></param>
protected void DecreaseBodyPartEffectTimes(PmcData pmcProfile, double hpRegenPerHour, double diffSeconds)
protected void DecreaseBodyPartEffectTimes(
PmcData pmcProfile,
double hpRegenPerHour,
double diffSeconds
)
{
foreach (var bodyPart in pmcProfile.Health!.BodyParts!
.Select(bodyPartKvP => bodyPartKvP.Value))
foreach (
var bodyPart in pmcProfile.Health!.BodyParts!.Select(bodyPartKvP => bodyPartKvP.Value)
)
{
// Check part hp
if (bodyPart.Health!.Current < bodyPart.Health.Maximum)
@@ -399,7 +406,6 @@ public class GameController(
bodyPart.Health.Current = bodyPart.Health.Maximum;
}
if (bodyPart.Effects is null || bodyPart.Effects.Count == 0)
{
continue;
@@ -423,7 +429,7 @@ public class GameController(
// Decrement effect time value by difference between current time and time health was last updated
effectKvP.Value.Time -= diffSeconds;
if (effectKvP.Value.Time < 1)
// Effect time was sub 1, set floor it can be
// Effect time was sub 1, set floor it can be
{
effectKvP.Value.Time = 1;
}
@@ -475,7 +481,9 @@ public class GameController(
{
if (
fullProfile.SptData.Mods.Any(m =>
m.Author == mod.ModMetadata.Author && m.Version == mod.ModMetadata.Version && m.Name == mod.ModMetadata.Name
m.Author == mod.ModMetadata.Author
&& m.Version == mod.ModMetadata.Version
&& m.Name == mod.ModMetadata.Name
)
)
{
@@ -490,7 +498,7 @@ public class GameController(
Version = mod.ModMetadata.Version,
Name = mod.ModMetadata.Name,
Url = mod.ModMetadata.Url,
DateAdded = _timeUtil.GetTimeStamp()
DateAdded = _timeUtil.GetTimeStamp(),
}
);
}
@@ -552,7 +560,9 @@ public class GameController(
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Profile made with: {fullProfile.SptData?.Version}");
_logger.Debug($"Server version: {ProgramStatics.SPT_VERSION() ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}");
_logger.Debug(
$"Server version: {ProgramStatics.SPT_VERSION() ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}"
);
_logger.Debug($"Debug enabled: {ProgramStatics.DEBUG()}");
_logger.Debug($"Mods enabled: {ProgramStatics.MODS()}");
}
@@ -25,7 +25,8 @@ public class HealthController(
LocalisationService _localisationService,
HttpResponseUtil _httpResponseUtil,
HealthHelper _healthHelper,
ICloner _cloner)
ICloner _cloner
)
{
/// <summary>
/// When healing in menu
@@ -37,15 +38,21 @@ public class HealthController(
public ItemEventRouterResponse OffRaidHeal(
PmcData pmcData,
OffraidHealRequestData request,
string sessionID)
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
// Update medkit used (hpresource)
var healingItemToUse = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
var healingItemToUse = pmcData.Inventory.Items.FirstOrDefault(item =>
item.Id == request.Item
);
if (healingItemToUse is null)
{
var errorMessage = _localisationService.GetText("health-healing_item_not_found", request.Item);
var errorMessage = _localisationService.GetText(
"health-healing_item_not_found",
request.Item
);
_logger.Error(errorMessage);
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage);
@@ -61,11 +68,10 @@ public class HealthController(
else
{
// Get max healing from db
var maxHp = _itemHelper.GetItem(healingItemToUse.Template).Value.Properties.MaxHpResource;
healingItemToUse.Upd.MedKit = new UpdMedKit
{
HpResource = maxHp - request.Count
}; // Subtract amout used from max
var maxHp = _itemHelper
.GetItem(healingItemToUse.Template)
.Value.Properties.MaxHpResource;
healingItemToUse.Upd.MedKit = new UpdMedKit { HpResource = maxHp - request.Count }; // Subtract amout used from max
// request.count appears to take into account healing effects removed, e.g. bleeds
// Salewa heals limb for 20 and fixes light bleed = (20+45 = 65)
}
@@ -82,7 +88,9 @@ public class HealthController(
var bodyPartToHeal = pmcData.Health.BodyParts.GetValueOrDefault(request.Part);
if (bodyPartToHeal is null)
{
_logger.Warning($"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}");
_logger.Warning(
$"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}"
);
return output;
}
@@ -99,20 +107,25 @@ public class HealthController(
{
// Check enum has effectType
if (!Enum.TryParse<DamageEffectType>(effectKvP.Key, out var effect))
// Enum doesnt contain this key
// Enum doesnt contain this key
{
continue;
}
// Check if healing item removes the effect on limb
if (!healItemEffectDetails.TryGetValue(effect, out var matchingEffectFromHealingItem))
// Healing item doesn't have matching effect, it doesn't remove the effect
if (
!healItemEffectDetails.TryGetValue(
effect,
out var matchingEffectFromHealingItem
)
)
// Healing item doesn't have matching effect, it doesn't remove the effect
{
continue;
}
// Adjust limb heal amount based on if it's fixing an effect (request.count is TOTAL cost of hp resource on heal item, NOT amount to heal limb)
amountToHealLimb -= (int) (matchingEffectFromHealingItem.Cost ?? 0);
amountToHealLimb -= (int)(matchingEffectFromHealingItem.Cost ?? 0);
bodyPartToHeal.Effects.Remove(effectKvP.Key);
}
}
@@ -140,14 +153,15 @@ public class HealthController(
public ItemEventRouterResponse OffRaidEat(
PmcData pmcData,
OffraidEatRequestData request,
string sessionID)
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
var resourceLeft = 0d;
var itemToConsume = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
if (itemToConsume is null)
// Item not found, very bad
// Item not found, very bad
{
return _httpResponseUtil.AppendErrorToOutput(
output,
@@ -155,7 +169,9 @@ public class HealthController(
);
}
var consumedItemMaxResource = _itemHelper.GetItem(itemToConsume.Template).Value.Properties.MaxResource;
var consumedItemMaxResource = _itemHelper
.GetItem(itemToConsume.Template)
.Value.Properties.MaxResource;
if (consumedItemMaxResource > 1)
{
// Ensure item has a upd object
@@ -165,7 +181,7 @@ public class HealthController(
{
itemToConsume.Upd.FoodDrink = new UpdFoodDrink
{
HpPercent = consumedItemMaxResource - request.Count
HpPercent = consumedItemMaxResource - request.Count,
};
}
else
@@ -192,14 +208,21 @@ public class HealthController(
switch (key)
{
case HealthFactor.Hydration:
ApplyEdibleEffect(pmcData.Health.Hydration, effectProps, foodIsSingleUse, request);
ApplyEdibleEffect(
pmcData.Health.Hydration,
effectProps,
foodIsSingleUse,
request
);
break;
case HealthFactor.Energy:
ApplyEdibleEffect(pmcData.Health.Energy, effectProps, foodIsSingleUse, request);
break;
default:
_logger.Warning($"Unhandled effect after consuming: {itemToConsume.Template}, {key}");
_logger.Warning(
$"Unhandled effect after consuming: {itemToConsume.Template}, {key}"
);
break;
}
}
@@ -214,11 +237,15 @@ public class HealthController(
/// <param name="consumptionDetails">Properties of consumed item</param>
/// <param name="foodIsSingleUse">Single use item</param>
/// <param name="request">Client request</param>
protected void ApplyEdibleEffect(CurrentMinMax bodyValue, EffectsHealthProps consumptionDetails, bool foodIsSingleUse,
OffraidEatRequestData request)
protected void ApplyEdibleEffect(
CurrentMinMax bodyValue,
EffectsHealthProps consumptionDetails,
bool foodIsSingleUse,
OffraidEatRequestData request
)
{
if (foodIsSingleUse)
// Apply whole value from passed in parameter
// Apply whole value from passed in parameter
{
bodyValue.Current += consumptionDetails.Value;
}
@@ -253,7 +280,8 @@ public class HealthController(
public ItemEventRouterResponse HealthTreatment(
PmcData pmcData,
HealthTreatmentRequestData healthTreatmentRequest,
string sessionID)
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
var payMoneyRequest = new ProcessBuyTradeRequestData
@@ -264,7 +292,7 @@ public class HealthController(
Type = "",
ItemId = "",
Count = 0,
SchemeId = 0
SchemeId = 0,
};
_paymentService.PayMoney(pmcData, payMoneyRequest, sessionID, output);
@@ -276,12 +304,12 @@ public class HealthController(
foreach (var bodyPartKvP in healthTreatmentRequest.Difference.BodyParts.GetAllPropsAsDict())
{
// Get body part from request + from pmc profile
var partRequest = (BodyPartEffects) bodyPartKvP.Value;
var partRequest = (BodyPartEffects)bodyPartKvP.Value;
var profilePart = pmcData.Health.BodyParts[bodyPartKvP.Key];
// Bodypart healing is chosen when part request hp is above 0
if (partRequest.Health > 0)
// Heal bodypart
// Heal bodypart
{
profilePart.Health.Current = profilePart.Health.Maximum;
}
@@ -315,10 +343,7 @@ public class HealthController(
/// <param name="pmcData">Player profile</param>
/// <param name="request">Request data</param>
/// <param name="sessionId">session id</param>
public void ApplyWorkoutChanges(
PmcData? pmcData,
WorkoutData request,
string sessionId)
public void ApplyWorkoutChanges(PmcData? pmcData, WorkoutData request, string sessionId)
{
pmcData.Skills.Common = request.Skills.Common;
}
File diff suppressed because it is too large Load Diff
@@ -25,7 +25,7 @@ public class InRaidController(
/// <param name="info">Register player request</param>
public void AddPlayer(string sessionId, RegisterPlayerRequestData info)
{
// _applicationContext.AddValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info);
// _applicationContext.AddValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info);
}
/// <summary>
@@ -91,11 +91,15 @@ public class InsuranceController(
{
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}");
_logger.Debug(
$"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}"
);
}
}
return profileInsuranceDetails.Where(insured => insuranceTime >= insured.ScheduledTime).ToList();
return profileInsuranceDetails
.Where(insured => insuranceTime >= insured.ScheduledTime)
.ToList();
}
/// <summary>
@@ -159,17 +163,20 @@ public class InsuranceController(
protected void RemoveInsurancePackageFromProfile(string sessionId, Insurance insPackage)
{
var profile = _saveServer.GetProfile(sessionId);
profile.InsuranceList = profile.InsuranceList.Where(insurance =>
insurance.TraderId != insPackage.TraderId ||
insurance.SystemData?.Date != insPackage.SystemData?.Date ||
insurance.SystemData?.Time != insPackage.SystemData?.Time ||
insurance.SystemData?.Location != insPackage.SystemData?.Location
profile.InsuranceList = profile
.InsuranceList.Where(insurance =>
insurance.TraderId != insPackage.TraderId
|| insurance.SystemData?.Date != insPackage.SystemData?.Date
|| insurance.SystemData?.Time != insPackage.SystemData?.Time
|| insurance.SystemData?.Location != insPackage.SystemData?.Location
)
.ToList();
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}");
_logger.Debug(
$"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}"
);
}
}
@@ -186,11 +193,14 @@ public class InsuranceController(
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
// and each of their attachments. For example, a gun mapped to each of its attachments.
var itemsMap = _itemHelper.GenerateItemsMap(insured.Items);
var parentAttachmentsMap = PopulateParentAttachmentsMap(rootItemParentId, insured, itemsMap);
var parentAttachmentsMap = PopulateParentAttachmentsMap(
rootItemParentId,
insured,
itemsMap
);
// Check to see if any regular items are present.
var hasRegularItems = itemsMap.Values.Any(item => !_itemHelper.IsAttachmentAttached(item)
);
var hasRegularItems = itemsMap.Values.Any(item => !_itemHelper.IsAttachmentAttached(item));
// Process all items that are not attached, attachments; those are handled separately, by value.
if (hasRegularItems)
@@ -229,7 +239,11 @@ public class InsuranceController(
/// <param name="insured">The insurance object containing the items to evaluate</param>
/// <param name="itemsMap">A Dictionary for quick item look-up by item ID</param>
/// <returns>A dictionary containing parent item IDs to arrays of their attachment items</returns>
protected Dictionary<string, List<Item>> PopulateParentAttachmentsMap(string rootItemParentID, Insurance insured, Dictionary<string, Item> itemsMap)
protected Dictionary<string, List<Item>> PopulateParentAttachmentsMap(
string rootItemParentID,
Insurance insured,
Dictionary<string, Item> itemsMap
)
{
var mainParentToAttachmentsMap = new Dictionary<string, List<Item>>();
foreach (var insuredItem in insured.Items)
@@ -247,7 +261,7 @@ public class InsuranceController(
{
insuredItemId = insuredItem.Id,
insuredItemTpl = insuredItem.Template,
parentId = insuredItem.ParentId
parentId = insuredItem.ParentId,
}
)
);
@@ -270,7 +284,7 @@ public class InsuranceController(
new
{
insuredItemId = insuredItem.Id,
insuredItemTpl = insuredItem.Template
insuredItemTpl = insuredItem.Template,
}
)
);
@@ -290,7 +304,7 @@ public class InsuranceController(
{
insuredItemId = insuredItem.Id,
insuredItemTpl = insuredItem.Template,
parentId = insuredItem.ParentId
parentId = insuredItem.ParentId,
}
)
);
@@ -322,8 +336,10 @@ public class InsuranceController(
/// <param name="parentAttachmentsMap">Dictionary containing parent item IDs to arrays of their attachment items</param>
/// <param name="itemsMap">Hashset containing parent item IDs to arrays of their attachment items which are not moddable in-raid</param>
/// <returns></returns>
protected Dictionary<string, List<Item>> RemoveNonModdableAttachments(Dictionary<string, List<Item>> parentAttachmentsMap,
Dictionary<string, Item> itemsMap)
protected Dictionary<string, List<Item>> RemoveNonModdableAttachments(
Dictionary<string, List<Item>> parentAttachmentsMap,
Dictionary<string, Item> itemsMap
)
{
var updatedMap = new Dictionary<string, List<Item>>();
@@ -371,7 +387,11 @@ public class InsuranceController(
/// <param name="insured">Insurance object containing the items to evaluate</param>
/// <param name="toDelete">Hashset to keep track of items marked for deletion</param>
/// <param name="parentAttachmentsMap">Dictionary containing parent item IDs to arrays of their attachment items</param>
protected void ProcessRegularItems(Insurance insured, HashSet<string> toDelete, Dictionary<string, List<Item>> parentAttachmentsMap)
protected void ProcessRegularItems(
Insurance insured,
HashSet<string> toDelete,
Dictionary<string, List<Item>> parentAttachmentsMap
)
{
foreach (var insuredItem in insured.Items)
{
@@ -419,8 +439,12 @@ public class InsuranceController(
/// <param name="itemsMap">Dictionary for quick item look-up by item ID</param>
/// <param name="insuredTraderId">Trader ID from the Insurance object</param>
/// <param name="toDelete">Tracked attachment ids to be removed</param>
protected void ProcessAttachments(Dictionary<string, List<Item>> mainParentToAttachmentsMap, Dictionary<string, Item> itemsMap, string? insuredTraderId,
HashSet<string> toDelete)
protected void ProcessAttachments(
Dictionary<string, List<Item>> mainParentToAttachmentsMap,
Dictionary<string, Item> itemsMap,
string? insuredTraderId,
HashSet<string> toDelete
)
{
foreach (var parentObj in mainParentToAttachmentsMap)
{
@@ -444,7 +468,6 @@ public class InsuranceController(
}
}
/// <summary>
/// Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by
/// their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the
@@ -454,16 +477,26 @@ public class InsuranceController(
/// <param name="attachments">Array of attachment items to sort, filter, and roll</param>
/// <param name="traderId">ID of the trader to that has ensured these items</param>
/// <param name="toDelete">array that accumulates the IDs of the items to be deleted</param>
protected void ProcessAttachmentByParent(List<Item> attachments, string? traderId, HashSet<string> toDelete)
protected void ProcessAttachmentByParent(
List<Item> attachments,
string? traderId,
HashSet<string> toDelete
)
{
// Create dict of item ids + their flea/handbook price (highest is chosen)
var weightedAttachmentByPrice = WeightAttachmentsByPrice(attachments);
// Get how many attachments we want to pull off parent
var countOfAttachmentsToRemove = GetAttachmentCountToRemove(weightedAttachmentByPrice, traderId);
var countOfAttachmentsToRemove = GetAttachmentCountToRemove(
weightedAttachmentByPrice,
traderId
);
// Create prob array and add all attachments with rouble price as the weight
var attachmentsProbabilityArray = new ProbabilityObjectArray<string, double?>(_mathUtil, _cloner);
var attachmentsProbabilityArray = new ProbabilityObjectArray<string, double?>(
_mathUtil,
_cloner
);
foreach (var attachmentTpl in weightedAttachmentByPrice)
{
attachmentsProbabilityArray.Add(
@@ -472,7 +505,10 @@ public class InsuranceController(
}
// Draw x attachments from weighted array to remove from parent, remove from pool after being picked
var attachmentIdsToRemove = attachmentsProbabilityArray.Draw((int) countOfAttachmentsToRemove, false);
var attachmentIdsToRemove = attachmentsProbabilityArray.Draw(
(int)countOfAttachmentsToRemove,
false
);
foreach (var attachmentId in attachmentIdsToRemove)
{
toDelete.Add(attachmentId);
@@ -492,7 +528,11 @@ public class InsuranceController(
/// <param name="attachmentIdsToRemove"></param>
/// <param name="attachments"></param>
/// <param name="attachmentPrices"></param>
protected void LogAttachmentsBeingRemoved(List<string> attachmentIdsToRemove, List<Item> attachments, Dictionary<string, double> attachmentPrices)
protected void LogAttachmentsBeingRemoved(
List<string> attachmentIdsToRemove,
List<Item> attachments,
Dictionary<string, double> attachmentPrices
)
{
var index = 1;
foreach (var attachmentId in attachmentIdsToRemove)
@@ -500,8 +540,8 @@ public class InsuranceController(
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(
$"Attachment {index} Id: {attachmentId} Tpl: {attachments.FirstOrDefault(x => x.Id == attachmentId)?.Template} - " +
$"Price: {attachmentPrices[attachmentId]}"
$"Attachment {index} Id: {attachmentId} Tpl: {attachments.FirstOrDefault(x => x.Id == attachmentId)?.Template} - "
+ $"Price: {attachmentPrices[attachmentId]}"
);
}
@@ -521,7 +561,10 @@ public class InsuranceController(
// Get a dictionary of item tpls + their rouble price
foreach (var attachment in attachments)
{
var price = _ragfairPriceService.GetDynamicItemPrice(attachment.Template, Money.ROUBLES);
var price = _ragfairPriceService.GetDynamicItemPrice(
attachment.Template,
Money.ROUBLES
);
if (price is not null)
{
result[attachment.Id] = Math.Round(price ?? 0);
@@ -539,7 +582,10 @@ public class InsuranceController(
/// <param name="weightedAttachmentByPrice">Dict of item Tpls and their rouble price</param>
/// <param name="traderId">Trader the attachment is insured against</param>
/// <returns>Attachment count to remove</returns>
protected double GetAttachmentCountToRemove(Dictionary<string, double> weightedAttachmentByPrice, string? traderId)
protected double GetAttachmentCountToRemove(
Dictionary<string, double> weightedAttachmentByPrice,
string? traderId
)
{
const int removeCount = 0;
@@ -550,7 +596,9 @@ public class InsuranceController(
// Get attachments count above or equal to price set in config
return weightedAttachmentByPrice
.Where(attachment => attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken)
.Where(attachment =>
attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken
)
.Count(_ => RollForDelete(traderId) ?? false);
}
@@ -577,8 +625,8 @@ public class InsuranceController(
// Map is labs + insurance is disabled in base.json
if (IsMapLabsAndInsuranceDisabled(insurance))
// Trader has labs-specific messages
// Wipe out returnable items
// Trader has labs-specific messages
// Wipe out returnable items
{
HandleLabsInsurance(traderDialogMessages, insurance);
}
@@ -587,9 +635,14 @@ public class InsuranceController(
HandleLabyrinthInsurance(traderDialogMessages, insurance);
}
else if (insurance.Items?.Count == 0)
// Not labs and no items to return
// Not labs and no items to return
{
if (traderDialogMessages.TryGetValue("insuranceFailed", out var insuranceFailedTemplates))
if (
traderDialogMessages.TryGetValue(
"insuranceFailed",
out var insuranceFailedTemplates
)
)
{
insurance.MessageTemplateId = _randomUtil.GetArrayValue(insuranceFailedTemplates);
}
@@ -615,8 +668,15 @@ public class InsuranceController(
/// <returns></returns>
protected bool IsMapLabsAndInsuranceDisabled(Insurance insurance, string labsId = "laboratory")
{
return string.Equals(insurance.SystemData?.Location, labsId, StringComparison.OrdinalIgnoreCase) &&
!(_databaseService.GetLocation(labsId)?.Base?.Insurance.GetValueOrDefault(false) ?? false);
return string.Equals(
insurance.SystemData?.Location,
labsId,
StringComparison.OrdinalIgnoreCase
)
&& !(
_databaseService.GetLocation(labsId)?.Base?.Insurance.GetValueOrDefault(false)
?? false
);
}
/// <summary>
@@ -625,10 +685,20 @@ public class InsuranceController(
/// <param name="insurance">The insured items to process</param>
/// <param name="labsId">OPTIONAL - id of labs location</param>
/// <returns></returns>
protected bool IsMapLabyrinthAndInsuranceDisabled(Insurance insurance, string labyrinthId = "labyrinth")
protected bool IsMapLabyrinthAndInsuranceDisabled(
Insurance insurance,
string labyrinthId = "labyrinth"
)
{
return string.Equals(insurance.SystemData?.Location, labyrinthId, StringComparison.OrdinalIgnoreCase) &&
!(_databaseService.GetLocation(labyrinthId)?.Base?.Insurance.GetValueOrDefault(false) ?? false);
return string.Equals(
insurance.SystemData?.Location,
labyrinthId,
StringComparison.OrdinalIgnoreCase
)
&& !(
_databaseService.GetLocation(labyrinthId)?.Base?.Insurance.GetValueOrDefault(false)
?? false
);
}
/// <summary>
@@ -636,7 +706,10 @@ public class InsuranceController(
/// </summary>
/// <param name="traderDialogMessages"></param>
/// <param name="insurance"></param>
protected void HandleLabsInsurance(Dictionary<string, List<string>?>? traderDialogMessages, Insurance insurance)
protected void HandleLabsInsurance(
Dictionary<string, List<string>?>? traderDialogMessages,
Insurance insurance
)
{
// Use labs specific messages if available, otherwise use default
var responseMesageIds =
@@ -655,10 +728,13 @@ public class InsuranceController(
/// </summary>
/// <param name="traderDialogMessages"></param>
/// <param name="insurance"></param>
protected void HandleLabyrinthInsurance(Dictionary<string, List<string>?>? traderDialogMessages, Insurance insurance)
protected void HandleLabyrinthInsurance(
Dictionary<string, List<string>?>? traderDialogMessages,
Insurance insurance
)
{
// Use labs specific messages if available, otherwise use default
var responseMessageIds =
var responseMessageIds =
traderDialogMessages["insuranceFailedLabyrinth"]?.Count > 0
? traderDialogMessages["insuranceFailedLabyrinth"]
: traderDialogMessages["insuranceFailed"];
@@ -669,7 +745,6 @@ public class InsuranceController(
insurance.Items = [];
}
/// <summary>
/// Roll for chance of item being 'lost'
/// </summary>
@@ -692,11 +767,15 @@ public class InsuranceController(
var roll = returnChance >= traderReturnChance;
// Log the roll with as much detail as possible.
var itemName = insuredItem is not null ? $"{_itemHelper.GetItemName(insuredItem.Template)}" : "";
var itemName = insuredItem is not null
? $"{_itemHelper.GetItemName(insuredItem.Template)}"
: "";
var status = roll ? "Delete" : "Keep";
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}");
_logger.Debug(
$"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}"
);
}
return roll;
@@ -709,7 +788,11 @@ public class InsuranceController(
/// <param name="request">Insurance request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse object to send to client</returns>
public ItemEventRouterResponse Insure(PmcData pmcData, InsureRequestData request, string sessionId)
public ItemEventRouterResponse Insure(
PmcData pmcData,
InsureRequestData request,
string sessionId
)
{
var output = _eventOutputHolder.GetOutput(sessionId);
var itemsToInsureCount = request.Items.Count;
@@ -729,7 +812,7 @@ public class InsuranceController(
pmcData,
inventoryItemsHash[key],
request.TransactionId
)
),
}
);
}
@@ -742,7 +825,7 @@ public class InsuranceController(
Type = "",
ItemId = "",
Count = 0,
SchemeId = 0
SchemeId = 0,
};
// pay for the item insurance
@@ -757,20 +840,22 @@ public class InsuranceController(
foreach (var key in request.Items)
{
pmcData.InsuredItems.Add(
new InsuredItem
{
TId = request.TransactionId,
ItemId = inventoryItemsHash[key].Id
}
new InsuredItem { TId = request.TransactionId, ItemId = inventoryItemsHash[key].Id }
);
// If Item is Helmet or Body Armour -> Handle insurance of soft inserts
if (_itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(inventoryItemsHash[key].Template))
if (
_itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(inventoryItemsHash[key].Template)
)
{
InsureSoftInserts(inventoryItemsHash[key], pmcData, request);
}
}
_profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.Charisma, itemsToInsureCount * 0.01);
_profileHelper.AddSkillPointsToPlayer(
pmcData,
SkillTypes.Charisma,
itemsToInsureCount * 0.01
);
return output;
}
@@ -781,9 +866,15 @@ public class InsuranceController(
/// <param name="itemWithSoftInserts">Armor item to be insured</param>
/// <param name="pmcData">Players PMC profile</param>
/// <param name="request">Insurance request data</param>
public void InsureSoftInserts(Item itemWithSoftInserts, PmcData pmcData, InsureRequestData request)
public void InsureSoftInserts(
Item itemWithSoftInserts,
PmcData pmcData,
InsureRequestData request
)
{
var softInsertSlots = pmcData.Inventory.Items.Where(item => item.ParentId == itemWithSoftInserts.Id && _itemHelper.IsSoftInsertId(item.SlotId.ToLower())
var softInsertSlots = pmcData.Inventory.Items.Where(item =>
item.ParentId == itemWithSoftInserts.Id
&& _itemHelper.IsSoftInsertId(item.SlotId.ToLower())
);
foreach (var softInsertSlot in softInsertSlots)
@@ -794,11 +885,7 @@ public class InsuranceController(
}
pmcData.InsuredItems.Add(
new InsuredItem
{
TId = request.TransactionId,
ItemId = softInsertSlot.Id
}
new InsuredItem { TId = request.TransactionId, ItemId = softInsertSlot.Id }
);
}
}
@@ -830,7 +917,9 @@ public class InsuranceController(
{
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Item with id: {itemId} missing from player inventory, skipping");
_logger.Debug(
$"Item with id: {itemId} missing from player inventory, skipping"
);
}
continue;
@@ -838,7 +927,11 @@ public class InsuranceController(
items.TryAdd(
inventoryItemsHash[itemId].Template,
_insuranceService.GetRoublePriceToInsureItemWithTrader(pmcData, inventoryItemsHash[itemId], trader)
_insuranceService.GetRoublePriceToInsureItemWithTrader(
pmcData,
inventoryItemsHash[itemId],
trader
)
);
}
@@ -48,8 +48,12 @@ public class InventoryController(
/// <param name="moveRequest">Move request data</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void MoveItem(PmcData pmcData, InventoryMoveRequestData moveRequest, string sessionId,
ItemEventRouterResponse output)
public void MoveItem(
PmcData pmcData,
InventoryMoveRequestData moveRequest,
string sessionId,
ItemEventRouterResponse output
)
{
if (output.Warnings?.Count > 0)
{
@@ -57,18 +61,27 @@ public class InventoryController(
}
// Changes made to result apply to character inventory
var ownerInventoryItems = _inventoryHelper.GetOwnerInventoryItems(moveRequest, moveRequest.Item, sessionId);
var ownerInventoryItems = _inventoryHelper.GetOwnerInventoryItems(
moveRequest,
moveRequest.Item,
sessionId
);
if (ownerInventoryItems.SameInventory.GetValueOrDefault(false))
{
// Don't move items from trader to profile, this can happen when editing a traders preset weapons
if (moveRequest.FromOwner?.Type == "Trader" && !ownerInventoryItems.IsMail.GetValueOrDefault(false))
if (
moveRequest.FromOwner?.Type == "Trader"
&& !ownerInventoryItems.IsMail.GetValueOrDefault(false)
)
{
AppendTraderExploitErrorResponse(output);
return;
}
// Check for item in inventory before allowing internal transfer
var originalItemLocation = ownerInventoryItems.From?.FirstOrDefault(item => item.Id == moveRequest.Item);
var originalItemLocation = ownerInventoryItems.From?.FirstOrDefault(item =>
item.Id == moveRequest.Item
);
if (originalItemLocation is null)
{
// Internal item move but item never existed, possible dupe glitch
@@ -91,9 +104,19 @@ public class InventoryController(
}
// Item is moving into or out of place of fame dog tag slot
if (moveRequest.To?.Container != null &&
(moveRequest.To.Container.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase) ||
originalLocationSlotId.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase)))
if (
moveRequest.To?.Container != null
&& (
moveRequest.To.Container.StartsWith(
"dogtag",
StringComparison.OrdinalIgnoreCase
)
|| originalLocationSlotId.StartsWith(
"dogtag",
StringComparison.OrdinalIgnoreCase
)
)
)
{
_hideoutHelper.ApplyPlaceOfFameDogtagBonus(pmcData);
}
@@ -117,7 +140,7 @@ public class InventoryController(
_httpResponseUtil.AppendErrorToOutput(
output,
_localisationService.GetText("inventory-edit_trader_item"),
(BackendErrorCodes) 228
(BackendErrorCodes)228
);
}
@@ -129,13 +152,21 @@ public class InventoryController(
/// <param name="request">Pin/Lock request data</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void PinOrLock(PmcData pmcData, PinOrLockItemRequest request, string sessionId,
ItemEventRouterResponse output)
public void PinOrLock(
PmcData pmcData,
PinOrLockItemRequest request,
string sessionId,
ItemEventRouterResponse output
)
{
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item => item.Id == request.Item);
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item =>
item.Id == request.Item
);
if (itemToAdjust is null)
{
_logger.Error($"Unable find item: {request.Item} to: {request.State} on player {sessionId}to: ");
_logger.Error(
$"Unable find item: {request.Item} to: {request.State} on player {sessionId}to: "
);
return;
}
@@ -165,7 +196,11 @@ public class InventoryController(
/// <param name="pmcData">Players PMC profile</param>
/// <param name="request"></param>
/// <param name="sessionId">Session/Player id</param>
public void RedeemProfileReward(PmcData pmcData, RedeemProfileRequestData request, string sessionId)
public void RedeemProfileReward(
PmcData pmcData,
RedeemProfileRequestData request,
string sessionId
)
{
var fullProfile = _profileHelper.GetFullProfile(sessionId);
foreach (var rewardEvent in request.Events)
@@ -173,49 +208,58 @@ public class InventoryController(
// Hard coded to `SYSTEM` for now
// TODO: make this dynamic
var dialog = fullProfile.DialogueRecords["59e7125688a45068a6249071"];
var mail = dialog.Messages.FirstOrDefault(message => message.Id == rewardEvent.MessageId);
var mailEvent =
mail.ProfileChangeEvents.FirstOrDefault(changeEvent => changeEvent.Id == rewardEvent.EventId);
var mail = dialog.Messages.FirstOrDefault(message =>
message.Id == rewardEvent.MessageId
);
var mailEvent = mail.ProfileChangeEvents.FirstOrDefault(changeEvent =>
changeEvent.Id == rewardEvent.EventId
);
switch (mailEvent.Type)
{
case "TraderSalesSum":
pmcData.TradersInfo[mailEvent.Entity].SalesSum = mailEvent.Value;
_traderHelper.LevelUp(mailEvent.Entity, pmcData);
_logger.Success($"Set trader {mailEvent.Entity}: Sales Sum to: {mailEvent.Value}");
_logger.Success(
$"Set trader {mailEvent.Entity}: Sales Sum to: {mailEvent.Value}"
);
break;
case "TraderStanding":
pmcData.TradersInfo[mailEvent.Entity].Standing = mailEvent.Value;
_traderHelper.LevelUp(mailEvent.Entity, pmcData);
_logger.Success($"Set trader {mailEvent.Entity}: Standing to: {mailEvent.Value}");
_logger.Success(
$"Set trader {mailEvent.Entity}: Standing to: {mailEvent.Value}"
);
break;
case "ProfileLevel":
pmcData.Info.Experience = (int) mailEvent.Value.Value;
pmcData.Info.Experience = (int)mailEvent.Value.Value;
// Will calculate level below
_traderHelper.ValidateTraderStandingsAndPlayerLevelForProfile(sessionId);
_logger.Success($"Set profile xp to: {mailEvent.Value}");
break;
case "SkillPoints":
{
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x =>
x.Id == Enum.Parse<SkillTypes>(mailEvent.Entity)
);
if (profileSkill is null)
{
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x => x.Id == Enum.Parse<SkillTypes>(mailEvent.Entity));
if (profileSkill is null)
{
_logger.Warning($"Unable to find skill with name: {mailEvent.Entity}");
continue;
}
profileSkill.Progress = mailEvent.Value;
_logger.Success($"Set profile skill: {mailEvent.Entity} to: {mailEvent.Value}");
break;
_logger.Warning($"Unable to find skill with name: {mailEvent.Entity}");
continue;
}
profileSkill.Progress = mailEvent.Value;
_logger.Success($"Set profile skill: {mailEvent.Entity} to: {mailEvent.Value}");
break;
}
case "ExamineAllItems":
{
var itemsToInspect = _itemHelper.GetItems().Where(x => x.Type != "Node");
FlagItemsAsInspectedAndRewardXp(itemsToInspect.Select(x => x.Id), fullProfile);
_logger.Success($"Flagged {itemsToInspect.Count()} items as examined");
{
var itemsToInspect = _itemHelper.GetItems().Where(x => x.Type != "Node");
FlagItemsAsInspectedAndRewardXp(itemsToInspect.Select(x => x.Id), fullProfile);
_logger.Success($"Flagged {itemsToInspect.Count()} items as examined");
break;
}
break;
}
case "UnlockTrader":
pmcData.TradersInfo[mailEvent.Entity].Unlocked = true;
_logger.Success($"Trader {mailEvent.Entity} Unlocked");
@@ -228,19 +272,21 @@ public class InventoryController(
break;
case "HideoutAreaLevel":
{
var areaName = mailEvent.Entity;
var newValue = mailEvent.Value;
var hideoutAreaType = Enum.Parse<HideoutAreas>(areaName ?? "NotSet");
var desiredArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
area.Type == hideoutAreaType
);
if (desiredArea is not null)
{
var areaName = mailEvent.Entity;
var newValue = mailEvent.Value;
var hideoutAreaType = Enum.Parse<HideoutAreas>(areaName ?? "NotSet");
var desiredArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == hideoutAreaType);
if (desiredArea is not null)
{
desiredArea.Level = (int?) newValue;
}
break;
desiredArea.Level = (int?)newValue;
}
break;
}
default:
_logger.Warning($"Unhandled profile reward event: {mailEvent.Type}");
@@ -254,7 +300,10 @@ public class InventoryController(
/// </summary>
/// <param name="itemTpls">Inspected item tpls</param>
/// <param name="fullProfile">Profile to add xp to</param>
protected void FlagItemsAsInspectedAndRewardXp(IEnumerable<string> itemTpls, SptProfile fullProfile)
protected void FlagItemsAsInspectedAndRewardXp(
IEnumerable<string> itemTpls,
SptProfile fullProfile
)
{
foreach (var itemTpl in itemTpls)
{
@@ -262,16 +311,23 @@ public class InventoryController(
if (!item.Key)
{
_logger.Warning(
_localisationService.GetText("inventory-unable_to_inspect_item_not_in_db", itemTpl)
_localisationService.GetText(
"inventory-unable_to_inspect_item_not_in_db",
itemTpl
)
);
return;
}
fullProfile.CharacterData.PmcData.Info.Experience += item.Value.Properties.ExamineExperience;
fullProfile.CharacterData.PmcData.Info.Experience += item.Value
.Properties
.ExamineExperience;
fullProfile.CharacterData.PmcData.Encyclopedia[itemTpl] = false;
fullProfile.CharacterData.ScavData.Info.Experience += item.Value.Properties.ExamineExperience;
fullProfile.CharacterData.ScavData.Info.Experience += item.Value
.Properties
.ExamineExperience;
fullProfile.CharacterData.ScavData.Encyclopedia[itemTpl] = false;
}
@@ -291,8 +347,12 @@ public class InventoryController(
/// <param name="request"></param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void OpenRandomLootContainer(PmcData pmcData, OpenRandomLootContainerRequestData request, string sessionId,
ItemEventRouterResponse output)
public void OpenRandomLootContainer(
PmcData pmcData,
OpenRandomLootContainerRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
// Container player opened in their inventory
var openedItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
@@ -305,7 +365,7 @@ public class InventoryController(
{
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_VIOLET_OPEN,
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_BLUE_OPEN,
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_GREEN_OPEN
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_GREEN_OPEN,
};
// Temp fix for unlocked weapon crate hideout craft
if (isSealedWeaponBox || unlockedWeaponCrates.Contains(containerDetailsDb.Value.Id))
@@ -320,10 +380,14 @@ public class InventoryController(
}
else
{
var rewardContainerDetails = _inventoryHelper.GetRandomLootContainerRewardDetails(openedItem.Template);
var rewardContainerDetails = _inventoryHelper.GetRandomLootContainerRewardDetails(
openedItem.Template
);
if (rewardContainerDetails?.RewardCount == null)
{
_logger.Error($"Unable to add loot to container: {openedItem.Template}, no rewards found");
_logger.Error(
$"Unable to add loot to container: {openedItem.Template}, no rewards found"
);
}
else
{
@@ -344,7 +408,7 @@ public class InventoryController(
ItemsWithModsToAdd = rewards,
FoundInRaid = foundInRaid,
Callback = null,
UseSortingTable = true
UseSortingTable = true,
};
_inventoryHelper.AddItemsToStash(sessionId, addItemsRequest, pmcData, output);
if (output.Warnings?.Count > 0)
@@ -364,8 +428,12 @@ public class InventoryController(
/// <param name="request">Edit marker request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void EditMapMarker(PmcData pmcData, InventoryEditMarkerRequestData request, string sessionId,
ItemEventRouterResponse output)
public void EditMapMarker(
PmcData pmcData,
InventoryEditMarkerRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
var mapItem = _mapMarkerService.EditMarkerOnMap(pmcData, request);
@@ -380,8 +448,12 @@ public class InventoryController(
/// <param name="request">Delete marker request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void DeleteMapMarker(PmcData pmcData, InventoryDeleteMarkerRequestData request, string sessionId,
ItemEventRouterResponse output)
public void DeleteMapMarker(
PmcData pmcData,
InventoryDeleteMarkerRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
var mapItem = _mapMarkerService.DeleteMarkerFromMap(pmcData, request);
@@ -389,8 +461,12 @@ public class InventoryController(
output.ProfileChanges[sessionId].Items.ChangedItems.Add(mapItem);
}
public void CreateMapMarker(PmcData pmcData, InventoryCreateMarkerRequestData request, string sessionId,
ItemEventRouterResponse output)
public void CreateMapMarker(
PmcData pmcData,
InventoryCreateMarkerRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
var adjustedMapItem = _mapMarkerService.CreateMarkerOnMap(pmcData, request);
@@ -405,16 +481,25 @@ public class InventoryController(
/// <param name="request">Add marker request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void SortInventory(PmcData pmcData, InventorySortRequestData request, string sessionId,
ItemEventRouterResponse output)
public void SortInventory(
PmcData pmcData,
InventorySortRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
foreach (var change in request.ChangedItems)
{
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == change.Id);
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item =>
item.Id == change.Id
);
if (inventoryItem is null)
{
_logger.Error(
_localisationService.GetText("inventory-unable_to_sort_inventory_restart_game", change.Id)
_localisationService.GetText(
"inventory-unable_to_sort_inventory_restart_game",
change.Id
)
);
continue;
@@ -440,8 +525,11 @@ public class InventoryController(
/// <param name="request"></param>
/// <param name="sessionId">Session/Player id</param>
/// <returns></returns>
public ItemEventRouterResponse ReadEncyclopedia(PmcData pmcData, InventoryReadEncyclopediaRequestData request,
string sessionId)
public ItemEventRouterResponse ReadEncyclopedia(
PmcData pmcData,
InventoryReadEncyclopediaRequestData request,
string sessionId
)
{
foreach (var id in request.Ids)
{
@@ -458,8 +546,12 @@ public class InventoryController(
/// <param name="request">Examine item request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void ExamineItem(PmcData pmcData, InventoryExamineRequestData request, string sessionId,
ItemEventRouterResponse output)
public void ExamineItem(
PmcData pmcData,
InventoryExamineRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
string? itemId = null;
if (request.FromOwner is not null)
@@ -470,12 +562,17 @@ public class InventoryController(
}
catch
{
_logger.Error(_localisationService.GetText("inventory-examine_item_does_not_exist", request.Item));
_logger.Error(
_localisationService.GetText(
"inventory-examine_item_does_not_exist",
request.Item
)
);
}
}
if (itemId is null)
// item template
// item template
{
if (_databaseService.GetItems().ContainsKey(request.Item))
{
@@ -514,14 +611,17 @@ public class InventoryController(
}
if (request.FromOwner.Id == Traders.FENCE)
// Get tpl from fence assorts
// Get tpl from fence assorts
{
return _fenceService.GetRawFenceAssorts().Items.FirstOrDefault(x => x.Id == request.Item)?.Template;
return _fenceService
.GetRawFenceAssorts()
.Items.FirstOrDefault(x => x.Id == request.Item)
?.Template;
}
if (request.FromOwner.Type == "Trader")
// Not fence
// get tpl from trader assort
// Not fence
// get tpl from trader assort
{
return _databaseService
.GetTrader(request.FromOwner.Id)
@@ -539,18 +639,23 @@ public class InventoryController(
}
// Try alternate way of getting offer if first approach fails
var offer = _ragfairOfferService.GetOfferByOfferId(request.Item) ??
_ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id);
var offer =
_ragfairOfferService.GetOfferByOfferId(request.Item)
?? _ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id);
// Try find examine item inside offer items array
var matchingItem = offer.Items.FirstOrDefault(offerItem => offerItem.Id == request.Item);
var matchingItem = offer.Items.FirstOrDefault(offerItem =>
offerItem.Id == request.Item
);
if (matchingItem is not null)
{
return matchingItem.Template;
}
// Unable to find item in database or ragfair
_logger.Warning(_localisationService.GetText("inventory-unable_to_find_item", request.Item));
_logger.Warning(
_localisationService.GetText("inventory-unable_to_find_item", request.Item)
);
}
// get hideout item
@@ -565,7 +670,9 @@ public class InventoryController(
// all mail the player has
var mail = _profileHelper.GetFullProfile(sessionId).DialogueRecords;
// per trader/person mail
var dialogue = mail.FirstOrDefault(x => x.Value.Messages.Any(m => m.Id == request.FromOwner.Id));
var dialogue = mail.FirstOrDefault(x =>
x.Value.Messages.Any(m => m.Id == request.FromOwner.Id)
);
// check each message from that trader/person for messages that match the ID we got
var message = dialogue.Value.Messages.FirstOrDefault(m => m.Id == request.FromOwner.Id);
// get the Id given and get the Template ID from that
@@ -590,8 +697,12 @@ public class InventoryController(
/// <param name="request"></param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void UnBindItem(PmcData pmcData, InventoryBindRequestData request, string sessionId,
ItemEventRouterResponse output)
public void UnBindItem(
PmcData pmcData,
InventoryBindRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
// Remove kvp from requested fast panel index
@@ -607,8 +718,12 @@ public class InventoryController(
/// <param name="bindRequest"></param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void BindItem(PmcData pmcData, InventoryBindRequestData bindRequest, string sessionId,
ItemEventRouterResponse output)
public void BindItem(
PmcData pmcData,
InventoryBindRequestData bindRequest,
string sessionId,
ItemEventRouterResponse output
)
{
// Remove link
if (pmcData.Inventory.FastPanel.ContainsKey(bindRequest.Index))
@@ -627,7 +742,11 @@ public class InventoryController(
/// <param name="request"></param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse TagItem(PmcData pmcData, InventoryTagRequestData request, string sessionId)
public ItemEventRouterResponse TagItem(
PmcData pmcData,
InventoryTagRequestData request,
string sessionId
)
{
var itemToTag = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
if (itemToTag is null)
@@ -636,20 +755,13 @@ public class InventoryController(
$"Unable to tag item: {request.Item} as it cannot be found in player {sessionId} inventory"
);
return new ItemEventRouterResponse
{
Warnings = []
};
return new ItemEventRouterResponse { Warnings = [] };
}
// Null guard
itemToTag.Upd ??= new Upd();
itemToTag.Upd.Tag = new UpdTag
{
Color = request.TagColor,
Name = request.TagName
};
itemToTag.Upd.Tag = new UpdTag { Color = request.TagColor, Name = request.TagName };
return _eventOutputHolder.GetOutput(sessionId);
}
@@ -661,7 +773,11 @@ public class InventoryController(
/// <param name="request">Toggle request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse ToggleItem(PmcData pmcData, InventoryToggleRequestData request, string sessionId)
public ItemEventRouterResponse ToggleItem(
PmcData pmcData,
InventoryToggleRequestData request,
string sessionId
)
{
// May need to reassign to scav profile
var playerData = pmcData;
@@ -677,23 +793,22 @@ public class InventoryController(
{
_itemHelper.AddUpdObjectToItem(
itemToToggle,
_localisationService.GetText("inventory-item_to_toggle_missing_upd", itemToToggle.Id)
_localisationService.GetText(
"inventory-item_to_toggle_missing_upd",
itemToToggle.Id
)
);
itemToToggle.Upd.Togglable = new UpdTogglable
{
On = request.Value
};
itemToToggle.Upd.Togglable = new UpdTogglable { On = request.Value };
return _eventOutputHolder.GetOutput(sessionId);
}
_logger.Warning(_localisationService.GetText("inventory-unable_to_toggle_item_not_found", request.Item));
_logger.Warning(
_localisationService.GetText("inventory-unable_to_toggle_item_not_found", request.Item)
);
return new ItemEventRouterResponse
{
Warnings = []
};
return new ItemEventRouterResponse { Warnings = [] };
}
/// <summary>
@@ -703,7 +818,11 @@ public class InventoryController(
/// <param name="request">Fold item request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse FoldItem(PmcData pmcData, InventoryFoldRequestData request, string sessionId)
public ItemEventRouterResponse FoldItem(
PmcData pmcData,
InventoryFoldRequestData request,
string sessionId
)
{
// May need to reassign to scav profile
var playerData = pmcData;
@@ -714,27 +833,26 @@ public class InventoryController(
playerData = _profileHelper.GetScavProfile(sessionId);
}
var itemToFold = playerData.Inventory.Items.FirstOrDefault(item => item?.Id == request.Item);
var itemToFold = playerData.Inventory.Items.FirstOrDefault(item =>
item?.Id == request.Item
);
if (itemToFold is null)
{
// Item not found
_logger.Warning(
_localisationService.GetText("inventory-unable_to_fold_item_not_found_in_inventory", request.Item)
_localisationService.GetText(
"inventory-unable_to_fold_item_not_found_in_inventory",
request.Item
)
);
return new ItemEventRouterResponse
{
Warnings = []
};
return new ItemEventRouterResponse { Warnings = [] };
}
// Item may not have upd object
_itemHelper.AddUpdObjectToItem(itemToFold);
itemToFold.Upd.Foldable = new UpdFoldable
{
Folded = request.Value
};
itemToFold.Upd.Foldable = new UpdFoldable { Folded = request.Value };
return _eventOutputHolder.GetOutput(sessionId);
}
@@ -748,7 +866,11 @@ public class InventoryController(
/// <param name="request">Swap item request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse SwapItem(PmcData pmcData, InventorySwapRequestData request, string sessionId)
public ItemEventRouterResponse SwapItem(
PmcData pmcData,
InventorySwapRequestData request,
string sessionId
)
{
// During post-raid scav transfer, the swap may be in the scav inventory
var playerData = pmcData;
@@ -763,11 +885,7 @@ public class InventoryController(
_logger.Error(
_localisationService.GetText(
"inventory-unable_to_find_item_to_swap",
new
{
item1Id = request.Item,
item2Id = request.Item2
}
new { item1Id = request.Item, item2Id = request.Item2 }
)
);
}
@@ -778,11 +896,7 @@ public class InventoryController(
_logger.Error(
_localisationService.GetText(
"inventory-unable_to_find_item_to_swap",
new
{
item1Id = request.Item2,
item2Id = request.Item
}
new { item1Id = request.Item2, item2Id = request.Item }
)
);
}
@@ -827,11 +941,19 @@ public class InventoryController(
/// <param name="request">Transfer item request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void TransferItem(PmcData pmcData, InventoryTransferRequestData request, string sessionId,
ItemEventRouterResponse output)
public void TransferItem(
PmcData pmcData,
InventoryTransferRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
// TODO - check GetOwnerInventoryItems() call still works
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionId);
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
request,
request.Item,
sessionId
);
var sourceItem = inventoryItems.From.FirstOrDefault(item => item.Id == request.Item);
var destinationItem = inventoryItems.To.FirstOrDefault(item => item.Id == request.With);
@@ -855,27 +977,21 @@ public class InventoryController(
return;
}
sourceItem.Upd ??= new Upd
{
StackObjectsCount = 1
};
sourceItem.Upd ??= new Upd { StackObjectsCount = 1 };
var sourceStackCount = sourceItem.Upd.StackObjectsCount;
if (sourceStackCount > request.Count)
// Source items stack count greater than new desired count
// Source items stack count greater than new desired count
{
sourceItem.Upd.StackObjectsCount = sourceStackCount - request.Count;
}
else
// Moving a full stack onto a smaller stack
// Moving a full stack onto a smaller stack
{
sourceItem.Upd.StackObjectsCount = sourceStackCount - 1;
}
destinationItem.Upd ??= new Upd
{
StackObjectsCount = 1
};
destinationItem.Upd ??= new Upd { StackObjectsCount = 1 };
var destinationStackCount = destinationItem.Upd.StackObjectsCount;
destinationItem.Upd.StackObjectsCount = destinationStackCount + request.Count;
@@ -889,17 +1005,26 @@ public class InventoryController(
/// <param name="request">Merge stacks request</param>
/// <param name="sessionID">Session/Player id</param>
/// <param name="output">Client response</param>
public void MergeItem(PmcData pmcData, InventoryMergeRequestData request, string sessionID,
ItemEventRouterResponse output)
public void MergeItem(
PmcData pmcData,
InventoryMergeRequestData request,
string sessionID,
ItemEventRouterResponse output
)
{
// Changes made to result apply to character inventory
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionID);
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
request,
request.Item,
sessionID
);
// Get source item (can be from player or trader or mail)
var sourceItem = inventoryItems.From.FirstOrDefault(x => x.Id == request.Item);
if (sourceItem is null)
{
var errorMessage = $"Unable to merge stacks as source item: {request.With} cannot be found";
var errorMessage =
$"Unable to merge stacks as source item: {request.With} cannot be found";
_logger.Error(errorMessage);
_httpResponseUtil.AppendErrorToOutput(output, errorMessage);
@@ -911,7 +1036,8 @@ public class InventoryController(
var destinationItem = inventoryItems.To.FirstOrDefault(x => x.Id == request.With);
if (destinationItem is null)
{
var errorMessage = $"Unable to merge stacks as destination item: {request.With} cannot be found";
var errorMessage =
$"Unable to merge stacks as destination item: {request.With} cannot be found";
_logger.Error(errorMessage);
_httpResponseUtil.AppendErrorToOutput(output, errorMessage);
@@ -920,48 +1046,38 @@ public class InventoryController(
}
if (destinationItem.Upd?.StackObjectsCount is null)
// No stackcount on destination, add one
// No stackcount on destination, add one
{
destinationItem.Upd = new Upd
{
StackObjectsCount = 1
};
destinationItem.Upd = new Upd { StackObjectsCount = 1 };
}
if (sourceItem.Upd is null)
{
sourceItem.Upd = new Upd
{
StackObjectsCount = 1
};
sourceItem.Upd = new Upd { StackObjectsCount = 1 };
}
else if (sourceItem.Upd.StackObjectsCount is null)
// Items pulled out of raid can have no stack count if the stack should be 1
// Items pulled out of raid can have no stack count if the stack should be 1
{
sourceItem.Upd.StackObjectsCount = 1;
}
// Remove FiR status from destination stack when source stack has no FiR but destination does
if (!sourceItem.Upd.SpawnedInSession.GetValueOrDefault(false) &&
destinationItem.Upd.SpawnedInSession.GetValueOrDefault(false))
if (
!sourceItem.Upd.SpawnedInSession.GetValueOrDefault(false)
&& destinationItem.Upd.SpawnedInSession.GetValueOrDefault(false)
)
{
destinationItem.Upd.SpawnedInSession = false;
}
destinationItem.Upd.StackObjectsCount +=
sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
output.ProfileChanges[sessionID]
.Items.DeletedItems.Add(
new Item
{
Id = sourceItem.Id
}
); // Inform client source item being deleted
destinationItem.Upd.StackObjectsCount += sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
output.ProfileChanges[sessionID].Items.DeletedItems.Add(new Item { Id = sourceItem.Id }); // Inform client source item being deleted
var indexOfItemToRemove = inventoryItems.From.FindIndex(x => x.Id == sourceItem.Id);
if (indexOfItemToRemove == -1)
{
var errorMessage = $"Unable to find item: {sourceItem.Id} to remove from sender inventory";
var errorMessage =
$"Unable to find item: {sourceItem.Id} to remove from sender inventory";
_logger.Error(errorMessage);
_httpResponseUtil.AppendErrorToOutput(output, errorMessage);
@@ -979,11 +1095,19 @@ public class InventoryController(
/// <param name="request">Split stack request</param>
/// <param name="sessionID">Session/Player id</param>
/// <param name="output">Client response</param>
public void SplitItem(PmcData pmcData, InventorySplitRequestData request, string sessionID,
ItemEventRouterResponse output)
public void SplitItem(
PmcData pmcData,
InventorySplitRequestData request,
string sessionID,
ItemEventRouterResponse output
)
{
// Changes made to result apply to character inventory
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.NewItem, sessionID);
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
request,
request.NewItem,
sessionID
);
// Handle cartridge edge-case
if (request.Container.Location is null && request.Container.ContainerName == "cartridges")
@@ -996,7 +1120,8 @@ public class InventoryController(
var itemToSplit = inventoryItems.From.FirstOrDefault(x => x.Id == request.SplitItem);
if (itemToSplit is null)
{
var errorMessage = $"Unable to split stack as source item: {request.SplitItem} cannot be found";
var errorMessage =
$"Unable to split stack as source item: {request.SplitItem} cannot be found";
_logger.Error(errorMessage);
_httpResponseUtil.AppendErrorToOutput(output, errorMessage);
@@ -1012,13 +1137,14 @@ public class InventoryController(
itemToSplit.Upd.StackObjectsCount -= request.Count;
// Inform client of change
output.ProfileChanges[sessionID]
output
.ProfileChanges[sessionID]
.Items.NewItems.Add(
new Item
{
Id = request.NewItem,
Template = itemToSplit.Template,
Upd = updatedUpd
Upd = updatedUpd,
}
);
@@ -1031,7 +1157,7 @@ public class InventoryController(
ParentId = request.Container.Id,
SlotId = request.Container.ContainerName,
Location = request.Container.Location,
Upd = updatedUpd
Upd = updatedUpd,
}
);
}
@@ -1044,8 +1170,12 @@ public class InventoryController(
/// <param name="request">Discard item request</param>
/// <param name="sessionId">Session/Player id</param>
/// <param name="output">Client response</param>
public void DiscardItem(PmcData pmcData, InventoryRemoveRequestData request, string sessionId,
ItemEventRouterResponse output)
public void DiscardItem(
PmcData pmcData,
InventoryRemoveRequestData request,
string sessionId,
ItemEventRouterResponse output
)
{
if (request.FromOwner?.Type == "Mail")
{
@@ -1054,9 +1184,10 @@ public class InventoryController(
return;
}
var profileToRemoveItemFrom = request.FromOwner is null || request.FromOwner?.Id == pmcData.Id
? pmcData
: _profileHelper.GetFullProfile(sessionId).CharacterData.ScavData;
var profileToRemoveItemFrom =
request.FromOwner is null || request.FromOwner?.Id == pmcData.Id
? pmcData
: _profileHelper.GetFullProfile(sessionId).CharacterData.ScavData;
_inventoryHelper.RemoveItem(profileToRemoveItemFrom, request.Item, sessionId, output);
}
@@ -37,8 +37,11 @@ public class LauncherController(
public ConnectResponse Connect()
{
// Get all possible profile types + filter out any that are blacklisted
var profileTemplates = _databaseService.GetProfileTemplates()
.Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key))
var profileTemplates = _databaseService
.GetProfileTemplates()
.Where(profile =>
!_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key)
)
.ToDictionary();
return new ConnectResponse
@@ -46,7 +49,7 @@ public class LauncherController(
BackendUrl = _httpServerHelper.GetBackendUrl(),
Name = _coreConfig.ServerName,
Editions = profileTemplates.Select(x => x.Key).ToList(),
ProfileDescriptions = GetProfileDescriptions(profileTemplates)
ProfileDescriptions = GetProfileDescriptions(profileTemplates),
};
}
@@ -55,7 +58,9 @@ public class LauncherController(
/// </summary>
/// <param name="profileTemplates">Profiles to get descriptions of</param>
/// <returns>Dictionary of profile types with related descriptive text</returns>
protected Dictionary<string, string> GetProfileDescriptions(Dictionary<string, ProfileSides> profileTemplates)
protected Dictionary<string, string> GetProfileDescriptions(
Dictionary<string, ProfileSides> profileTemplates
)
{
var result = new Dictionary<string, string>();
foreach (var (profileKey, profile) in profileTemplates)
@@ -72,7 +77,11 @@ public class LauncherController(
/// <returns></returns>
public Info? Find(string? sessionId)
{
return sessionId is not null && _saveServer.GetProfiles().TryGetValue(sessionId, out var profile) ? profile.ProfileInfo : null;
return
sessionId is not null
&& _saveServer.GetProfiles().TryGetValue(sessionId, out var profile)
? profile.ProfileInfo
: null;
}
/// <summary>
@@ -126,7 +135,7 @@ public class LauncherController(
Username = info.Username,
Password = info.Password,
IsWiped = true,
Edition = info.Edition
Edition = info.Edition,
};
_saveServer.CreateProfile(newProfileDetails);
@@ -229,7 +238,10 @@ public class LauncherController(
/// <returns>Dictionary of mod name and mod details</returns>
public Dictionary<string, AbstractModMetadata> GetLoadedServerMods()
{
return _loadedMods.ToDictionary(sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD", sptMod => sptMod.ModMetadata);
return _loadedMods.ToDictionary(
sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD",
sptMod => sptMod.ModMetadata
);
}
/// <summary>
@@ -48,7 +48,10 @@ public class LauncherV2Controller(
foreach (var profileKvP in dbProfiles)
{
result.TryAdd(profileKvP.Key, _localisationService.GetText(profileKvP.Value.DescriptionLocaleKey));
result.TryAdd(
profileKvP.Key,
_localisationService.GetText(profileKvP.Value.DescriptionLocaleKey)
);
}
return result;
@@ -174,7 +177,7 @@ public class LauncherV2Controller(
Username = info.Username,
Password = info.Password,
IsWiped = true,
Edition = info.Edition
Edition = info.Edition,
};
_saveServer.CreateProfile(newProfileDetails);
@@ -204,7 +207,10 @@ public class LauncherV2Controller(
{
foreach (var profile in _saveServer.GetProfiles())
{
if (info.Username == profile.Value.ProfileInfo!.Username && info.Password == profile.Value.ProfileInfo.Password)
if (
info.Username == profile.Value.ProfileInfo!.Username
&& info.Password == profile.Value.ProfileInfo.Password
)
{
return profile.Key;
}
@@ -7,7 +7,6 @@ using SPTarkov.Server.Core.Services;
using SPTarkov.Server.Core.Utils.Cloners;
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
@@ -54,7 +53,7 @@ public class LocationController(
return new LocationsGenerateAllResponse
{
Locations = locationResult,
Paths = locationsFromDb.Base!.Paths
Paths = locationsFromDb.Base!.Paths,
};
}
@@ -70,9 +70,9 @@ public class MatchController(
RaidMode = "Online",
Mode = "deathmatch",
ShortId = null,
AdditionalInfo = null
}
]
AdditionalInfo = null,
},
],
};
return output;
@@ -85,11 +85,7 @@ public class MatchController(
/// <returns>MatchGroupStatusResponse</returns>
public MatchGroupStatusResponse GetGroupStatus(MatchGroupStatusRequest request)
{
return new MatchGroupStatusResponse
{
Players = [],
MaxPveCountExceeded = false
};
return new MatchGroupStatusResponse { Players = [], MaxPveCountExceeded = false };
}
/// <summary>
@@ -138,7 +134,10 @@ public class MatchController(
/// <param name="sessionId">Session/Player id</param>
/// <param name="request">Start raid request</param>
/// <returns>StartLocalRaidResponseData</returns>
public StartLocalRaidResponseData StartLocalRaid(string sessionId, StartLocalRaidRequestData request)
public StartLocalRaidResponseData StartLocalRaid(
string sessionId,
StartLocalRaidRequestData request
)
{
return _locationLifecycleService.StartLocalRaid(sessionId, request);
}
@@ -7,9 +7,7 @@ using SPTarkov.Server.Core.Routers;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
public class NoteController(
EventOutputHolder _eventOutputHolder
)
public class NoteController(EventOutputHolder _eventOutputHolder)
{
/// <summary>
/// </summary>
@@ -20,13 +18,10 @@ public class NoteController(
public ItemEventRouterResponse AddNote(
PmcData pmcData,
NoteActionRequest request,
string sessionId)
string sessionId
)
{
var newNote = new Note
{
Time = request.Note.Time,
Text = request.Note.Text
};
var newNote = new Note { Time = request.Note.Time, Text = request.Note.Text };
pmcData.Notes.DataNotes.Add(newNote);
return _eventOutputHolder.GetOutput(sessionId);
@@ -41,7 +36,8 @@ public class NoteController(
public ItemEventRouterResponse EditNote(
PmcData pmcData,
NoteActionRequest request,
string sessionId)
string sessionId
)
{
var noteToEdit = pmcData.Notes.DataNotes[request.Index!.Value];
noteToEdit.Time = request.Note.Time;
@@ -59,7 +55,8 @@ public class NoteController(
public ItemEventRouterResponse DeleteNote(
PmcData pmcData,
NoteActionRequest request,
string sessionId)
string sessionId
)
{
pmcData.Notes?.DataNotes?.RemoveAt(request.Index!.Value);
@@ -63,7 +63,7 @@ public class NotifierController(
ChannelId = sessionId,
Url = "",
NotifierServer = GetServer(sessionId),
WebSocket = _notifierHelper.GetWebSocketServer(sessionId)
WebSocket = _notifierHelper.GetWebSocketServer(sessionId),
};
}
@@ -33,10 +33,7 @@ public class PresetController(
// Get root items tpl
var tpl = preset.Items.FirstOrDefault()?.Template;
result.TryAdd(tpl, new PresetCacheDetails
{
PresetIds = []
});
result.TryAdd(tpl, new PresetCacheDetails { PresetIds = [] });
result.TryGetValue(tpl, out var details);
details.PresetIds.Add(presetId);
@@ -23,8 +23,7 @@ public class PrestigeController(
/// </summary>
/// <param name="sessionId">Session/Player id</param>
/// <returns>Prestige</returns>
public Prestige GetPrestige(
string sessionId)
public Prestige GetPrestige(string sessionId)
{
return _databaseService.GetTemplates().Prestige;
}
@@ -59,9 +58,7 @@ public class PrestigeController(
/// </list>
/// </summary>
/// <returns></returns>
public async Task ObtainPrestige(
string sessionId,
ObtainPrestigeRequestList request)
public async Task ObtainPrestige(string sessionId, ObtainPrestigeRequestList request)
{
var profile = _profileHelper.GetFullProfile(sessionId);
if (profile is not null)
@@ -69,7 +66,7 @@ public class PrestigeController(
var pendingPrestige = new PendingPrestige
{
PrestigeLevel = profile.CharacterData.PmcData.Info.PrestigeLevel + 1,
Items = request
Items = request,
};
profile.SptData.PendingPrestige = pendingPrestige;
@@ -57,7 +57,9 @@ public class ProfileController(
var profile = _saveServer.GetProfile(sessionId);
if (profile?.CharacterData == null)
{
throw new Exception($"Unable to find character data for id: {sessionId}. Profile may be corrupt");
throw new Exception(
$"Unable to find character data for id: {sessionId}. Profile may be corrupt"
);
}
var pmc = profile.CharacterData.PmcData;
@@ -81,7 +83,7 @@ public class ProfileController(
MaxLevel = maxLvl,
Edition = profile.ProfileInfo?.Edition ?? "",
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
SptData = _profileHelper.GetDefaultSptDataObject()
SptData = _profileHelper.GetDefaultSptDataObject(),
};
}
@@ -93,12 +95,13 @@ public class ProfileController(
Side = pmc.Info.Side,
CurrentLevel = pmc.Info.Level,
CurrentExperience = pmc.Info.Experience ?? 0,
PreviousExperience = currentLevel == 0 ? 0 : _profileHelper.GetExperience(currentLevel.Value),
PreviousExperience =
currentLevel == 0 ? 0 : _profileHelper.GetExperience(currentLevel.Value),
NextLevel = xpToNextLevel,
MaxLevel = maxLvl,
Edition = profile.ProfileInfo?.Edition ?? "",
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
SptData = profile.SptData
SptData = profile.SptData,
};
}
@@ -118,7 +121,10 @@ public class ProfileController(
/// <param name="request">Create profile request</param>
/// <param name="sessionId">Player id</param>
/// <returns>Player id</returns>
public virtual async ValueTask<string> CreateProfile(ProfileCreateRequestData request, string sessionId)
public virtual async ValueTask<string> CreateProfile(
ProfileCreateRequestData request,
string sessionId
)
{
return await _createProfileService.CreateProfile(sessionId, request);
}
@@ -140,7 +146,10 @@ public class ProfileController(
/// <param name="request">Validate nickname request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns></returns>
public virtual NicknameValidationResult ValidateNickname(ValidateNicknameRequestData request, string sessionId)
public virtual NicknameValidationResult ValidateNickname(
ValidateNicknameRequestData request,
string sessionId
)
{
if (request.Nickname?.Length < 3)
{
@@ -162,13 +171,13 @@ public class ProfileController(
/// <param name="request">Change nickname request</param>
/// <param name="sessionId">Player id</param>
/// <returns></returns>
public virtual NicknameValidationResult ChangeNickname(ProfileChangeNicknameRequestData request, string sessionId)
public virtual NicknameValidationResult ChangeNickname(
ProfileChangeNicknameRequestData request,
string sessionId
)
{
var output = ValidateNickname(
new ValidateNicknameRequestData
{
Nickname = request.Nickname
},
new ValidateNicknameRequestData { Nickname = request.Nickname },
sessionId
);
@@ -200,7 +209,10 @@ public class ProfileController(
/// <param name="request">Search profiles request</param>
/// <param name="sessionID">Player id</param>
/// <returns>Found profiles</returns>
public virtual List<SearchFriendResponse> SearchProfiles(SearchProfilesRequestData request, string sessionID)
public virtual List<SearchFriendResponse> SearchProfiles(
SearchProfilesRequestData request,
string sessionID
)
{
var result = new List<SearchFriendResponse>();
@@ -241,7 +253,7 @@ public class ProfileController(
Status = "Free",
Sid = "",
Ip = "",
Port = 0
Port = 0,
},
new ProfileStatusData
{
@@ -250,9 +262,9 @@ public class ProfileController(
Status = "Free",
Sid = "",
Ip = "",
Port = 0
}
]
Port = 0,
},
],
};
return response;
@@ -264,13 +276,21 @@ public class ProfileController(
/// <param name="sessionId">Session/Player id</param>
/// <param name="request">Get other profile request</param>
/// <returns>GetOtherProfileResponse</returns>
public virtual GetOtherProfileResponse GetOtherProfile(string sessionId, GetOtherProfileRequest request)
public virtual GetOtherProfileResponse GetOtherProfile(
string sessionId,
GetOtherProfileRequest request
)
{
// Find the profile by the account ID, fall back to the current player if we can't find the account
var profileToView = _profileHelper.GetFullProfileByAccountId(request.AccountId);
if (profileToView?.CharacterData?.PmcData is null || profileToView.CharacterData.ScavData is null)
if (
profileToView?.CharacterData?.PmcData is null
|| profileToView.CharacterData.ScavData is null
)
{
_logger.Warning($"Unable to get profile: {request.AccountId} to show, falling back to own profile");
_logger.Warning(
$"Unable to get profile: {request.AccountId} to show, falling back to own profile"
);
profileToView = _profileHelper.GetFullProfile(sessionId);
}
@@ -283,12 +303,17 @@ public class ProfileController(
hideoutKeys.Add(profileToViewPmc.Inventory.HideoutCustomizationStashId);
// Find hideout items e.g. posters
var hideoutRootItems = profileToViewPmc.Inventory.Items.Where(x => hideoutKeys.Contains(x.Id));
var hideoutRootItems = profileToViewPmc.Inventory.Items.Where(x =>
hideoutKeys.Contains(x.Id)
);
var itemsToReturn = new List<Item>();
foreach (var rootItems in hideoutRootItems)
{
// Check each root items for children and add
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(profileToViewPmc.Inventory.Items, rootItems.Id);
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(
profileToViewPmc.Inventory.Items,
rootItems.Id
);
itemsToReturn.AddRange(itemWithChildren);
}
@@ -301,10 +326,12 @@ public class ProfileController(
Nickname = profileToViewPmc.Info.Nickname,
Side = profileToViewPmc.Info.Side,
Experience = profileToViewPmc.Info.Experience,
MemberCategory = (int)(profileToViewPmc.Info.MemberCategory ?? MemberCategory.Default),
MemberCategory = (int)(
profileToViewPmc.Info.MemberCategory ?? MemberCategory.Default
),
BannedState = profileToViewPmc.Info.BannedState,
BannedUntil = profileToViewPmc.Info.BannedUntil,
RegistrationDate = profileToViewPmc.Info.RegistrationDate
RegistrationDate = profileToViewPmc.Info.RegistrationDate,
},
Customization = new OtherProfileCustomization
{
@@ -312,13 +339,13 @@ public class ProfileController(
Body = profileToViewPmc.Customization.Body,
Feet = profileToViewPmc.Customization.Feet,
Hands = profileToViewPmc.Customization.Hands,
Dogtag = profileToViewPmc.Customization.DogTag
Dogtag = profileToViewPmc.Customization.DogTag,
},
Skills = profileToViewPmc.Skills,
Equipment = new OtherProfileEquipment
{
Id = profileToViewPmc.Inventory.Equipment,
Items = profileToViewPmc.Inventory.Items
Items = profileToViewPmc.Inventory.Items,
},
Achievements = profileToViewPmc.Achievements,
FavoriteItems = _profileHelper.GetOtherProfileFavorites(profileToViewPmc),
@@ -327,21 +354,21 @@ public class ProfileController(
Eft = new OtherProfileSubStats
{
TotalInGameTime = profileToViewPmc.Stats.Eft.TotalInGameTime,
OverAllCounters = profileToViewPmc.Stats.Eft.OverallCounters
}
OverAllCounters = profileToViewPmc.Stats.Eft.OverallCounters,
},
},
ScavStats = new OtherProfileStats
{
Eft = new OtherProfileSubStats
{
TotalInGameTime = profileToViewScav.Stats.Eft.TotalInGameTime,
OverAllCounters = profileToViewScav.Stats.Eft.OverallCounters
}
OverAllCounters = profileToViewScav.Stats.Eft.OverallCounters,
},
},
Hideout = profileToViewPmc.Hideout,
CustomizationStash = profileToViewPmc.Inventory.HideoutCustomizationStashId,
HideoutAreaStashes = profileToViewPmc.Inventory.HideoutAreaStashes,
Items = itemsToReturn
Items = itemsToReturn,
};
return profile;
@@ -14,7 +14,6 @@ using SPTarkov.Server.Core.Utils;
using SPTarkov.Server.Core.Utils.Cloners;
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
@@ -63,13 +62,19 @@ public class QuestController(
/// <param name="acceptedQuest">Quest accepted</param>
/// <param name="sessionID">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse AcceptQuest(PmcData pmcData, AcceptQuestRequestData acceptedQuest, string sessionID)
public ItemEventRouterResponse AcceptQuest(
PmcData pmcData,
AcceptQuestRequestData acceptedQuest,
string sessionID
)
{
var acceptQuestResponse = _eventOutputHolder.GetOutput(sessionID);
// Does quest exist in profile
// Restarting a failed quest can mean quest exists in profile
var existingQuestStatus = pmcData.Quests.FirstOrDefault(x => x.QId == acceptedQuest.QuestId);
var existingQuestStatus = pmcData.Quests.FirstOrDefault(x =>
x.QId == acceptedQuest.QuestId
);
if (existingQuestStatus is not null)
{
// Update existing
@@ -81,7 +86,11 @@ public class QuestController(
else
{
// Add new quest to server profile
var newQuest = _questHelper.GetQuestReadyForProfile(pmcData, QuestStatusEnum.Started, acceptedQuest);
var newQuest = _questHelper.GetQuestReadyForProfile(
pmcData,
QuestStatusEnum.Started,
acceptedQuest
);
pmcData.Quests.Add(newQuest);
}
@@ -94,10 +103,10 @@ public class QuestController(
AddTaskConditionCountersToProfile(
questFromDb.Conditions.AvailableForFinish,
pmcData,
acceptedQuest.QuestId);
acceptedQuest.QuestId
);
}
// Get messageId of text to send to player as text message in game
var messageId = _questHelper.GetMessageIdForQuestStart(
questFromDb.StartedMessageText,
@@ -120,7 +129,9 @@ public class QuestController(
MessageType.QuestStart,
messageId,
startedQuestRewardItems.ToList(),
_timeUtil.GetHoursAsSeconds((int) _questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData))
_timeUtil.GetHoursAsSeconds(
(int)_questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData)
)
);
// Having accepted new quest, look for newly unlocked quests and inform client of them
@@ -142,7 +153,11 @@ public class QuestController(
/// <param name="questConditions">Conditions to iterate over and possibly add to profile</param>
/// <param name="pmcData">Players PMC profile</param>
/// <param name="questId">Quest where conditions originated</param>
protected void AddTaskConditionCountersToProfile(List<QuestCondition> questConditions, PmcData pmcData, string questId)
protected void AddTaskConditionCountersToProfile(
List<QuestCondition> questConditions,
PmcData pmcData,
string questId
)
{
foreach (var condition in questConditions)
{
@@ -161,7 +176,7 @@ public class QuestController(
Id = condition.Id,
SourceId = questId,
Type = condition.ConditionType,
Value = 0
Value = 0,
};
break;
}
@@ -178,7 +193,11 @@ public class QuestController(
/// <param name="request">Complete quest request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse CompleteQuest(PmcData pmcData, CompleteQuestRequestData request, string sessionId)
public ItemEventRouterResponse CompleteQuest(
PmcData pmcData,
CompleteQuestRequestData request,
string sessionId
)
{
return _questHelper.CompleteQuest(pmcData, request, sessionId);
}
@@ -191,7 +210,11 @@ public class QuestController(
/// <param name="request">Handover request</param>
/// <param name="sessionID">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse HandoverQuest(PmcData pmcData, HandoverQuestRequestData request, string sessionID)
public ItemEventRouterResponse HandoverQuest(
PmcData pmcData,
HandoverQuestRequestData request,
string sessionID
)
{
var quest = _questHelper.GetQuestFromDb(request.QuestId, pmcData);
List<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
@@ -202,7 +225,11 @@ public class QuestController(
// Decrement number of items handed in
QuestCondition? handoverRequirements = null;
foreach (var condition in quest.Conditions.AvailableForFinish.Where(condition => condition.Id == request.ConditionId))
foreach (
var condition in quest.Conditions.AvailableForFinish.Where(condition =>
condition.Id == request.ConditionId
)
)
{
// Not a handover quest type, skip
if (!handoverQuestTypes.Contains(condition.ConditionType))
@@ -216,7 +243,7 @@ public class QuestController(
if (pmcData.TaskConditionCounters.TryGetValue("ConditionId", out var counter))
{
handedInCount -= (int) (counter.Value ?? 0);
handedInCount -= (int)(counter.Value ?? 0);
if (handedInCount <= 0)
{
@@ -228,7 +255,7 @@ public class QuestController(
questId = request.QuestId,
conditionId = request.ConditionId,
profileCounter = counter.Value,
value = handedInCount
value = handedInCount,
}
)
);
@@ -242,15 +269,26 @@ public class QuestController(
if (isItemHandoverQuest && handedInCount == 0)
{
return ShowRepeatableQuestInvalidConditionError(request.QuestId, request.ConditionId, output);
return ShowRepeatableQuestInvalidConditionError(
request.QuestId,
request.ConditionId,
output
);
}
var totalItemCountToRemove = 0d;
foreach (var itemHandover in request.Items)
{
var matchingItemInProfile = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == itemHandover.Id);
if (!(matchingItemInProfile is not null && handoverRequirements.Target.List.Contains(matchingItemInProfile.Template)))
// Item handed in by player doesn't match what was requested
var matchingItemInProfile = pmcData.Inventory.Items.FirstOrDefault(item =>
item.Id == itemHandover.Id
);
if (
!(
matchingItemInProfile is not null
&& handoverRequirements.Target.List.Contains(matchingItemInProfile.Template)
)
)
// Item handed in by player doesn't match what was requested
{
return ShowQuestItemHandoverMatchError(
request,
@@ -261,7 +299,10 @@ public class QuestController(
}
// Remove the right quantity of given items
var itemCountToRemove = Math.Min(itemHandover.Count ?? 0, handedInCount - totalItemCountToRemove);
var itemCountToRemove = Math.Min(
itemHandover.Count ?? 0,
handedInCount - totalItemCountToRemove
);
totalItemCountToRemove += itemCountToRemove;
if (itemHandover.Count - itemCountToRemove > 0)
{
@@ -269,7 +310,7 @@ public class QuestController(
_questHelper.ChangeItemStack(
pmcData,
itemHandover.Id,
(int) (itemHandover.Count - itemCountToRemove),
(int)(itemHandover.Count - itemCountToRemove),
sessionID,
output
);
@@ -283,17 +324,16 @@ public class QuestController(
else
{
// Remove item with children
var toRemove = _itemHelper.FindAndReturnChildrenByItems(pmcData.Inventory.Items, itemHandover.Id);
var toRemove = _itemHelper.FindAndReturnChildrenByItems(
pmcData.Inventory.Items,
itemHandover.Id
);
var index = pmcData.Inventory.Items.Count;
// Important: don't tell the client to remove the attachments, it will handle it
output.ProfileChanges[sessionID]
.Items.DeletedItems.Add(
new Item
{
Id = itemHandover.Id
}
);
output
.ProfileChanges[sessionID]
.Items.DeletedItems.Add(new Item { Id = itemHandover.Id });
// Important: loop backward when removing items from the array we're looping on
while (index-- > 0)
@@ -315,7 +355,7 @@ public class QuestController(
childItems.RemoveAt(0); // Remove the parent
// Sort by the current `location` and update
childItems.Sort((a, b) => (int) a.Location > (int) b.Location ? 1 : -1);
childItems.Sort((a, b) => (int)a.Location > (int)b.Location ? 1 : -1);
for (var i = 0; i < childItems.Count; i++)
{
@@ -344,15 +384,15 @@ public class QuestController(
/// <param name="conditionId">Relevant condition id that failed</param>
/// <param name="output">Client response</param>
/// <returns>ItemEventRouterResponse</returns>
protected ItemEventRouterResponse ShowRepeatableQuestInvalidConditionError(string questId, string conditionId, ItemEventRouterResponse output)
protected ItemEventRouterResponse ShowRepeatableQuestInvalidConditionError(
string questId,
string conditionId,
ItemEventRouterResponse output
)
{
var errorMessage = _localisationService.GetText(
"repeatable-quest_handover_failed_condition_invalid",
new
{
questId,
conditionId
}
new { questId, conditionId }
);
_logger.Error(errorMessage);
@@ -367,8 +407,12 @@ public class QuestController(
/// <param name="handoverRequirements">Quest handover requirements</param>
/// <param name="output">Response to send to user</param>
/// <returns>ItemEventRouterResponse</returns>
protected ItemEventRouterResponse ShowQuestItemHandoverMatchError(HandoverQuestRequestData handoverQuestRequest, Item? itemHandedOver,
QuestCondition? handoverRequirements, ItemEventRouterResponse output)
protected ItemEventRouterResponse ShowQuestItemHandoverMatchError(
HandoverQuestRequestData handoverQuestRequest,
Item? itemHandedOver,
QuestCondition? handoverRequirements,
ItemEventRouterResponse output
)
{
var errorMessage = _localisationService.GetText(
"quest-handover_wrong_item",
@@ -376,7 +420,7 @@ public class QuestController(
{
questId = handoverQuestRequest.QuestId,
handedInTpl = itemHandedOver?.Template ?? "UNKNOWN",
requiredTpl = handoverRequirements.Target.List.FirstOrDefault()
requiredTpl = handoverRequirements.Target.List.FirstOrDefault(),
}
);
_logger.Error(errorMessage);
@@ -392,7 +436,12 @@ public class QuestController(
/// <param name="conditionId">Backend counter id to update</param>
/// <param name="questId">Quest id counter is associated with</param>
/// <param name="counterValue">Value to increment the backend counter with</param>
protected void UpdateProfileTaskConditionCounterValue(PmcData pmcData, string conditionId, string questId, double counterValue)
protected void UpdateProfileTaskConditionCounterValue(
PmcData pmcData,
string conditionId,
string questId,
double counterValue
)
{
if (pmcData.TaskConditionCounters.GetValueOrDefault(conditionId) != null)
{
@@ -401,13 +450,16 @@ public class QuestController(
return;
}
pmcData.TaskConditionCounters.Add(conditionId, new TaskConditionCounter
{
Id = conditionId,
SourceId = questId,
Type = "HandoverItem",
Value = counterValue
});
pmcData.TaskConditionCounters.Add(
conditionId,
new TaskConditionCounter
{
Id = conditionId,
SourceId = questId,
Type = "HandoverItem",
Value = counterValue,
}
);
}
/// <summary>
@@ -418,7 +470,12 @@ public class QuestController(
/// <param name="sessionID">Session/Player id</param>
/// <param name="output"></param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse FailQuest(PmcData pmcData, FailQuestRequestData request, string sessionID, ItemEventRouterResponse output)
public ItemEventRouterResponse FailQuest(
PmcData pmcData,
FailQuestRequestData request,
string sessionID,
ItemEventRouterResponse output
)
{
_questHelper.FailQuest(pmcData, request, sessionID, output);
@@ -114,8 +114,9 @@ public class RagfairController
// Check profile is capable of creating offers
var pmcProfile = profile.CharacterData.PmcData;
if (
pmcProfile.RagfairInfo is not null &&
pmcProfile.Info.Level >= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
pmcProfile.RagfairInfo is not null
&& pmcProfile.Info.Level
>= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
)
{
_ragfairOfferHelper.ProcessOffersOnProfile(sessionId);
@@ -139,19 +140,28 @@ public class RagfairController
{
Offers = [],
OffersCount = searchRequest.Limit,
SelectedCategory = searchRequest.HandbookId
SelectedCategory = searchRequest.HandbookId,
};
// Get all offers ready for sorting/filtering below
result.Offers = GetOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, profile.CharacterData.PmcData);
result.Offers = GetOffersForSearchType(
searchRequest,
itemsToAdd,
traderAssorts,
profile.CharacterData.PmcData
);
// Client requested a category refresh
if (searchRequest.UpdateOfferCount.GetValueOrDefault(false))
{
result.Categories = GetSpecificCategories(profile.CharacterData.PmcData, searchRequest, result.Offers);
result.Categories = GetSpecificCategories(
profile.CharacterData.PmcData,
searchRequest,
result.Offers
);
}
// Adjust index value of offers found to start at 0
// Adjust index value of offers found to start at 0
AddIndexValueToOffers(result.Offers);
// Sort offers
@@ -171,7 +181,11 @@ public class RagfairController
}
// Update trader offers' values, Lock quest-linked offers + adjust offer buy limits
foreach (var traderOffer in result.Offers.Where(offer => _ragfairOfferHelper.OfferIsFromTrader(offer)))
foreach (
var traderOffer in result.Offers.Where(offer =>
_ragfairOfferHelper.OfferIsFromTrader(offer)
)
)
{
// For the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked
// to true if the quest is not completed yet
@@ -239,11 +253,7 @@ public class RagfairController
_logger.Warning(
_localisationService.GetText(
"ragfair-unable_to_adjust_stack_count_assort_not_found",
new
{
offerId = offer.Items.First().Id,
traderId = offer.User.Id
}
new { offerId = offer.Items.First().Id, traderId = offer.User.Id }
)
);
@@ -288,7 +298,7 @@ public class RagfairController
// Get specific assort purchase data and set current purchase buy value
traderPurchases.TryGetValue(assortId, out var assortTraderPurchaseData);
offer.BuyRestrictionCurrent = (int?) assortTraderPurchaseData?.PurchaseCount ?? 0;
offer.BuyRestrictionCurrent = (int?)assortTraderPurchaseData?.PurchaseCount ?? 0;
offer.BuyRestrictionMax = offerRootItem.Upd.BuyRestrictionMax;
}
@@ -313,12 +323,16 @@ public class RagfairController
/// <param name="searchRequest">Client search request data</param>
/// <param name="offers">Ragfair offers to get categories for</param>
/// <returns>Record with templates + counts</returns>
protected Dictionary<string, int> GetSpecificCategories(PmcData pmcProfile, SearchRequestData searchRequest,
List<RagfairOffer> offers)
protected Dictionary<string, int> GetSpecificCategories(
PmcData pmcProfile,
SearchRequestData searchRequest,
List<RagfairOffer> offers
)
{
// Linked/required search categories
var playerHasFleaUnlocked =
pmcProfile.Info.Level >= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel;
pmcProfile.Info.Level
>= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel;
List<RagfairOffer> offerPool = [];
if (IsLinkedSearch(searchRequest) || IsRequiredSearch(searchRequest))
{
@@ -340,7 +354,11 @@ public class RagfairController
return new Dictionary<string, int>();
}
return _ragfairServer.GetAllActiveCategories(playerHasFleaUnlocked, searchRequest, offerPool);
return _ragfairServer.GetAllActiveCategories(
playerHasFleaUnlocked,
searchRequest,
offerPool
);
}
/// <summary>
@@ -371,14 +389,22 @@ public class RagfairController
/// <param name="traderAssorts">Trader assorts</param>
/// <param name="pmcProfile"></param>
/// <returns>Array of offers</returns>
protected List<RagfairOffer> GetOffersForSearchType(SearchRequestData searchRequest, List<string> itemsToAdd,
protected List<RagfairOffer> GetOffersForSearchType(
SearchRequestData searchRequest,
List<string> itemsToAdd,
Dictionary<string, TraderAssort> traderAssorts,
PmcData pmcProfile)
PmcData pmcProfile
)
{
// Searching for items in preset menu
if (searchRequest.BuildCount > 0)
{
return _ragfairOfferHelper.GetOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
return _ragfairOfferHelper.GetOffersForBuild(
searchRequest,
itemsToAdd,
traderAssorts,
pmcProfile
);
}
if (searchRequest.NeededSearchId?.Length > 0)
@@ -387,7 +413,12 @@ public class RagfairController
}
// Searching for general items
return _ragfairOfferHelper.GetValidOffers(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
return _ragfairOfferHelper.GetValidOffers(
searchRequest,
itemsToAdd,
traderAssorts,
pmcProfile
);
}
/// <summary>
@@ -396,8 +427,10 @@ public class RagfairController
/// <param name="getPriceRequest">Client request object</param>
/// <param name="ignoreTraderOffers">OPTIONAL - Should trader offers be ignored in the calculation</param>
/// <returns>min/avg/max values for an item based on flea offers available</returns>
public GetItemPriceResult GetItemMinAvgMaxFleaPriceValues(GetMarketPriceRequestData getPriceRequest,
bool ignoreTraderOffers = true)
public GetItemPriceResult GetItemMinAvgMaxFleaPriceValues(
GetMarketPriceRequestData getPriceRequest,
bool ignoreTraderOffers = true
)
{
// Get all items of tpl
var offers = _ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId);
@@ -415,7 +448,7 @@ public class RagfairController
{
Avg = Math.Round(average),
Min = minMax.Min,
Max = minMax.Max
Max = minMax.Max,
};
}
@@ -431,11 +464,15 @@ public class RagfairController
{
Avg = tplPrice,
Min = tplPrice,
Max = tplPrice
Max = tplPrice,
};
}
protected double GetAveragePriceFromOffers(List<RagfairOffer> offers, MinMax<double> minMax, bool ignoreTraderOffers)
protected double GetAveragePriceFromOffers(
List<RagfairOffer> offers,
MinMax<double> minMax,
bool ignoreTraderOffers
)
{
var sum = 0d;
var totalOfferCount = 0;
@@ -488,14 +525,21 @@ public class RagfairController
/// <param name="offerRequest">Flea list creation offer</param>
/// <param name="sessionID">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse AddPlayerOffer(PmcData pmcData, AddOfferRequestData offerRequest, string sessionID)
public ItemEventRouterResponse AddPlayerOffer(
PmcData pmcData,
AddOfferRequestData offerRequest,
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
var fullProfile = _profileHelper.GetFullProfile(sessionID);
if (!IsValidPlayerOfferRequest(offerRequest))
{
return _httpResponseUtil.AppendErrorToOutput(output, "Unable to add offer, check server for error");
return _httpResponseUtil.AppendErrorToOutput(
output,
"Unable to add offer, check server for error"
);
}
var typeOfOffer = GetOfferType(offerRequest);
@@ -540,7 +584,9 @@ public class RagfairController
if (offerRequest.Requirements is null)
{
_logger.Error(_localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements"));
_logger.Error(
_localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements")
);
return false;
}
@@ -588,8 +634,12 @@ public class RagfairController
/// <param name="fullProfile">Full profile of player</param>
/// <param name="output">output Response to send to client</param>
/// <returns>ItemEventRouterResponse</returns>
protected ItemEventRouterResponse CreateMultiOffer(string sessionID, AddOfferRequestData offerRequest,
SptProfile fullProfile, ItemEventRouterResponse output)
protected ItemEventRouterResponse CreateMultiOffer(
string sessionID,
AddOfferRequestData offerRequest,
SptProfile fullProfile,
ItemEventRouterResponse output
)
{
var pmcData = fullProfile.CharacterData.PmcData;
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used to commented out for now // Does not count stack size, only items
@@ -625,17 +675,18 @@ public class RagfairController
var rootOfferItem = offer.Items.First(x => x.Id == firstOfferItemId);
// Average offer price for single item (or whole weapon)
var averages =
GetItemMinAvgMaxFleaPriceValues(
new GetMarketPriceRequestData
{
TemplateId = offer.Items[0].Template
}
);
var averages = GetItemMinAvgMaxFleaPriceValues(
new GetMarketPriceRequestData { TemplateId = offer.Items[0].Template }
);
// Check for and apply item price modifer if it exists in config
var averageOfferPrice = averages.Avg;
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(rootOfferItem.Template, out var itemPriceModifer))
if (
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
rootOfferItem.Template,
out var itemPriceModifer
)
)
{
averageOfferPrice *= itemPriceModifer;
}
@@ -657,7 +708,7 @@ public class RagfairController
);
// Create array of sell times for items listed
offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int) stackCountTotal);
offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal);
// Subtract flea market fee from stash
if (_ragfairConfig.Sell.Fees)
@@ -667,7 +718,7 @@ public class RagfairController
rootOfferItem,
pmcData,
playerListedPriceInRub,
(int) stackCountTotal,
(int)stackCountTotal,
offerRequest,
output
);
@@ -700,8 +751,12 @@ public class RagfairController
/// <param name="fullProfile">Full profile of player</param>
/// <param name="output">Response to send to client</param>
/// <returns>ItemEventRouterResponse</returns>
protected ItemEventRouterResponse CreatePackOffer(string sessionID, AddOfferRequestData offerRequest,
SptProfile fullProfile, ItemEventRouterResponse output)
protected ItemEventRouterResponse CreatePackOffer(
string sessionID,
AddOfferRequestData offerRequest,
SptProfile fullProfile,
ItemEventRouterResponse output
)
{
var pmcData = fullProfile.CharacterData.PmcData;
// var itemsToListCount = offerRequest.Items.Count; // TODO: Wasn't used so commented out for now // Does not count stack size, only items
@@ -730,22 +785,29 @@ public class RagfairController
firstListingRootItem.Upd.StackObjectsCount = stackCountTotal;
// Create flea object
var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstListingAndChildren, true);
var offer = CreatePlayerOffer(
sessionID,
offerRequest.Requirements,
firstListingAndChildren,
true
);
// This is the item that will be listed on flea, has merged stackObjectCount
var newRootOfferItem = offer.Items[0]; // TODO: add logic like single/multi offers to find root item
// Single price for an item
var averages = GetItemMinAvgMaxFleaPriceValues(
new GetMarketPriceRequestData
{
TemplateId = firstListingRootItem.Template
}
new GetMarketPriceRequestData { TemplateId = firstListingRootItem.Template }
);
var singleItemPrice = averages.Avg;
// Check for and apply item price modifer if it exists in config
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(newRootOfferItem.Template, out var itemPriceModifer))
if (
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
newRootOfferItem.Template,
out var itemPriceModifer
)
)
{
singleItemPrice *= itemPriceModifer;
}
@@ -767,7 +829,11 @@ public class RagfairController
);
// Create array of sell times for items listed + sell all at once as it's a pack
offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int) stackCountTotal, true);
offer.SellResults = _ragfairSellHelper.RollForSale(
sellChancePercent,
(int)stackCountTotal,
true
);
// Subtract flea market fee from stash
if (_ragfairConfig.Sell.Fees)
@@ -777,7 +843,7 @@ public class RagfairController
newRootOfferItem,
pmcData,
playerListedPriceInRub,
(int) stackCountTotal,
(int)stackCountTotal,
offerRequest,
output
);
@@ -809,22 +875,30 @@ public class RagfairController
/// <param name="fullProfile">Full profile of player</param>
/// <param name="output">Response to send to client</param>
/// <returns>ItemEventRouterResponse</returns>
protected ItemEventRouterResponse CreateSingleOffer(string sessionID, AddOfferRequestData offerRequest,
protected ItemEventRouterResponse CreateSingleOffer(
string sessionID,
AddOfferRequestData offerRequest,
SptProfile fullProfile,
ItemEventRouterResponse output)
ItemEventRouterResponse output
)
{
var pmcData = fullProfile.CharacterData.PmcData;
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used so commented out for now // Does not count stack size, only items
// Find items to be listed on flea from player inventory
var inventoryItemsToSell = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items);
if (inventoryItemsToSell.Items is null || !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage))
if (
inventoryItemsToSell.Items is null
|| !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage)
)
{
_httpResponseUtil.AppendErrorToOutput(output, inventoryItemsToSell.ErrorMessage);
}
// Total count of items summed using their stack counts
var stackCountTotal = _ragfairOfferHelper.GetTotalStackCountSize(inventoryItemsToSell.Items);
var stackCountTotal = _ragfairOfferHelper.GetTotalStackCountSize(
inventoryItemsToSell.Items
);
// Checks are done, create offer
var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements);
@@ -841,17 +915,18 @@ public class RagfairController
var qualityMultiplier = _itemHelper.GetItemQualityModifierForItems(offer.Items, true);
// Average offer price for single item (or whole weapon)
var averages =
GetItemMinAvgMaxFleaPriceValues(
new GetMarketPriceRequestData
{
TemplateId = offerRootItem.Template
}
);
var averages = GetItemMinAvgMaxFleaPriceValues(
new GetMarketPriceRequestData { TemplateId = offerRootItem.Template }
);
var averageOfferPriceSingleItem = averages.Avg;
// Check for and apply item price modifer if it exists in config
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(offerRootItem.Template, out var itemPriceModifer))
if (
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
offerRootItem.Template,
out var itemPriceModifer
)
)
{
averageOfferPriceSingleItem *= itemPriceModifer;
}
@@ -865,7 +940,7 @@ public class RagfairController
playerListedPriceInRub,
qualityMultiplier
);
offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int) stackCountTotal);
offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal);
// Subtract flea market fee from stash
if (_ragfairConfig.Sell.Fees)
@@ -875,7 +950,7 @@ public class RagfairController
offerRootItem,
pmcData,
playerListedPriceInRub,
(int) stackCountTotal,
(int)stackCountTotal,
offerRequest,
output
);
@@ -916,10 +991,13 @@ public class RagfairController
double requirementsPriceInRub,
int itemStackCount,
AddOfferRequestData offerRequest,
ItemEventRouterResponse output)
ItemEventRouterResponse output
)
{
// Get tax from cache hydrated earlier by client, if that's missing fall back to server calculation (inaccurate)
var storedClientTaxValue = _ragfairTaxService.GetStoredClientOfferTaxValueById(offerRequest.Items[0]);
var storedClientTaxValue = _ragfairTaxService.GetStoredClientOfferTaxValueById(
offerRequest.Items[0]
);
var tax = storedClientTaxValue is not null
? storedClientTaxValue.Fee
: _ragfairTaxService.CalculateTax(
@@ -932,7 +1010,9 @@ public class RagfairController
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}");
_logger.Debug(
$"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}"
);
}
// cleanup of cache now we've used the tax value from it
@@ -960,32 +1040,34 @@ public class RagfairController
/// <param name="items">Item(s) to list on flea (with children)</param>
/// <param name="sellInOnePiece">Is this a pack offer</param>
/// <returns>RagfairOffer</returns>
protected RagfairOffer CreatePlayerOffer(string sessionId, List<Requirement> requirements, List<Item> items,
bool sellInOnePiece)
protected RagfairOffer CreatePlayerOffer(
string sessionId,
List<Requirement> requirements,
List<Item> items,
bool sellInOnePiece
)
{
const int loyalLevel = 1;
var formattedItems = items.Select(item =>
{
var isChild = items.Any(subItem => subItem.Id == item.ParentId);
{
var isChild = items.Any(subItem => subItem.Id == item.ParentId);
return new Item
{
Id = item.Id,
Template = item.Template,
ParentId = isChild ? item.ParentId : "hideout",
SlotId = isChild ? item.SlotId : "hideout",
Upd = item.Upd
};
}
);
return new Item
{
Id = item.Id,
Template = item.Template,
ParentId = isChild ? item.ParentId : "hideout",
SlotId = isChild ? item.SlotId : "hideout",
Upd = item.Upd,
};
});
var formattedRequirements = requirements.Select(item => new BarterScheme
{
Template = item.Template,
Count = item.Count,
OnlyFunctional = item.OnlyFunctional
}
);
{
Template = item.Template,
Count = item.Count,
OnlyFunctional = item.OnlyFunctional,
});
return _ragfairOfferGenerator.CreateAndAddFleaOffer(
sessionId,
@@ -993,7 +1075,7 @@ public class RagfairController
formattedItems.ToList(),
formattedRequirements.ToList(),
loyalLevel,
(int?) items.FirstOrDefault()?.Upd?.StackObjectsCount ?? 1,
(int?)items.FirstOrDefault()?.Upd?.StackObjectsCount ?? 1,
sellInOnePiece
);
}
@@ -1006,17 +1088,21 @@ public class RagfairController
protected double CalculateRequirementsPriceInRub(List<Requirement> requirements)
{
return requirements.Sum(requirement =>
{
if (
string.IsNullOrEmpty(requirement.Template)
|| !requirement.Count.HasValue
|| requirement.Count == 0
)
{
if (string.IsNullOrEmpty(requirement.Template) || !requirement.Count.HasValue || requirement.Count == 0)
{
return 0;
}
return _paymentHelper.IsMoneyTpl(requirement.Template)
? _handbookHelper.InRUB(requirement.Count.Value, requirement.Template)
: _itemHelper.GetDynamicItemPrice(requirement.Template).Value * requirement.Count.Value;
return 0;
}
);
return _paymentHelper.IsMoneyTpl(requirement.Template)
? _handbookHelper.InRUB(requirement.Count.Value, requirement.Template)
: _itemHelper.GetDynamicItemPrice(requirement.Template).Value
* requirement.Count.Value;
});
}
/// <summary>
@@ -1025,8 +1111,10 @@ public class RagfairController
/// <param name="pmcData">Players PMC profile</param>
/// <param name="itemIdsFromFleaOfferRequest">Request</param>
/// <returns>GetItemsToListOnFleaFromInventoryResult</returns>
protected GetItemsToListOnFleaFromInventoryResult GetItemsToListOnFleaFromInventory(PmcData pmcData,
List<string> itemIdsFromFleaOfferRequest)
protected GetItemsToListOnFleaFromInventoryResult GetItemsToListOnFleaFromInventory(
PmcData pmcData,
List<string> itemIdsFromFleaOfferRequest
)
{
List<List<Item>> itemsToReturn = [];
var errorMessage = string.Empty;
@@ -1039,40 +1127,38 @@ public class RagfairController
{
errorMessage = _localisationService.GetText(
"ragfair-unable_to_find_item_in_inventory",
new
{
id = itemId
}
new { id = itemId }
);
_logger.Error(errorMessage);
return new GetItemsToListOnFleaFromInventoryResult
{
Items = itemsToReturn,
ErrorMessage = errorMessage
ErrorMessage = errorMessage,
};
}
_itemHelper.FixItemStackCount(rootItem);
itemsToReturn.Add(_itemHelper.FindAndReturnChildrenAsItems(pmcData.Inventory.Items, itemId));
itemsToReturn.Add(
_itemHelper.FindAndReturnChildrenAsItems(pmcData.Inventory.Items, itemId)
);
}
if (itemsToReturn?.Count == 0)
{
errorMessage = _localisationService.GetText("ragfair-unable_to_find_requested_items_in_inventory");
errorMessage = _localisationService.GetText(
"ragfair-unable_to_find_requested_items_in_inventory"
);
_logger.Error(errorMessage);
return new GetItemsToListOnFleaFromInventoryResult
{
ErrorMessage = errorMessage
};
return new GetItemsToListOnFleaFromInventoryResult { ErrorMessage = errorMessage };
}
return new GetItemsToListOnFleaFromInventoryResult
{
Items = itemsToReturn,
ErrorMessage = errorMessage
ErrorMessage = errorMessage,
};
}
@@ -1094,11 +1180,7 @@ public class RagfairController
_logger.Warning(
_localisationService.GetText(
"ragfair-unable_to_remove_offer_not_found_in_profile",
new
{
profileId = sessionId,
offerId
}
new { profileId = sessionId, offerId }
)
);
@@ -1109,13 +1191,7 @@ public class RagfairController
if (playerOffer is null)
{
_logger.Error(
_localisationService.GetText(
"ragfair-offer_not_found_in_profile",
new
{
offerId
}
)
_localisationService.GetText("ragfair-offer_not_found_in_profile", new { offerId })
);
return _httpResponseUtil.AppendErrorToOutput(
@@ -1130,10 +1206,12 @@ public class RagfairController
{
// `expireSeconds` Default is 71 seconds
var newEndTime = _ragfairConfig.Sell.ExpireSeconds + _timeUtil.GetTimeStamp();
playerOffer.EndTime = (long?) Math.Round((double) newEndTime);
playerOffer.EndTime = (long?)Math.Round((double)newEndTime);
}
_logger.Debug($"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}");
_logger.Debug(
$"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}"
);
return output;
}
@@ -1144,7 +1222,10 @@ public class RagfairController
/// <param name="extendRequest">Extend time request</param>
/// <param name="sessionId">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse ExtendOffer(ExtendOfferRequestData extendRequest, string sessionId)
public ItemEventRouterResponse ExtendOffer(
ExtendOfferRequestData extendRequest,
string sessionId
)
{
var output = _eventOutputHolder.GetOutput(sessionId);
@@ -1158,10 +1239,7 @@ public class RagfairController
_logger.Warning(
_localisationService.GetText(
"ragfair-offer_not_found_in_profile",
new
{
offerId = extendRequest.OfferId
}
new { offerId = extendRequest.OfferId }
)
);
return _httpResponseUtil.AppendErrorToOutput(
@@ -1179,7 +1257,8 @@ public class RagfairController
var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false);
if (!sellInOncePiece)
{
count = (int) playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
count = (int)
playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
}
var tax = _ragfairTaxService.CalculateTax(
@@ -1202,7 +1281,7 @@ public class RagfairController
}
// Add extra time to offer
playerOffers[playerOfferIndex].EndTime += (long?) Math.Round((decimal) secondsToAdd);
playerOffers[playerOfferIndex].EndTime += (long?)Math.Round((decimal)secondsToAdd);
return output;
}
@@ -1213,7 +1292,10 @@ public class RagfairController
/// <param name="currency">What currency: RUB, EURO, USD</param>
/// <param name="value">Amount of currency</param>
/// <returns>ProcessBuyTradeRequestData</returns>
protected ProcessBuyTradeRequestData CreateBuyTradeRequestObject(CurrencyType currency, double value)
protected ProcessBuyTradeRequestData CreateBuyTradeRequestObject(
CurrencyType currency,
double value
)
{
return new ProcessBuyTradeRequestData
{
@@ -1224,13 +1306,13 @@ public class RagfairController
new IdWithCount
{
Id = _paymentHelper.GetCurrency(currency),
Count = Math.Round(value)
}
Count = Math.Round(value),
},
],
Type = "",
ItemId = "",
Count = 0,
SchemeId = 0
SchemeId = 0,
};
}
@@ -1258,16 +1340,8 @@ public class RagfairController
public record GetItemsToListOnFleaFromInventoryResult
{
public List<List<Item>>? Items
{
get;
set;
}
public List<List<Item>>? Items { get; set; }
public string? ErrorMessage
{
get;
set;
}
public string? ErrorMessage { get; set; }
}
}
@@ -8,10 +8,7 @@ using SPTarkov.Server.Core.Services;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
public class RepairController(
EventOutputHolder _eventOutputHolder,
RepairService _repairService
)
public class RepairController(EventOutputHolder _eventOutputHolder, RepairService _repairService)
{
/// <summary>
/// Handle TraderRepair event
@@ -24,14 +21,20 @@ public class RepairController(
public ItemEventRouterResponse TraderRepair(
string sessionID,
TraderRepairActionDataRequest body,
PmcData pmcData)
PmcData pmcData
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
// find the item to repair
foreach (var repairItem in body.RepairItems)
{
var repairDetails = _repairService.RepairItemByTrader(sessionID, pmcData, repairItem, body.TId);
var repairDetails = _repairService.RepairItemByTrader(
sessionID,
pmcData,
repairItem,
body.TId
);
_repairService.PayForRepair(
sessionID,
@@ -68,7 +71,8 @@ public class RepairController(
public ItemEventRouterResponse RepairWithKit(
string sessionId,
RepairActionDataRequest body,
PmcData pmcData)
PmcData pmcData
)
{
var output = _eventOutputHolder.GetOutput(sessionId);
@@ -53,7 +53,11 @@ public class RepeatableQuestController(
/// <param name="acceptedQuest">Repeatable quest accepted</param>
/// <param name="sessionID">Session/Player id</param>
/// <returns>ItemEventRouterResponse</returns>
public ItemEventRouterResponse AcceptRepeatableQuest(PmcData pmcData, AcceptQuestRequestData acceptedQuest, string sessionID)
public ItemEventRouterResponse AcceptRepeatableQuest(
PmcData pmcData,
AcceptQuestRequestData acceptedQuest,
string sessionID
)
{
// Create and store quest status object inside player profile
var newRepeatableQuest = _questHelper.GetQuestReadyForProfile(
@@ -74,11 +78,16 @@ public class RepeatableQuestController(
)
);
throw new Exception(_localisationService.GetText("repeatable-unable_to_accept_quest_see_log"));
throw new Exception(
_localisationService.GetText("repeatable-unable_to_accept_quest_see_log")
);
}
// Some scav quests need to be added to scav profile for them to show up in-raid
if (repeatableQuestProfile.Side == "Scav" && _questTypes.Contains(repeatableQuestProfile.Type.ToString()))
if (
repeatableQuestProfile.Side == "Scav"
&& _questTypes.Contains(repeatableQuestProfile.Type.ToString())
)
{
var fullProfile = _profileHelper.GetFullProfile(sessionID);
@@ -98,8 +107,11 @@ public class RepeatableQuestController(
/// <param name="changeRequest">Change quest request</param>
/// <param name="sessionID">Session/Player id</param>
/// <returns></returns>
public ItemEventRouterResponse ChangeRepeatableQuest(PmcData pmcData, RepeatableQuestChangeRequest changeRequest,
string sessionID)
public ItemEventRouterResponse ChangeRepeatableQuest(
PmcData pmcData,
RepeatableQuestChangeRequest changeRequest,
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
@@ -112,7 +124,9 @@ public class RepeatableQuestController(
if (repeatables.RepeatableType is null || repeatables.Quest is null)
{
// Unable to find quest being replaced
var message = _localisationService.GetText("quest-unable_to_find_repeatable_to_replace");
var message = _localisationService.GetText(
"quest-unable_to_find_repeatable_to_replace"
);
_logger.Error(message);
return _httpResponseUtil.AppendErrorToOutput(output, message);
@@ -125,8 +139,8 @@ public class RepeatableQuestController(
var replacedQuestTraderId = questToReplace.TraderId;
// Update active quests to exclude the quest we're replacing
repeatablesOfTypeInProfile.ActiveQuests = repeatablesOfTypeInProfile.ActiveQuests.Where(quest => quest.Id != changeRequest.QuestId
)
repeatablesOfTypeInProfile.ActiveQuests = repeatablesOfTypeInProfile
.ActiveQuests.Where(quest => quest.Id != changeRequest.QuestId)
.ToList();
// Save for later cost calculations
@@ -138,7 +152,8 @@ public class RepeatableQuestController(
repeatablesOfTypeInProfile.ChangeRequirement.Remove(changeRequest.QuestId);
// Get config for this repeatable subtype (daily/weekly/scav)
var repeatableConfig = _questConfig.RepeatableQuests.FirstOrDefault(config => config.Name == repeatablesOfTypeInProfile.Name
var repeatableConfig = _questConfig.RepeatableQuests.FirstOrDefault(config =>
config.Name == repeatablesOfTypeInProfile.Name
);
// If the configuration dictates to replace with the same quest type, adjust the available quest types
@@ -148,7 +163,10 @@ public class RepeatableQuestController(
}
// Generate meta-data for what type/level range of quests can be generated for player
var allowedQuestTypes = GenerateQuestPool(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
var allowedQuestTypes = GenerateQuestPool(
repeatableConfig,
pmcData.Info.Level.GetValueOrDefault(1)
);
var newRepeatableQuest = AttemptToGenerateRepeatableQuest(
sessionID,
pmcData,
@@ -186,7 +204,7 @@ public class RepeatableQuestController(
repeatablesOfTypeInProfile.ChangeRequirement[newRepeatableQuest.Id] = new ChangeRequirement
{
ChangeCost = newRepeatableQuest.ChangeCost,
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost)
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost),
};
// Check if we should charge player for replacing quest
@@ -201,12 +219,22 @@ public class RepeatableQuestController(
var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId];
traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost;
var charismaBonus = _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0;
var charismaBonus =
_profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0;
foreach (var cost in previousChangeRequirement.ChangeCost)
{
// Not free, Charge player + apply charisma bonus to cost of replacement
cost.Count = (int) Math.Truncate(cost.Count.Value * (1 - Math.Truncate(charismaBonus / 100) * 0.001));
_paymentService.AddPaymentToOutput(pmcData, cost.TemplateId, cost.Count.Value, sessionID, output);
cost.Count = (int)
Math.Truncate(
cost.Count.Value * (1 - Math.Truncate(charismaBonus / 100) * 0.001)
);
_paymentService.AddPaymentToOutput(
pmcData,
cost.TemplateId,
cost.Count.Value,
sessionID,
output
);
if (output.Warnings.Count > 0)
{
return output;
@@ -265,8 +293,11 @@ public class RepeatableQuestController(
/// <param name="repeatableSubType">Can be daily / weekly / scav repeatable</param>
/// <param name="repeatableTypeName">Subtype of repeatable quest: daily / weekly / scav</param>
/// <returns>Is the repeatable being replaced for free</returns>
protected bool UseFreeRefreshIfAvailable(SptProfile? fullProfile, PmcDataRepeatableQuest repeatableSubType,
string repeatableTypeName)
protected bool UseFreeRefreshIfAvailable(
SptProfile? fullProfile,
PmcDataRepeatableQuest repeatableSubType,
string repeatableTypeName
)
{
// No free refreshes, exit early
if (repeatableSubType.FreeChangesAvailable <= 0)
@@ -305,12 +336,14 @@ public class RepeatableQuestController(
/// </summary>
/// <param name="repeatablesOfTypeInProfile">repeatables that have the replaced and new quest</param>
/// <param name="replacedQuestId">Id of the replaced quest</param>
protected void CleanUpRepeatableChangeRequirements(PmcDataRepeatableQuest repeatablesOfTypeInProfile,
string replacedQuestId)
protected void CleanUpRepeatableChangeRequirements(
PmcDataRepeatableQuest repeatablesOfTypeInProfile,
string replacedQuestId
)
{
if (repeatablesOfTypeInProfile.ActiveQuests.Count == 1)
// Only one repeatable quest being replaced (e.g. scav_daily), remove everything ready for new quest requirement to be added
// Will assist in cleanup of existing profiles data
// Only one repeatable quest being replaced (e.g. scav_daily), remove everything ready for new quest requirement to be added
// Will assist in cleanup of existing profiles data
{
repeatablesOfTypeInProfile.ChangeRequirement.Clear();
@@ -329,8 +362,12 @@ public class RepeatableQuestController(
/// <param name="questTypePool">What type/level range of quests can be generated for player</param>
/// <param name="repeatableConfig">Config for the quest type to generate</param>
/// <returns></returns>
protected RepeatableQuest? AttemptToGenerateRepeatableQuest(string sessionId, PmcData pmcData,
QuestTypePool questTypePool, RepeatableQuestConfig repeatableConfig)
protected RepeatableQuest? AttemptToGenerateRepeatableQuest(
string sessionId,
PmcData pmcData,
QuestTypePool questTypePool,
RepeatableQuestConfig repeatableConfig
)
{
const int maxAttempts = 10;
RepeatableQuest? newRepeatableQuest = null;
@@ -346,7 +383,7 @@ public class RepeatableQuestController(
);
if (newRepeatableQuest is not null)
// Successfully generated a quest, exit loop
// Successfully generated a quest, exit loop
{
break;
}
@@ -356,7 +393,12 @@ public class RepeatableQuestController(
if (attempts > maxAttempts)
{
_logger.Error(_localisationService.GetText("quest-repeatable_generation_failed_please_report", attempts));
_logger.Error(
_localisationService.GetText(
"quest-repeatable_generation_failed_please_report",
attempts
)
);
}
return newRepeatableQuest;
@@ -370,7 +412,10 @@ public class RepeatableQuestController(
protected void RemoveQuestFromProfile(SptProfile fullProfile, string questToReplaceId)
{
// Find quest we're replacing in pmc profile quests array and remove it
_questHelper.FindAndRemoveQuestFromArrayIfExists(questToReplaceId, fullProfile.CharacterData.PmcData.Quests);
_questHelper.FindAndRemoveQuestFromArrayIfExists(
questToReplaceId,
fullProfile.CharacterData.PmcData.Quests
);
// Look for and remove quest we're replacing in scav profile too
if (fullProfile.CharacterData.ScavData is not null)
@@ -393,10 +438,11 @@ public class RepeatableQuestController(
foreach (var repeatablesInProfile in pmcData.RepeatableQuests)
{
// Check for existing quest in (daily/weekly/scav arrays)
var questToReplace =
repeatablesInProfile.ActiveQuests?.FirstOrDefault(repeatable => repeatable.Id == questId);
var questToReplace = repeatablesInProfile.ActiveQuests?.FirstOrDefault(repeatable =>
repeatable.Id == questId
);
if (questToReplace is null)
// Not found, skip to next repeatable subtype
// Not found, skip to next repeatable subtype
{
continue;
}
@@ -404,7 +450,7 @@ public class RepeatableQuestController(
return new GetRepeatableByIdResult
{
Quest = questToReplace,
RepeatableType = repeatablesInProfile
RepeatableType = repeatablesInProfile,
};
}
@@ -443,12 +489,15 @@ public class RepeatableQuestController(
foreach (var repeatableConfig in _questConfig.RepeatableQuests)
{
// Get daily/weekly data from profile, add empty object if missing
var generatedRepeatables = GetRepeatableQuestSubTypeFromProfile(repeatableConfig, pmcData);
var generatedRepeatables = GetRepeatableQuestSubTypeFromProfile(
repeatableConfig,
pmcData
);
var repeatableTypeLower = repeatableConfig.Name.ToLower();
var canAccessRepeatables = CanProfileAccessRepeatableQuests(repeatableConfig, pmcData);
if (!canAccessRepeatables)
// Don't send any repeatables, even existing ones
// Don't send any repeatables, even existing ones
{
continue;
}
@@ -483,7 +532,10 @@ public class RepeatableQuestController(
ProcessExpiredQuests(generatedRepeatables, pmcData);
// Create dynamic quest pool to avoid generating duplicates
var questTypePool = GenerateQuestPool(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
var questTypePool = GenerateQuestPool(
repeatableConfig,
pmcData.Info.Level.GetValueOrDefault(1)
);
// Add repeatable quests of this loops sub-type (daily/weekly)
for (var i = 0; i < GetQuestCount(repeatableConfig, fullProfile); i++)
@@ -535,7 +587,9 @@ public class RepeatableQuestController(
new ChangeRequirement
{
ChangeCost = quest.ChangeCost,
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost) // Randomise standing loss to replace
ChangeStandingCost = _randomUtil.GetArrayValue(
repeatableConfig.StandingChangeCost
), // Randomise standing loss to replace
}
);
}
@@ -553,7 +607,7 @@ public class RepeatableQuestController(
InactiveQuests = generatedRepeatables.InactiveQuests,
ChangeRequirement = generatedRepeatables.ChangeRequirement,
FreeChanges = generatedRepeatables.FreeChanges,
FreeChangesAvailable = generatedRepeatables.FreeChangesAvailable
FreeChangesAvailable = generatedRepeatables.FreeChangesAvailable,
}
);
}
@@ -567,11 +621,14 @@ public class RepeatableQuestController(
/// <param name="repeatableConfig">daily/weekly config</param>
/// <param name="pmcData">Players PMC profile</param>
/// <returns>PmcDataRepeatableQuest</returns>
protected PmcDataRepeatableQuest GetRepeatableQuestSubTypeFromProfile(RepeatableQuestConfig repeatableConfig,
PmcData pmcData)
protected PmcDataRepeatableQuest GetRepeatableQuestSubTypeFromProfile(
RepeatableQuestConfig repeatableConfig,
PmcData pmcData
)
{
// Get from profile, add if missing
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable => repeatable.Name == repeatableConfig.Name
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable =>
repeatable.Name == repeatableConfig.Name
);
var hasAccess = _profileHelper.HasAccessToRepeatableFreeRefreshSystem(pmcData);
@@ -586,7 +643,7 @@ public class RepeatableQuestController(
InactiveQuests = [],
EndTime = 0,
FreeChanges = hasAccess ? repeatableConfig.FreeChanges : 0,
FreeChangesAvailable = hasAccess ? repeatableConfig.FreeChangesAvailable : 0
FreeChangesAvailable = hasAccess ? repeatableConfig.FreeChangesAvailable : 0,
};
// Add base object that holds repeatable data to profile
@@ -610,10 +667,16 @@ public class RepeatableQuestController(
/// <param name="repeatableConfig">Repeatable quest config</param>
/// <param name="pmcData">Players PMC profile</param>
/// <returns>True if profile has access to repeatables</returns>
protected bool CanProfileAccessRepeatableQuests(RepeatableQuestConfig repeatableConfig, PmcData pmcData)
protected bool CanProfileAccessRepeatableQuests(
RepeatableQuestConfig repeatableConfig,
PmcData pmcData
)
{
// PMC and daily quests not unlocked yet
if (repeatableConfig.Side == "Pmc" && !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig))
if (
repeatableConfig.Side == "Pmc"
&& !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig)
)
{
return false;
}
@@ -638,7 +701,10 @@ public class RepeatableQuestController(
/// <param name="pmcData">Players PMC profile</param>
/// <param name="repeatableConfig">Config of daily type to check</param>
/// <returns>True if unlocked</returns>
protected static bool PlayerHasDailyPmcQuestsUnlocked(PmcData pmcData, RepeatableQuestConfig repeatableConfig)
protected static bool PlayerHasDailyPmcQuestsUnlocked(
PmcData pmcData,
RepeatableQuestConfig repeatableConfig
)
{
return pmcData.Info.Level >= repeatableConfig.MinPlayerLevel;
}
@@ -650,9 +716,11 @@ public class RepeatableQuestController(
/// <returns>True if unlocked</returns>
protected bool PlayerHasDailyScavQuestsUnlocked(PmcData pmcData)
{
return pmcData?.Hideout?.Areas?.FirstOrDefault(hideoutArea => hideoutArea.Type == HideoutAreas.IntelligenceCenter)
?.Level >=
1;
return pmcData
?.Hideout?.Areas?.FirstOrDefault(hideoutArea =>
hideoutArea.Type == HideoutAreas.IntelligenceCenter
)
?.Level >= 1;
}
/// <summary>
@@ -660,12 +728,17 @@ public class RepeatableQuestController(
/// </summary>
/// <param name="generatedRepeatables">Repeatables to process (daily/weekly)</param>
/// <param name="pmcData">Players PMC profile</param>
protected void ProcessExpiredQuests(PmcDataRepeatableQuest generatedRepeatables, PmcData pmcData)
protected void ProcessExpiredQuests(
PmcDataRepeatableQuest generatedRepeatables,
PmcData pmcData
)
{
var questsToKeep = new List<RepeatableQuest>();
foreach (var activeQuest in generatedRepeatables.ActiveQuests)
{
var questStatusInProfile = pmcData.Quests.FirstOrDefault(quest => quest.QId == activeQuest.Id);
var questStatusInProfile = pmcData.Quests.FirstOrDefault(quest =>
quest.QId == activeQuest.Id
);
if (questStatusInProfile is null)
{
continue;
@@ -723,8 +796,15 @@ public class RepeatableQuestController(
// Add "any" to pickup quest pool
questPool.Pool.Pickup.Locations[ELocationName.any] = ["any"];
var eliminationConfig = _repeatableQuestHelper.GetEliminationConfigByPmcLevel(pmcLevel, repeatableConfig);
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(_mathUtil, _cloner, eliminationConfig.Targets);
var eliminationConfig = _repeatableQuestHelper.GetEliminationConfigByPmcLevel(
pmcLevel,
repeatableConfig
);
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(
_mathUtil,
_cloner,
eliminationConfig.Targets
);
// Populate Elimination quest targets and their locations
foreach (var target in targetsConfig)
@@ -734,10 +814,7 @@ public class RepeatableQuestController(
{
questPool.Pool.Elimination.Targets.Add(
target.Key,
new TargetLocation
{
Locations = ["any"]
}
new TargetLocation { Locations = ["any"] }
);
continue;
@@ -747,16 +824,16 @@ public class RepeatableQuestController(
var possibleLocations = repeatableConfig.Locations.Keys;
var allowedLocations =
target.Key == "Savage"
? possibleLocations.Where(location => location != ELocationName.laboratory
) // Exclude labs for Savage targets.
? possibleLocations.Where(location => location != ELocationName.laboratory) // Exclude labs for Savage targets.
: possibleLocations;
questPool.Pool.Elimination.Targets.Add(
target.Key,
new TargetLocation
{
Locations = allowedLocations.Select(x => x.ToString()).ToList()
});
Locations = allowedLocations.Select(x => x.ToString()).ToList(),
}
);
}
return questPool;
@@ -776,17 +853,17 @@ public class RepeatableQuestController(
{
Exploration = new ExplorationPool
{
Locations = new Dictionary<ELocationName, List<string>>()
Locations = new Dictionary<ELocationName, List<string>>(),
},
Elimination = new EliminationPool
{
Targets = new Dictionary<string, TargetLocation>()
Targets = new Dictionary<string, TargetLocation>(),
},
Pickup = new ExplorationPool
{
Locations = new Dictionary<ELocationName, List<string>>()
}
}
Locations = new Dictionary<ELocationName, List<string>>(),
},
},
};
}
@@ -805,23 +882,25 @@ public class RepeatableQuestController(
}
// Add elite bonus to daily quests
if (string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase) &&
_profileHelper.HasEliteSkillLevel(SkillTypes.Charisma, fullProfile.CharacterData.PmcData))
// Elite charisma skill gives extra daily quest(s)
if (
string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase)
&& _profileHelper.HasEliteSkillLevel(
SkillTypes.Charisma,
fullProfile.CharacterData.PmcData
)
)
// Elite charisma skill gives extra daily quest(s)
{
questCount += _databaseService
.GetGlobals()
.Configuration
.SkillsSettings
.Charisma
.BonusSettings
.EliteBonusSettings
.RepeatableQuestExtraCount
.GetValueOrDefault(0);
.Configuration.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings.RepeatableQuestExtraCount.GetValueOrDefault(
0
);
}
// Add any extra repeatable quests the profile has unlocked
questCount += (int) fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
questCount += (int)
fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
return questCount;
}
@@ -50,7 +50,8 @@ public class TradeController(
public ItemEventRouterResponse ConfirmTrading(
PmcData pmcData,
ProcessBaseTradeRequestData request,
string sessionID)
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
@@ -58,7 +59,7 @@ public class TradeController(
if (request.Type == "buy_from_trader")
{
var foundInRaid = _traderConfig.PurchasesAreFoundInRaid;
var buyData = (ProcessBuyTradeRequestData) request;
var buyData = (ProcessBuyTradeRequestData)request;
_tradeHelper.BuyItem(pmcData, buyData, sessionID, foundInRaid, output);
return output;
@@ -67,7 +68,7 @@ public class TradeController(
// Selling
if (request.Type == "sell_to_trader")
{
var sellData = (ProcessSellTradeRequestData) request;
var sellData = (ProcessSellTradeRequestData)request;
_tradeHelper.SellItem(pmcData, pmcData, sellData, sessionID, output);
return output;
@@ -76,7 +77,11 @@ public class TradeController(
var errorMessage = $"Unhandled trade event: {request.Type}";
_logger.Error(errorMessage);
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
return _httpResponseUtil.AppendErrorToOutput(
output,
errorMessage,
BackendErrorCodes.RagfairUnavailable
);
}
/// <summary>
@@ -89,7 +94,8 @@ public class TradeController(
public ItemEventRouterResponse ConfirmRagfairTrading(
PmcData pmcData,
ProcessRagfairTradeRequestData request,
string sessionID)
string sessionID
)
{
var output = _eventOutputHolder.GetOutput(sessionID);
@@ -111,7 +117,11 @@ public class TradeController(
"ragfair-unable_to_purchase_0_count_item",
_itemHelper.GetItem(fleaOffer.Items[0].Template).Value.Name
);
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.OfferOutOfStock);
return _httpResponseUtil.AppendErrorToOutput(
output,
errorMessage,
BackendErrorCodes.OfferOutOfStock
);
}
if (_ragfairOfferHelper.OfferIsFromTrader(fleaOffer))
@@ -146,18 +156,24 @@ public class TradeController(
PmcData pmcData,
RagfairOffer fleaOffer,
OfferRequest requestOffer,
ItemEventRouterResponse output)
ItemEventRouterResponse output
)
{
// Skip buying items when player doesn't have needed loyalty
if (PlayerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData))
{
var errorMessage = $"Unable to buy item: {fleaOffer.Items[0].Template} from trader: {fleaOffer.User.Id} as loyalty level too low, skipping";
var errorMessage =
$"Unable to buy item: {fleaOffer.Items[0].Template} from trader: {fleaOffer.User.Id} as loyalty level too low, skipping";
if (_logger.IsLogEnabled(LogLevel.Debug))
{
_logger.Debug(errorMessage);
}
_httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
_httpResponseUtil.AppendErrorToOutput(
output,
errorMessage,
BackendErrorCodes.RagfairUnavailable
);
return;
}
@@ -171,9 +187,15 @@ public class TradeController(
ItemId = fleaOffer.Root,
Count = requestOffer.Count,
SchemeId = 0,
SchemeItems = requestOffer.Items
SchemeItems = requestOffer.Items,
};
_tradeHelper.BuyItem(pmcData, buyData, sessionId, _traderConfig.PurchasesAreFoundInRaid, output);
_tradeHelper.BuyItem(
pmcData,
buyData,
sessionId,
_traderConfig.PurchasesAreFoundInRaid,
output
);
// Remove/lower offer quantity of item purchased from trader flea offer
_ragfairServer.ReduceOfferQuantity(fleaOffer.Id, requestOffer.Count ?? 0);
@@ -192,7 +214,8 @@ public class TradeController(
PmcData pmcData,
RagfairOffer fleaOffer,
OfferRequest requestOffer,
ItemEventRouterResponse output)
ItemEventRouterResponse output
)
{
var buyData = new ProcessBuyTradeRequestData
{
@@ -202,11 +225,17 @@ public class TradeController(
ItemId = fleaOffer.Id, // Store ragfair offerId in buyRequestData.item_id
Count = requestOffer.Count,
SchemeId = 0,
SchemeItems = requestOffer.Items
SchemeItems = requestOffer.Items,
};
// buyItem() must occur prior to removing the offer stack, otherwise item inside offer doesn't exist for confirmTrading() to use
_tradeHelper.BuyItem(pmcData, buyData, sessionId, _ragfairConfig.Dynamic.PurchasesAreFoundInRaid, output);
_tradeHelper.BuyItem(
pmcData,
buyData,
sessionId,
_ragfairConfig.Dynamic.PurchasesAreFoundInRaid,
output
);
if (output.Warnings?.Count > 0)
{
return;
@@ -234,9 +263,7 @@ public class TradeController(
/// <param name="offerId">id of the offer</param>
/// <param name="offerOwnerId">Owner id</param>
/// <returns>true if offer was made by a player</returns>
protected bool IsPlayerOffer(
string offerId,
string? offerOwnerId)
protected bool IsPlayerOffer(string offerId, string? offerOwnerId)
{
// No ownerId, not player offer
if (offerOwnerId is null)
@@ -246,7 +273,7 @@ public class TradeController(
var offerCreatorProfile = _profileHelper.GetPmcProfile(offerOwnerId);
if (offerCreatorProfile is null || offerCreatorProfile.RagfairInfo.Offers?.Count == 0)
// No profile or no offers
// No profile or no offers
{
return false;
}
@@ -261,9 +288,7 @@ public class TradeController(
/// <param name="fleaOffer">Flea offer being bought</param>
/// <param name="pmcData">Player profile</param>
/// <returns>True if player can buy offer</returns>
protected bool PlayerLacksTraderLoyaltyLevelToBuyOffer(
RagfairOffer fleaOffer,
PmcData pmcData)
protected bool PlayerLacksTraderLoyaltyLevelToBuyOffer(RagfairOffer fleaOffer, PmcData pmcData)
{
return fleaOffer.LoyaltyLevel > pmcData.TradersInfo[fleaOffer.User.Id].LoyaltyLevel;
}
@@ -278,11 +303,12 @@ public class TradeController(
public ItemEventRouterResponse SellScavItemsToFence(
PmcData pmcData,
SellScavItemsToFenceRequestData request,
string sessionId)
string sessionId
)
{
var output = _eventOutputHolder.GetOutput(sessionId);
MailMoneyToPlayer(sessionId, (int) request.TotalValue, Traders.FENCE);
MailMoneyToPlayer(sessionId, (int)request.TotalValue, Traders.FENCE);
return output;
}
@@ -293,10 +319,7 @@ public class TradeController(
/// <param name="sessionId">Session id</param>
/// <param name="roublesToSend">amount of roubles to send</param>
/// <param name="trader">Trader to sell items to</param>
protected void MailMoneyToPlayer(
string sessionId,
int roublesToSend,
string trader)
protected void MailMoneyToPlayer(string sessionId, int roublesToSend, string trader)
{
if (_logger.IsLogEnabled(LogLevel.Debug))
{
@@ -308,10 +331,7 @@ public class TradeController(
{
Id = _hashUtil.Generate(),
Template = Money.ROUBLES,
Upd = new Upd
{
StackObjectsCount = roublesToSend
}
Upd = new Upd { StackObjectsCount = roublesToSend },
};
// Ensure money is properly split to follow its max stack size limit
@@ -322,7 +342,11 @@ public class TradeController(
sessionId,
trader,
MessageType.MessageWithItems,
_randomUtil.GetArrayValue(_databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items) ? items : new List<string>()),
_randomUtil.GetArrayValue(
_databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items)
? items
: new List<string>()
),
curencyReward.SelectMany(x => x).ToList(),
_timeUtil.GetHoursAsSeconds(72)
);
@@ -340,7 +364,8 @@ public class TradeController(
string parentItemId,
List<Item> items,
Dictionary<string, int?> handbookPrices,
TraderBase traderDetails)
TraderBase traderDetails
)
{
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(items, parentItemId);
@@ -348,14 +373,25 @@ public class TradeController(
foreach (var itemToSell in itemWithChildren)
{
var itemDetails = _itemHelper.GetItem(itemToSell.Template);
if (!(itemDetails.Key && _itemHelper.IsOfBaseclasses(itemDetails.Value.Id, traderDetails.ItemsBuy.Category)))
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
if (
!(
itemDetails.Key
&& _itemHelper.IsOfBaseclasses(
itemDetails.Value.Id,
traderDetails.ItemsBuy.Category
)
)
)
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
{
continue;
}
// Get price of item multiplied by how many are in stack
totalPrice += (int) ((handbookPrices[itemToSell.Template] ?? 0) * (itemToSell.Upd?.StackObjectsCount ?? 1));
totalPrice += (int)(
(handbookPrices[itemToSell.Template] ?? 0)
* (itemToSell.Upd?.StackObjectsCount ?? 1)
);
}
return totalPrice;
@@ -67,8 +67,9 @@ public class TraderController(
_traderPurchasePersisterService.RemoveStalePurchasesFromProfiles(traderId);
// Set to next hour on clock or current time + 60 minutes
trader.Base.NextResupply =
traderResetStartsWithServer ? (int) _traderHelper.GetNextUpdateTimestamp(trader.Base.Id) : (int) nextHourTimestamp;
trader.Base.NextResupply = traderResetStartsWithServer
? (int)_traderHelper.GetNextUpdateTimestamp(trader.Base.Id)
: (int)nextHourTimestamp;
}
}
@@ -85,10 +86,7 @@ public class TraderController(
var barterSchemeItem = kvp.Value?.FirstOrDefault()?.FirstOrDefault();
if (barterSchemeItem != null && _paymentHelper.IsMoneyTpl(barterSchemeItem.Template))
{
barterSchemeItem.Count += Math.Round(
barterSchemeItem?.Count * multiplier ?? 0D,
2
);
barterSchemeItem.Count += Math.Round(barterSchemeItem?.Count * multiplier ?? 0D, 2);
}
}
}
@@ -108,14 +106,14 @@ public class TraderController(
case Traders.LIGHTHOUSEKEEPER:
continue;
case Traders.FENCE:
{
if (_fenceService.NeedsPartialRefresh())
{
if (_fenceService.NeedsPartialRefresh())
{
_fenceService.GenerateFenceAssorts();
}
continue;
_fenceService.GenerateFenceAssorts();
}
continue;
}
}
// Trader needs to be refreshed
@@ -203,8 +201,8 @@ public class TraderController(
{
{ "5449016a4bdc2d6f028b456f", handbookPrices[Money.ROUBLES] },
{ "569668774bdc2da2298b4568", handbookPrices[Money.EUROS] },
{ "5696686a4bdc2da3298b456a", handbookPrices[Money.DOLLARS] }
}
{ "5696686a4bdc2da3298b456a", handbookPrices[Money.DOLLARS] },
},
};
}
}
@@ -23,7 +23,6 @@ public class WeatherController(
{
protected WeatherConfig _weatherConfig = _configServer.GetConfig<WeatherConfig>();
/// <summary>
/// Handle client/weather
/// </summary>
@@ -36,7 +35,7 @@ public class WeatherController(
Time = "",
Date = "",
Weather = null,
Season = Season.AUTUMN
Season = Season.AUTUMN,
};
_weatherGenerator.CalculateGameTime(result);
@@ -55,7 +54,7 @@ public class WeatherController(
var result = new GetLocalWeatherResponseData
{
Season = _seasonalEventService.GetActiveWeatherSeason(),
Weather = []
Weather = [],
};
result.Weather.AddRange(_raidWeatherService.GetUpcomingWeather());
@@ -7,9 +7,7 @@ using SPTarkov.Server.Core.Routers;
namespace SPTarkov.Server.Core.Controllers;
[Injectable]
public class WishlistController(
EventOutputHolder _eventOutputHolder
)
public class WishlistController(EventOutputHolder _eventOutputHolder)
{
/// <summary>
/// Handle AddToWishList
@@ -21,7 +19,8 @@ public class WishlistController(
public ItemEventRouterResponse AddToWishList(
PmcData pmcData,
AddToWishlistRequest request,
string sessionId)
string sessionId
)
{
foreach (var item in request.Items)
{
@@ -41,7 +40,8 @@ public class WishlistController(
public ItemEventRouterResponse RemoveFromWishList(
PmcData pmcData,
RemoveFromWishlistRequest request,
string sessionId)
string sessionId
)
{
foreach (var itemId in request.Items)
{
@@ -61,7 +61,8 @@ public class WishlistController(
public ItemEventRouterResponse ChangeWishListItemCategory(
PmcData pmcData,
ChangeWishlistItemCategoryRequest request,
string sessionId)
string sessionId
)
{
pmcData.WishList.Dictionary[request.Item] = request.Category.Value;