Warning fixes continued (#550)
* More warning fixes * Revert ModHelper change
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Reflection;
|
||||
using SPTarkov.DI.Annotations;
|
||||
using SPTarkov.Server.Core.Utils;
|
||||
|
||||
|
||||
@@ -25,30 +25,31 @@ public class NotificationSendHelper(
|
||||
/// <summary>
|
||||
/// Send notification message to the appropriate channel
|
||||
/// </summary>
|
||||
/// <param name="sessionID">Session/player id</param>
|
||||
/// <param name="sessionId">Session/player id</param>
|
||||
/// <param name="notificationMessage"></param>
|
||||
public void SendMessage(MongoId sessionID, WsNotificationEvent notificationMessage)
|
||||
public void SendMessage(MongoId sessionId, WsNotificationEvent notificationMessage)
|
||||
{
|
||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
logger.Debug($"Send message for {sessionID} started, message: {jsonUtil.Serialize(notificationMessage)}");
|
||||
logger.Debug($"Send message for {sessionId} started, message: {jsonUtil.Serialize(notificationMessage)}");
|
||||
}
|
||||
if (sptWebSocketConnectionHandler.IsWebSocketConnected(sessionID))
|
||||
|
||||
if (sptWebSocketConnectionHandler.IsWebSocketConnected(sessionId))
|
||||
{
|
||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
logger.Debug($"Send message for {sessionID} websocket available, message being sent");
|
||||
logger.Debug($"Send message for {sessionId} websocket available, message being sent");
|
||||
}
|
||||
sptWebSocketConnectionHandler.SendMessage(sessionID, notificationMessage);
|
||||
sptWebSocketConnectionHandler.SendMessage(sessionId, notificationMessage);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||
{
|
||||
logger.Debug($"Send message for {sessionID} websocket not available, queueing into profile");
|
||||
}
|
||||
notificationService.Add(sessionID, notificationMessage);
|
||||
logger.Debug($"Send message for {sessionId} websocket not available, queueing into profile");
|
||||
}
|
||||
|
||||
notificationService.Add(sessionId, notificationMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,6 +62,11 @@ public class NotificationSendHelper(
|
||||
public void SendMessageToPlayer(MongoId sessionId, UserDialogInfo senderDetails, string messageText, MessageType messageType)
|
||||
{
|
||||
var dialog = GetDialog(sessionId, messageType, senderDetails);
|
||||
if (dialog is null)
|
||||
{
|
||||
// Error is logged in GetDialog
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.New += 1;
|
||||
var message = new Message
|
||||
@@ -74,7 +80,18 @@ public class NotificationSendHelper(
|
||||
RewardCollected = null,
|
||||
Items = null,
|
||||
};
|
||||
dialog.Messages.Add(message);
|
||||
|
||||
if (dialog.Messages != null)
|
||||
{
|
||||
dialog.Messages.Add(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error(
|
||||
$"Could not add message Id: {message.Id.ToString()} to dialogue for player Id: {sessionId.ToString()}. dialog.Messages is null. Message was not sent."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var notification = new WsChatMessageReceived
|
||||
{
|
||||
@@ -93,7 +110,7 @@ public class NotificationSendHelper(
|
||||
/// <param name="messageType">Type of message to generate</param>
|
||||
/// <param name="senderDetails">Who is sending the message</param>
|
||||
/// <returns>Dialogue</returns>
|
||||
protected Models.Eft.Profile.Dialogue GetDialog(MongoId sessionId, MessageType messageType, UserDialogInfo senderDetails)
|
||||
protected Models.Eft.Profile.Dialogue? GetDialog(MongoId sessionId, MessageType messageType, UserDialogInfo senderDetails)
|
||||
{
|
||||
// Use trader id if sender is trader, otherwise use nickname
|
||||
var dialogKey = senderDetails.Id;
|
||||
@@ -102,12 +119,23 @@ public class NotificationSendHelper(
|
||||
var dialogueData = saveServer.GetProfile(sessionId).DialogueRecords;
|
||||
|
||||
// Ensure empty dialog exists based on sender details passed in
|
||||
dialogueData.TryAdd(dialogKey, GetEmptyDialogTemplate(dialogKey, messageType, senderDetails));
|
||||
if (dialogueData?.TryAdd(dialogKey, GetEmptyDialogTemplate(dialogKey, messageType, senderDetails)) ?? false)
|
||||
{
|
||||
return dialogueData[dialogKey];
|
||||
}
|
||||
|
||||
return dialogueData[dialogKey];
|
||||
logger.Error($"Could not add dialog key: {dialogKey.ToString()} to dialogueData for player Id: {sessionId.ToString()}.");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Models.Eft.Profile.Dialogue GetEmptyDialogTemplate(string dialogKey, MessageType messageType, UserDialogInfo senderDetails)
|
||||
/// <summary>
|
||||
/// Get an empty dialog template
|
||||
/// </summary>
|
||||
/// <param name="dialogKey">Key to assign</param>
|
||||
/// <param name="messageType">Type of message</param>
|
||||
/// <param name="senderDetails">Sender details</param>
|
||||
/// <returns>Empty dialog template</returns>
|
||||
protected Models.Eft.Profile.Dialogue GetEmptyDialogTemplate(MongoId dialogKey, MessageType messageType, UserDialogInfo senderDetails)
|
||||
{
|
||||
return new Models.Eft.Profile.Dialogue
|
||||
{
|
||||
@@ -117,7 +145,7 @@ public class NotificationSendHelper(
|
||||
Pinned = false,
|
||||
New = 0,
|
||||
AttachmentsNew = 0,
|
||||
Users = senderDetails.Info.MemberCategory == MemberCategory.Trader ? null : [senderDetails],
|
||||
Users = senderDetails.Info?.MemberCategory == MemberCategory.Trader ? null : [senderDetails],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ namespace SPTarkov.Server.Core.Helpers;
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class NotifierHelper(HttpServerHelper httpServerHelper)
|
||||
{
|
||||
protected static readonly WsPing ping = new();
|
||||
protected static readonly WsPing Ping = new();
|
||||
|
||||
public WsNotificationEvent GetDefaultNotification()
|
||||
{
|
||||
return ping;
|
||||
return Ping;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace SPTarkov.Server.Core.Helpers;
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class PaymentHelper(ConfigServer configServer)
|
||||
{
|
||||
protected bool _addedCustomMoney;
|
||||
protected readonly InventoryConfig _inventoryConfig = configServer.GetConfig<InventoryConfig>();
|
||||
protected readonly HashSet<MongoId> _moneyTpls = [Money.DOLLARS, Money.EUROS, Money.ROUBLES, Money.GP];
|
||||
protected bool AddedCustomMoney;
|
||||
protected readonly InventoryConfig InventoryConfig = configServer.GetConfig<InventoryConfig>();
|
||||
protected readonly HashSet<MongoId> MoneyTpls = [Money.DOLLARS, Money.EUROS, Money.ROUBLES, Money.GP];
|
||||
|
||||
/// <summary>
|
||||
/// Is the passed in tpl money (also checks custom currencies in inventoryConfig.customMoneyTpls)
|
||||
@@ -21,16 +21,16 @@ public class PaymentHelper(ConfigServer configServer)
|
||||
public bool IsMoneyTpl(MongoId tpl)
|
||||
{
|
||||
// Add custom currency first time this method is accessed
|
||||
if (!_addedCustomMoney)
|
||||
if (!AddedCustomMoney)
|
||||
{
|
||||
foreach (var customMoney in _inventoryConfig.CustomMoneyTpls)
|
||||
foreach (var customMoney in InventoryConfig.CustomMoneyTpls)
|
||||
{
|
||||
_moneyTpls.Add(customMoney);
|
||||
MoneyTpls.Add(customMoney);
|
||||
}
|
||||
|
||||
_addedCustomMoney = true;
|
||||
AddedCustomMoney = true;
|
||||
}
|
||||
|
||||
return _moneyTpls.Contains(tpl);
|
||||
return MoneyTpls.Contains(tpl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,17 @@ namespace SPTarkov.Server.Core.Helpers;
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper, ICloner cloner)
|
||||
{
|
||||
protected Dictionary<MongoId, Preset>? _defaultEquipmentPresets;
|
||||
protected Dictionary<MongoId, Preset>? _defaultWeaponPresets;
|
||||
protected Dictionary<MongoId, Preset>? DefaultEquipmentPresets;
|
||||
protected Dictionary<MongoId, Preset>? DefaultWeaponPresets;
|
||||
|
||||
/// <summary>
|
||||
/// Preset cache - key = item tpl, value = preset ids
|
||||
/// </summary>
|
||||
protected Dictionary<MongoId, PresetCacheDetails> _lookup = new();
|
||||
protected Dictionary<MongoId, PresetCacheDetails> PresetCache = new();
|
||||
|
||||
public void HydratePresetStore(Dictionary<MongoId, PresetCacheDetails> input)
|
||||
{
|
||||
_lookup = input;
|
||||
PresetCache = input;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,7 +48,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
return weapons
|
||||
.Concat(equipment)
|
||||
.Where(preset => preset.Items.Count > 0) // Some safety to prevent nullref
|
||||
.ToDictionary(preset => preset.Items.FirstOrDefault().Template);
|
||||
.ToDictionary(preset => preset.Items.FirstOrDefault()!.Template);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -57,15 +57,15 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// <returns></returns>
|
||||
public Dictionary<MongoId, Preset> GetDefaultWeaponPresets()
|
||||
{
|
||||
if (_defaultWeaponPresets is null)
|
||||
if (DefaultWeaponPresets is null)
|
||||
{
|
||||
var tempPresets = databaseService.GetGlobals().ItemPresets;
|
||||
_defaultWeaponPresets = tempPresets
|
||||
DefaultWeaponPresets = tempPresets
|
||||
.Where(p => p.Value.Encyclopedia != null && itemHelper.IsOfBaseclass(p.Value.Encyclopedia.Value, BaseClasses.WEAPON))
|
||||
.ToDictionary();
|
||||
}
|
||||
|
||||
return _defaultWeaponPresets;
|
||||
return DefaultWeaponPresets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -74,15 +74,15 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// <returns>Dictionary</returns>
|
||||
public Dictionary<MongoId, Preset> GetDefaultEquipmentPresets()
|
||||
{
|
||||
if (_defaultEquipmentPresets == null)
|
||||
if (DefaultEquipmentPresets == null)
|
||||
{
|
||||
var tempPresets = databaseService.GetGlobals().ItemPresets;
|
||||
_defaultEquipmentPresets = tempPresets
|
||||
DefaultEquipmentPresets = tempPresets
|
||||
.Where(p => p.Value.Encyclopedia != null && itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia.Value))
|
||||
.ToDictionary();
|
||||
}
|
||||
|
||||
return _defaultEquipmentPresets;
|
||||
return DefaultEquipmentPresets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -108,7 +108,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// <returns>True if the preset is of the given base class, false otherwise</returns>
|
||||
public bool IsPresetBaseClass(MongoId id, MongoId baseClass)
|
||||
{
|
||||
return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id).Encyclopedia.Value, baseClass);
|
||||
return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id)!.Encyclopedia!.Value, baseClass);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -118,10 +118,10 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// <returns>True if preset exists for tpl</returns>
|
||||
public bool HasPreset(MongoId templateId)
|
||||
{
|
||||
return _lookup.ContainsKey(templateId);
|
||||
return PresetCache.ContainsKey(templateId);
|
||||
}
|
||||
|
||||
public Preset GetPreset(MongoId id)
|
||||
public Preset? GetPreset(MongoId id)
|
||||
{
|
||||
return cloner.Clone(databaseService.GetGlobals().ItemPresets[id]);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// Get all presets from globals db
|
||||
/// </summary>
|
||||
/// <returns>List</returns>
|
||||
public List<Preset> GetAllPresets()
|
||||
public List<Preset>? GetAllPresets()
|
||||
{
|
||||
return cloner.Clone(databaseService.GetGlobals().ItemPresets.Values.ToList());
|
||||
}
|
||||
@@ -140,10 +140,10 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
/// </summary>
|
||||
/// <param name="templateId">Tpl to get presets for</param>
|
||||
/// <returns>List</returns>
|
||||
public List<Preset> GetPresets(MongoId templateId)
|
||||
public List<Preset>? GetPresets(MongoId templateId)
|
||||
{
|
||||
// Try adn get preset ids from cache if they exist
|
||||
if (!_lookup.TryGetValue(templateId, out var presetDetailsForTpl))
|
||||
// Try and get preset ids from cache if they exist
|
||||
if (!PresetCache.TryGetValue(templateId, out var presetDetailsForTpl))
|
||||
{
|
||||
// None found, early exit
|
||||
return [];
|
||||
@@ -161,7 +161,7 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
public Preset? GetDefaultPreset(MongoId templateId)
|
||||
{
|
||||
// look in main cache for presets for this tpl
|
||||
if (!_lookup.TryGetValue(templateId, out var presetDetails))
|
||||
if (!PresetCache.TryGetValue(templateId, out var presetDetails))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -172,9 +172,9 @@ public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper
|
||||
}
|
||||
|
||||
// Use default preset id from above cache to find the weapon/equipment preset
|
||||
if (!_defaultWeaponPresets.TryGetValue(presetDetails.DefaultId.Value, out var defaultPreset))
|
||||
if (DefaultWeaponPresets?.TryGetValue(presetDetails.DefaultId.Value, out var defaultPreset) is null or false)
|
||||
{
|
||||
if (!_defaultEquipmentPresets.TryGetValue(presetDetails.DefaultId.Value, out defaultPreset))
|
||||
if (DefaultEquipmentPresets?.TryGetValue(presetDetails.DefaultId.Value, out defaultPreset) is null or false)
|
||||
{
|
||||
// Default not found in weapon or equipment, return first preset in list
|
||||
return cloner.Clone(databaseService.GetGlobals().ItemPresets[presetDetails.PresetIds.First()]);
|
||||
|
||||
@@ -22,9 +22,9 @@ public class PrestigeHelper(
|
||||
{
|
||||
public void ProcessPendingPrestige(SptProfile oldProfile, SptProfile newProfile, PendingPrestige prestige)
|
||||
{
|
||||
var prePrestigePmc = oldProfile.CharacterData.PmcData;
|
||||
var sessionId = newProfile.ProfileInfo.ProfileId;
|
||||
var prestigeLevels = databaseService.GetTemplates().Prestige.Elements;
|
||||
var prePrestigePmc = oldProfile.CharacterData?.PmcData;
|
||||
var sessionId = newProfile.ProfileInfo?.ProfileId;
|
||||
var prestigeLevels = databaseService.GetTemplates().Prestige?.Elements ?? [];
|
||||
var indexOfPrestigeObtained = Math.Clamp((prestige.PrestigeLevel ?? 1) - 1, 0, prestigeLevels.Count - 1); // Levels are 1 to 4, Index is 0 to 3
|
||||
|
||||
// Skill copy
|
||||
@@ -34,37 +34,39 @@ public class PrestigeHelper(
|
||||
1 - prestigeLevels[indexOfPrestigeObtained].TransferConfigs.MasteringConfig.TransferMultiplier
|
||||
);
|
||||
|
||||
if (prePrestigePmc.Skills.Common is not null)
|
||||
if (prePrestigePmc?.Skills?.Common is not null)
|
||||
{
|
||||
var commonSKillsToCopy = prePrestigePmc.Skills.Common;
|
||||
foreach (var skillToCopy in commonSKillsToCopy)
|
||||
{
|
||||
// Set progress for 5% of what it was, multiplied by prestige level
|
||||
skillToCopy.Progress *= skillProgressCopyAmount;
|
||||
var existingSkill = newProfile.CharacterData.PmcData.Skills.Common.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
|
||||
var existingSkill = newProfile.CharacterData?.PmcData?.Skills?.Common.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
|
||||
if (existingSkill is not null)
|
||||
{
|
||||
existingSkill.Progress = skillToCopy.Progress;
|
||||
}
|
||||
else
|
||||
{
|
||||
newProfile.CharacterData.PmcData.Skills.Common = newProfile.CharacterData.PmcData.Skills.Common.Union([skillToCopy]);
|
||||
newProfile.CharacterData!.PmcData!.Skills!.Common = newProfile.CharacterData.PmcData.Skills.Common.Union([skillToCopy]);
|
||||
}
|
||||
}
|
||||
|
||||
var masteringSkillsToCopy = prePrestigePmc.Skills.Mastering;
|
||||
foreach (var skillToCopy in masteringSkillsToCopy)
|
||||
foreach (var skillToCopy in masteringSkillsToCopy ?? [])
|
||||
{
|
||||
// Set progress 5% of what it was, multiplied by prestige level
|
||||
skillToCopy.Progress *= masteringProgressCopyAmount;
|
||||
var existingSkill = newProfile.CharacterData.PmcData.Skills.Mastering.FirstOrDefault(skill => skill.Id == skillToCopy.Id);
|
||||
var existingSkill = newProfile.CharacterData?.PmcData?.Skills?.Mastering?.FirstOrDefault(skill =>
|
||||
skill.Id == skillToCopy.Id
|
||||
);
|
||||
if (existingSkill is not null)
|
||||
{
|
||||
existingSkill.Progress = skillToCopy.Progress;
|
||||
}
|
||||
else
|
||||
{
|
||||
newProfile.CharacterData.PmcData.Skills.Mastering = newProfile.CharacterData.PmcData.Skills.Mastering.Union(
|
||||
newProfile.CharacterData!.PmcData!.Skills!.Mastering = newProfile.CharacterData.PmcData.Skills.Mastering?.Union(
|
||||
[skillToCopy]
|
||||
);
|
||||
}
|
||||
@@ -73,30 +75,35 @@ public class PrestigeHelper(
|
||||
|
||||
// Add "Prestigious" achievement
|
||||
var prestigiousAchievement = new MongoId("676091c0f457869a94017a23");
|
||||
if (!newProfile.CharacterData.PmcData.Achievements.ContainsKey(prestigiousAchievement))
|
||||
if (newProfile.CharacterData?.PmcData?.Achievements?.ContainsKey(prestigiousAchievement) is false)
|
||||
{
|
||||
rewardHelper.AddAchievementToProfile(newProfile, prestigiousAchievement);
|
||||
}
|
||||
|
||||
// Assumes Prestige data is in descending order
|
||||
var currentPrestigeData = databaseService.GetTemplates().Prestige.Elements[indexOfPrestigeObtained];
|
||||
var currentPrestigeData = databaseService.GetTemplates().Prestige?.Elements[indexOfPrestigeObtained];
|
||||
|
||||
// Get all prestige rewards from prestige 1 up to desired prestige
|
||||
var prestigeRewards = prestigeLevels
|
||||
.Slice(0, indexOfPrestigeObtained + 1) // Index back to PrestigeLevel
|
||||
.SelectMany(prestige => prestige.Rewards);
|
||||
.SelectMany(prestigeInner => prestigeInner.Rewards);
|
||||
|
||||
AddPrestigeRewardsToProfile(sessionId.Value, newProfile, prestigeRewards);
|
||||
AddPrestigeRewardsToProfile(sessionId!.Value, newProfile, prestigeRewards);
|
||||
|
||||
// Flag profile as having achieved this prestige level
|
||||
newProfile.CharacterData.PmcData.Prestige.TryAdd(currentPrestigeData.Id, timeUtil.GetTimeStamp());
|
||||
if (newProfile.CharacterData?.PmcData?.Prestige?.TryAdd(currentPrestigeData!.Id, timeUtil.GetTimeStamp()) is false)
|
||||
{
|
||||
logger.Error(
|
||||
$"Failed to add prestige element with id: {currentPrestigeData.Id} to new profile during processing of pending prestige."
|
||||
);
|
||||
}
|
||||
|
||||
var itemsToTransfer = new List<Item>();
|
||||
|
||||
// Copy transferred items
|
||||
foreach (var transferRequest in prestige.Items ?? [])
|
||||
{
|
||||
var item = prePrestigePmc.Inventory.Items.FirstOrDefault(item => item.Id == transferRequest.Id);
|
||||
var item = prePrestigePmc?.Inventory?.Items?.FirstOrDefault(item => item.Id == transferRequest.Id);
|
||||
if (item is null)
|
||||
{
|
||||
logger.Error($"Unable to find item with id: {transferRequest.Id} in profile: {sessionId}, skipping");
|
||||
@@ -116,7 +123,7 @@ public class PrestigeHelper(
|
||||
);
|
||||
}
|
||||
|
||||
newProfile.CharacterData.PmcData.Info.PrestigeLevel = prestige.PrestigeLevel;
|
||||
newProfile.CharacterData!.PmcData!.Info!.PrestigeLevel = prestige.PrestigeLevel;
|
||||
}
|
||||
|
||||
private void AddPrestigeRewardsToProfile(MongoId sessionId, SptProfile newProfile, IEnumerable<Reward> rewards)
|
||||
@@ -135,7 +142,7 @@ public class PrestigeHelper(
|
||||
case RewardType.Skill:
|
||||
if (Enum.TryParse(reward.Target, out SkillTypes result))
|
||||
{
|
||||
profileHelper.AddSkillPointsToPlayer(newProfile.CharacterData.PmcData, result, reward.Value.GetValueOrDefault(0));
|
||||
profileHelper.AddSkillPointsToPlayer(newProfile.CharacterData!.PmcData!, result, reward.Value.GetValueOrDefault(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -145,12 +152,12 @@ public class PrestigeHelper(
|
||||
break;
|
||||
case RewardType.Item:
|
||||
{
|
||||
itemsToSend.AddRange(reward.Items);
|
||||
itemsToSend.AddRange(reward.Items ?? []);
|
||||
break;
|
||||
}
|
||||
case RewardType.ExtraDailyQuest:
|
||||
{
|
||||
newProfile.AddExtraRepeatableQuest(new MongoId(reward.Target), (double)reward.Value);
|
||||
newProfile.AddExtraRepeatableQuest(new MongoId(reward.Target), (double)reward.Value!);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user