Merge pull request #601 from sp-tarkov/repeatable-completion-quests

Repeatable completion quest level ranges
This commit is contained in:
Cj
2025-10-02 15:02:05 -04:00
committed by GitHub
parent 136c79b385
commit cf29c7bde3
5 changed files with 341 additions and 92 deletions
@@ -47,7 +47,13 @@ public class CompletionQuestGenerator(
RepeatableQuestConfig repeatableConfig
)
{
var completionConfig = repeatableConfig.QuestConfig.CompletionConfig;
var completionConfig = repeatableQuestHelper.GetCompletionConfigByPmcLevel(pmcLevel, repeatableConfig);
if (completionConfig is null)
{
logger.Warning(localisationService.GetText("repeatable-completion_config_no_template", new { pmcLevel }));
return null;
}
var levelsConfig = repeatableConfig.RewardScaling.Levels;
var roublesConfig = repeatableConfig.RewardScaling.Roubles;
@@ -73,12 +79,12 @@ public class CompletionQuestGenerator(
// We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as
// [{"minPlayerLevel": 1, "itemIds": ["id1",...]}, {"minPlayerLevel": 15, "itemIds": ["id3",...]}]
if (repeatableConfig.QuestConfig.CompletionConfig.UseWhitelist)
if (completionConfig.UseWhitelist)
{
itemsToRetrievePool = GetWhitelistedItemSelection(itemsToRetrievePool, pmcLevel);
}
if (repeatableConfig.QuestConfig.CompletionConfig.UseBlacklist)
if (completionConfig.UseBlacklist)
{
itemsToRetrievePool = GetBlacklistedItemSelection(itemsToRetrievePool, pmcLevel);
}
@@ -91,7 +97,7 @@ public class CompletionQuestGenerator(
return null;
}
var selectedItems = GenerateAvailableForFinish(quest, completionConfig, repeatableConfig, itemsToRetrievePool.ToList(), budget);
var selectedItems = GenerateAvailableForFinish(quest, completionConfig, itemsToRetrievePool.ToList(), budget);
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(
pmcLevel,
@@ -240,20 +246,18 @@ public class CompletionQuestGenerator(
/// </summary>
/// <param name="quest">Quest to add the conditions to</param>
/// <param name="completionConfig">Completion config</param>
/// <param name="repeatableConfig">Repeatable config</param>
/// <param name="itemSelection">Filtered item selection</param>
/// <param name="roublesBudget">Budget in roubles</param>
/// <returns>Chosen item template Ids</returns>
protected List<MongoId> GenerateAvailableForFinish(
RepeatableQuest quest,
CompletionConfig completionConfig,
RepeatableQuestConfig repeatableConfig,
List<MongoId> itemSelection,
double roublesBudget
)
{
// Store the indexes of items we are asking player to supply
var distinctItemsToRetrieveCount = randomUtil.GetInt(1, completionConfig.UniqueItemCount);
var distinctItemsToRetrieveCount = randomUtil.GetInt(completionConfig.UniqueItemCount.Min, completionConfig.UniqueItemCount.Max);
var chosenRequirementItemsTpls = new List<MongoId>();
var usedItemIndexes = new HashSet<int>();
@@ -289,8 +293,8 @@ public class CompletionQuestGenerator(
var tplChosen = itemSelection[chosenItemIndex];
var itemPrice = itemHelper.GetItemPrice(tplChosen)!.Value;
var minValue = completionConfig.MinimumRequestedAmount;
var maxValue = completionConfig.MaximumRequestedAmount;
var minValue = completionConfig.RequestedItemCount.Min;
var maxValue = completionConfig.RequestedItemCount.Max;
var value = minValue;
@@ -308,7 +312,7 @@ public class CompletionQuestGenerator(
// Push a CompletionCondition with the item and the amount of the item into quest
chosenRequirementItemsTpls.Add(tplChosen);
quest.Conditions.AvailableForFinish!.Add(GenerateCondition(tplChosen, value, repeatableConfig.QuestConfig.CompletionConfig));
quest.Conditions.AvailableForFinish!.Add(GenerateCondition(tplChosen, value, completionConfig));
// Is there budget left for more items
if (roublesBudget > 0)
@@ -45,6 +45,19 @@ public class RepeatableQuestHelper(
);
}
/// <summary>
/// Get the relevant completion config based on the current players PMC level
/// </summary>
/// <param name="pmcLevel">Level of PMC character</param>
/// <param name="repeatableConfig">Main repeatable config</param>
/// <returns>CompletionConfig</returns>
public CompletionConfig? GetCompletionConfigByPmcLevel(int pmcLevel, RepeatableQuestConfig repeatableConfig)
{
return repeatableConfig.QuestConfig.CompletionConfig.FirstOrDefault(x =>
pmcLevel >= x.LevelRange.Min && pmcLevel <= x.LevelRange.Max
);
}
/// <summary>
/// Gets a cloned repeatable quest template for the provided type with a unique id
/// </summary>
@@ -344,7 +344,7 @@ public record RepeatableQuestTypesConfig
/// Defines completion repeatable task generation parameters
/// </summary>
[JsonPropertyName("Completion")]
public required CompletionConfig CompletionConfig { get; set; }
public required List<CompletionConfig> CompletionConfig { get; set; }
/// <summary>
/// Defines pickup repeatable task generation parameters - TODO: Not implemented/No Data - NOTE: Does not work with dynamicLocale
@@ -416,34 +416,28 @@ public record SpecificExits
public record CompletionConfig : BaseQuestConfig
{
/// <summary>
/// Minimum item count that can be requested
/// Level range at which completion tasks should be generated from this config
/// </summary>
[JsonPropertyName("minRequestedAmount")]
public required int MinimumRequestedAmount { get; set; }
[JsonPropertyName("levelRange")]
public required MinMax<int> LevelRange { get; set; }
/// <summary>
/// Maximum item count that can be requested
/// The minimum and maximum amounts that can be requested for an item
/// </summary>
[JsonPropertyName("maxRequestedAmount")]
public required int MaximumRequestedAmount { get; set; }
[JsonPropertyName("requestedItemCount")]
public required MinMax<int> RequestedItemCount { get; set; }
/// <summary>
/// How many unique items should be requested - TODO: This needs to be a range
/// How many different unique items should be requested
/// </summary>
[JsonPropertyName("uniqueItemCount")]
public required int UniqueItemCount { get; set; }
public required MinMax<int> UniqueItemCount { get; set; }
/// <summary>
/// Minimum bullet count that can be requested - TODO: Not implemented
/// The minimum and maximum amounts that can be requested for bullets - TODO: Not implemented
/// </summary>
[JsonPropertyName("minRequestedBulletAmount")]
public required int MinimumRequestedBulletAmount { get; set; }
/// <summary>
/// Maximum bullet count that can be requested - TODO: Not implemented
/// </summary>
[JsonPropertyName("maxRequestedBulletAmount")]
public required int MaximumRequestedBulletAmount { get; set; }
[JsonPropertyName("requestedBulletCount")]
public required MinMax<int> RequestedBulletCount { get; set; }
/// <summary>
/// Should the item whitelist be used
@@ -467,7 +461,7 @@ public record CompletionConfig : BaseQuestConfig
/// Min/Max durability requirements for the item
/// </summary>
[JsonPropertyName("requiredItemMinDurabilityMinMax")]
public required MinMax<double> RequiredItemMinDurabilityMinMax { get; set; }
public required MinMax<int> RequiredItemMinDurabilityMinMax { get; set; }
/// <summary>
/// Blacklisted item types to not collect