skip btr driver and lightkeeper quest rewards (#262)
* skip btr driver and lightkeeper quest rewards * remove new line * fixed circular dep * fixes based on feedback * more feedback fixes
This commit is contained in:
@@ -76,7 +76,8 @@ public class QuestRewardHelper(
|
||||
fullProfile,
|
||||
profileData,
|
||||
questId,
|
||||
questResponse
|
||||
questResponse,
|
||||
questDetails
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,22 +28,25 @@ public class RewardHelper(
|
||||
PlayerService _playerService
|
||||
)
|
||||
{
|
||||
/**
|
||||
* Apply the given rewards to the passed in profile
|
||||
* @param rewards List of rewards to apply
|
||||
* @param source The source of the rewards (Achievement, quest)
|
||||
* @param fullProfile The full profile to apply the rewards to
|
||||
* @param questId The quest or achievement ID, used for finding production unlocks
|
||||
* @param questResponse Response to quest completion when a production is unlocked
|
||||
* @returns List of items that were rewarded
|
||||
*/
|
||||
/// <summary>
|
||||
/// Apply the given rewards to the passed in profile.
|
||||
/// </summary>
|
||||
/// <param name="rewards">List of rewards to apply.</param>
|
||||
/// <param name="source">The source of the rewards (Achievement, quest).</param>
|
||||
/// <param name="fullProfile">The full profile to apply the rewards to.</param>
|
||||
/// <param name="profileData">The profile data (could be the scav profile).</param>
|
||||
/// <param name="rewardSourceId">The quest or achievement ID, used for finding production unlocks.</param>
|
||||
/// <param name="questResponse">Response to quest completion when a production is unlocked.</param>
|
||||
/// <param name="quest">The quest that the reward is for.</param>
|
||||
/// <returns>List of items that is the reward.</returns>
|
||||
public List<Item> ApplyRewards(
|
||||
List<Reward> rewards,
|
||||
string source,
|
||||
SptProfile fullProfile,
|
||||
PmcData profileData,
|
||||
string questId,
|
||||
ItemEventRouterResponse questResponse = null
|
||||
string rewardSourceId,
|
||||
ItemEventRouterResponse? questResponse = null,
|
||||
Quest? quest = null
|
||||
)
|
||||
{
|
||||
var sessionId = fullProfile?.ProfileInfo?.ProfileId;
|
||||
@@ -56,6 +59,15 @@ public class RewardHelper(
|
||||
|
||||
var gameVersion = pmcProfile.Info.GameVersion;
|
||||
|
||||
var isInGameRewardTrader = quest != null && IsInGameRewardTrader(quest);
|
||||
if (isInGameRewardTrader)
|
||||
{
|
||||
_logger.Debug(
|
||||
$"Skipping quest rewards for quest {quest.Id} as it is in the InGameRewardrTader list"
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach (var reward in rewards)
|
||||
{
|
||||
// Handle reward availability for different game versions, notAvailableInGameEditions currently not used
|
||||
@@ -102,13 +114,16 @@ public class RewardHelper(
|
||||
AddAchievementToProfile(fullProfile, reward.Target);
|
||||
break;
|
||||
case RewardType.StashRows:
|
||||
_profileHelper.AddStashRowsBonusToProfile(
|
||||
sessionId,
|
||||
(int) reward.Value
|
||||
); // Add specified stash rows from reward - requires client restart
|
||||
_profileHelper.AddStashRowsBonusToProfile(sessionId, (int)reward.Value); // Add specified stash rows from reward - requires client restart
|
||||
break;
|
||||
case RewardType.ProductionScheme:
|
||||
FindAndAddHideoutProductionIdToProfile(pmcProfile, reward, questId, sessionId, questResponse);
|
||||
FindAndAddHideoutProductionIdToProfile(
|
||||
pmcProfile,
|
||||
reward,
|
||||
rewardSourceId,
|
||||
sessionId,
|
||||
questResponse
|
||||
);
|
||||
break;
|
||||
case RewardType.Pockets:
|
||||
_profileHelper.ReplaceProfilePocketTpl(pmcProfile, reward.Target);
|
||||
@@ -120,37 +135,61 @@ public class RewardHelper(
|
||||
_logger.Error(
|
||||
_localisationService.GetText(
|
||||
"reward-type_not_handled",
|
||||
new
|
||||
{
|
||||
rewardType = reward.Type,
|
||||
questId
|
||||
}
|
||||
new { rewardType = reward.Type, rewardSourceId }
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return GetRewardItems(rewards, gameVersion);
|
||||
return GetRewardItems(rewards, gameVersion, quest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the provided reward have a game version requirement to be given and does it match
|
||||
* @param reward Reward to check
|
||||
* @param gameVersion Version of game to check reward against
|
||||
* @returns True if it has requirement, false if it doesnt pass check
|
||||
*/
|
||||
/// <summary>
|
||||
/// Value for in game reward traders to not duplicate quest rewards.
|
||||
/// Value can be modified by modders by overriding this value with new traders.
|
||||
/// Ensure to add Lightkeeper's ID (638f541a29ffd1183d187f57) and BTR Driver's ID (656f0f98d80a697f855d34b1)
|
||||
/// </summary>
|
||||
protected string[] noRewardTraders =
|
||||
[
|
||||
// LightKeeper
|
||||
"638f541a29ffd1183d187f57",
|
||||
// BTR Driver
|
||||
"656f0f98d80a697f855d34b1",
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Determines if quest rewards are given in raid by the trader instead of through messaging system.
|
||||
/// </summary>
|
||||
/// <param name="quest">The quest to check.</param>
|
||||
/// <returns>True if the quest's trader is in the in-game reward trader list; otherwise, false.</returns>
|
||||
protected bool IsInGameRewardTrader(Quest quest)
|
||||
{
|
||||
return noRewardTraders.Contains(quest.TraderId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the provided reward have a game version requirement to be given and does it match.
|
||||
/// </summary>
|
||||
/// <param name="reward">Reward to check.</param>
|
||||
/// <param name="gameVersion">Version of game to check reward against.</param>
|
||||
/// <returns>True if it has requirement, false if it doesn't pass check.</returns>
|
||||
public bool RewardIsForGameEdition(Reward reward, string gameVersion)
|
||||
{
|
||||
if (reward.AvailableInGameEditions?.Count > 0 && !reward.AvailableInGameEditions.Contains(gameVersion))
|
||||
// Reward has edition whitelist and game version isn't in it
|
||||
if (
|
||||
reward.AvailableInGameEditions?.Count > 0
|
||||
&& !reward.AvailableInGameEditions.Contains(gameVersion)
|
||||
)
|
||||
// Reward has edition whitelist and game version isn't in it
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reward.NotAvailableInGameEditions?.Count > 0 &&
|
||||
reward.NotAvailableInGameEditions.Contains(gameVersion))
|
||||
// Reward has edition blacklist and game version is in it
|
||||
if (
|
||||
reward.NotAvailableInGameEditions?.Count > 0
|
||||
&& reward.NotAvailableInGameEditions.Contains(gameVersion)
|
||||
)
|
||||
// Reward has edition blacklist and game version is in it
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -159,21 +198,22 @@ public class RewardHelper(
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* WIP - Find hideout craft id and add to unlockedProductionRecipe array in player profile
|
||||
* also update client response recipeUnlocked array with craft id
|
||||
* @param pmcData Player profile
|
||||
* @param craftUnlockReward Reward with craft unlock details
|
||||
* @param questId Quest or achievement ID with craft unlock reward
|
||||
* @param sessionID Session id
|
||||
* @param response Response to send back to client
|
||||
*/
|
||||
/// <summary>
|
||||
/// WIP - Find hideout craft id and add to unlockedProductionRecipe array in player profile
|
||||
/// also update client response recipeUnlocked array with craft id
|
||||
/// </summary>
|
||||
/// <param name="pmcData">Player profile.</param>
|
||||
/// <param name="craftUnlockReward">Reward with craft unlock details.</param>
|
||||
/// <param name="questId">Quest or achievement ID with craft unlock reward.</param>
|
||||
/// <param name="sessionID">Session id.</param>
|
||||
/// <param name="response">Response to send back to client.</param>
|
||||
protected void FindAndAddHideoutProductionIdToProfile(
|
||||
PmcData pmcData,
|
||||
Reward craftUnlockReward,
|
||||
string questId,
|
||||
string sessionID,
|
||||
ItemEventRouterResponse response)
|
||||
ItemEventRouterResponse response
|
||||
)
|
||||
{
|
||||
var matchingProductions = GetRewardProductionMatch(craftUnlockReward, questId);
|
||||
if (matchingProductions.Count != 1)
|
||||
@@ -181,11 +221,7 @@ public class RewardHelper(
|
||||
_logger.Error(
|
||||
_localisationService.GetText(
|
||||
"reward-unable_to_find_matching_hideout_production",
|
||||
new
|
||||
{
|
||||
questId,
|
||||
matchCount = matchingProductions.Count
|
||||
}
|
||||
new { questId, matchCount = matchingProductions.Count }
|
||||
)
|
||||
);
|
||||
|
||||
@@ -202,50 +238,60 @@ public class RewardHelper(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find hideout craft for the specified reward
|
||||
* @param craftUnlockReward Reward with craft unlock details
|
||||
* @param questId Quest or achievement ID with craft unlock reward
|
||||
* @returns Hideout craft
|
||||
*/
|
||||
public List<HideoutProduction> GetRewardProductionMatch(Reward craftUnlockReward, string questId)
|
||||
/// <summary>
|
||||
/// Find hideout craft for the specified reward.
|
||||
/// </summary>
|
||||
/// <param name="craftUnlockReward">Reward with craft unlock details.</param>
|
||||
/// <param name="questId">Quest or achievement ID with craft unlock reward.</param>
|
||||
/// <returns>List of matching HideoutProduction objects.</returns>
|
||||
public List<HideoutProduction> GetRewardProductionMatch(
|
||||
Reward craftUnlockReward,
|
||||
string questId
|
||||
)
|
||||
{
|
||||
// Get hideout crafts and find those that match by areatype/required level/end product tpl - hope for just one match
|
||||
var craftingRecipes = _databaseService.GetHideout().Production.Recipes;
|
||||
|
||||
// Area that will be used to craft unlocked item
|
||||
var desiredHideoutAreaType = (HideoutAreas) int.Parse(craftUnlockReward.TraderId.ToString());
|
||||
var desiredHideoutAreaType = (HideoutAreas)int.Parse(craftUnlockReward.TraderId.ToString());
|
||||
|
||||
var matchingProductions = craftingRecipes.Where(prod =>
|
||||
prod.AreaType == desiredHideoutAreaType &&
|
||||
var matchingProductions = craftingRecipes
|
||||
.Where(prod =>
|
||||
prod.AreaType == desiredHideoutAreaType
|
||||
&&
|
||||
//prod.requirements.some((requirement) => requirement.questId == questId) && // BSG don't store the quest id in requirement any more!
|
||||
prod.Requirements.Any(requirement => requirement.Type == "QuestComplete") &&
|
||||
prod.Requirements.Any(requirement => requirement.RequiredLevel == craftUnlockReward.LoyaltyLevel
|
||||
) &&
|
||||
prod.EndProduct == craftUnlockReward.Items.FirstOrDefault().Template
|
||||
prod.Requirements.Any(requirement => requirement.Type == "QuestComplete")
|
||||
&& prod.Requirements.Any(requirement =>
|
||||
requirement.RequiredLevel == craftUnlockReward.LoyaltyLevel
|
||||
)
|
||||
&& prod.EndProduct == craftUnlockReward.Items.FirstOrDefault().Template
|
||||
)
|
||||
.ToList();
|
||||
|
||||
// More/less than single match, above filtering wasn't strict enough
|
||||
if (matchingProductions.Count != 1)
|
||||
// Multiple matches were found, last ditch attempt to match by questid (value we add manually to production.json via `gen:productionquests` command)
|
||||
// Multiple matches were found, last ditch attempt to match by questid (value we add manually to production.json via `gen:productionquests` command)
|
||||
{
|
||||
matchingProductions = matchingProductions.Where(prod =>
|
||||
prod.Requirements.Any(requirement => requirement.QuestId == questId)
|
||||
)
|
||||
matchingProductions = matchingProductions
|
||||
.Where(prod => prod.Requirements.Any(requirement => requirement.QuestId == questId))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return matchingProductions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a flat list of reward items from the given rewards for the specified game version
|
||||
* @param rewards Array of rewards to get the items from
|
||||
* @param gameVersion The game version of the profile
|
||||
* @returns array of items with the correct maxStack
|
||||
*/
|
||||
protected List<Item> GetRewardItems(List<Reward> rewards, string gameVersion)
|
||||
/// <summary>
|
||||
/// Gets a flat list of reward items from the given rewards for the specified game version.
|
||||
/// </summary>
|
||||
/// <param name="rewards">Array of rewards to get the items from.</param>
|
||||
/// <param name="gameVersion">The game version of the profile.</param>
|
||||
/// <param name="quest">The quest (optional).</param>
|
||||
/// <returns>Array of items with the correct maxStack.</returns>
|
||||
protected List<Item> GetRewardItems(
|
||||
List<Reward> rewards,
|
||||
string gameVersion,
|
||||
Quest? quest = null
|
||||
)
|
||||
{
|
||||
// Iterate over all rewards with the desired status, flatten out items that have a type of Item
|
||||
var rewardItems = rewards.SelectMany(reward =>
|
||||
@@ -257,11 +303,11 @@ public class RewardHelper(
|
||||
return rewardItems.ToList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Take reward item and set FiR status + fix stack sizes + fix mod Ids
|
||||
* @param reward Reward item to fix
|
||||
* @returns Fixed rewards
|
||||
*/
|
||||
/// <summary>
|
||||
/// Take reward item and set FiR status, fix stack sizes, and fix mod Ids.
|
||||
/// </summary>
|
||||
/// <param name="reward">Reward item to fix.</param>
|
||||
/// <returns>Fixed rewards.</returns>
|
||||
protected List<Item> ProcessReward(Reward reward)
|
||||
{
|
||||
/** item with mods to return */
|
||||
@@ -271,10 +317,10 @@ public class RewardHelper(
|
||||
|
||||
// Is armor item that may need inserts / plates
|
||||
if (reward.Items.Count == 1 && _itemHelper.ArmorItemCanHoldMods(reward.Items[0].Template))
|
||||
// Only process items with slots
|
||||
// Only process items with slots
|
||||
{
|
||||
if (_itemHelper.ItemHasSlots(reward.Items.FirstOrDefault().Template))
|
||||
// Attempt to pull default preset from globals and add child items to reward (clones reward.items)
|
||||
// Attempt to pull default preset from globals and add child items to reward (clones reward.items)
|
||||
{
|
||||
GenerateArmorRewardChildSlots(reward.Items.FirstOrDefault(), reward);
|
||||
}
|
||||
@@ -292,10 +338,12 @@ public class RewardHelper(
|
||||
{
|
||||
// Is base reward item
|
||||
if (
|
||||
rewardItem.ParentId != null &&
|
||||
rewardItem.ParentId == "hideout" && // Has parentId of hideout
|
||||
rewardItem.Upd != null &&
|
||||
rewardItem.Upd.StackObjectsCount != null && // Has upd with stackobject count
|
||||
rewardItem.ParentId != null
|
||||
&& rewardItem.ParentId == "hideout"
|
||||
&& // Has parentId of hideout
|
||||
rewardItem.Upd != null
|
||||
&& rewardItem.Upd.StackObjectsCount != null
|
||||
&& // Has upd with stackobject count
|
||||
rewardItem.Upd.StackObjectsCount > 1 // More than 1 item in stack
|
||||
)
|
||||
{
|
||||
@@ -314,11 +362,18 @@ public class RewardHelper(
|
||||
{
|
||||
// Is child mod
|
||||
if (reward.Items.FirstOrDefault().Upd.SpawnedInSession.GetValueOrDefault(false))
|
||||
// Propagate FiR status into child items
|
||||
// Propagate FiR status into child items
|
||||
{
|
||||
if (!_itemHelper.IsOfBaseclasses(rewardItem.Template, [BaseClasses.AMMO, BaseClasses.MONEY]))
|
||||
if (
|
||||
!_itemHelper.IsOfBaseclasses(
|
||||
rewardItem.Template,
|
||||
[BaseClasses.AMMO, BaseClasses.MONEY]
|
||||
)
|
||||
)
|
||||
{
|
||||
rewardItem.Upd.SpawnedInSession = reward.Items.FirstOrDefault()?.Upd.SpawnedInSession;
|
||||
rewardItem.Upd.SpawnedInSession = reward
|
||||
.Items.FirstOrDefault()
|
||||
?.Upd.SpawnedInSession;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,10 +385,7 @@ public class RewardHelper(
|
||||
foreach (var target in targets)
|
||||
{
|
||||
// This has all the original id relations since we reset the id to the original after the splitStack
|
||||
var itemsClone = new List<Item>
|
||||
{
|
||||
_cloner.Clone(target)
|
||||
};
|
||||
var itemsClone = new List<Item> { _cloner.Clone(target) };
|
||||
// Here we generate a new id for the root item
|
||||
target.Id = _hashUtil.Generate();
|
||||
|
||||
@@ -352,11 +404,11 @@ public class RewardHelper(
|
||||
return rewardItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add missing mod items to an armor reward
|
||||
* @param originalRewardRootItem Original armor reward item from IReward.items object
|
||||
* @param reward Armor reward
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add missing mod items to an armor reward.
|
||||
/// </summary>
|
||||
/// <param name="originalRewardRootItem">Original armor reward item from IReward.items object.</param>
|
||||
/// <param name="reward">Armor reward.</param>
|
||||
protected void GenerateArmorRewardChildSlots(Item originalRewardRootItem, Reward reward)
|
||||
{
|
||||
// Look for a default preset from globals for armor
|
||||
@@ -390,17 +442,19 @@ public class RewardHelper(
|
||||
reward.Items = _itemHelper.AddChildSlotItems(reward.Items, itemDbData, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an achievement to player profile and handle any rewards for the achievement
|
||||
* Triggered from a quest, or another achievement
|
||||
* @param fullProfile Profile to add achievement to
|
||||
* @param achievementId Id of achievement to add
|
||||
*/
|
||||
/// <summary>
|
||||
/// Add an achievement to player profile and handle any rewards for the achievement.
|
||||
/// Triggered from a quest, or another achievement.
|
||||
/// </summary>
|
||||
/// <param name="fullProfile">Profile to add achievement to.</param>
|
||||
/// <param name="achievementId">Id of achievement to add.</param>
|
||||
public void AddAchievementToProfile(SptProfile fullProfile, string achievementId)
|
||||
{
|
||||
// Add achievement id to profile with timestamp it was unlocked
|
||||
fullProfile.CharacterData.PmcData.Achievements.TryAdd(achievementId, _timeUtil.GetTimeStamp());
|
||||
|
||||
fullProfile.CharacterData.PmcData.Achievements.TryAdd(
|
||||
achievementId,
|
||||
_timeUtil.GetTimeStamp()
|
||||
);
|
||||
|
||||
// Check for any customisation unlocks
|
||||
var achievementDataDb = _databaseService
|
||||
|
||||
Reference in New Issue
Block a user