This commit is contained in:
clodan
2025-01-21 15:56:25 +00:00
20 changed files with 746 additions and 235 deletions
+39 -87
View File
@@ -23,9 +23,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse MoveItem(PmcData pmcData, InventoryMoveRequestData info, string sessionID, ItemEventRouterResponse output)
{
_inventoryController.MoveItem(pmcData, info, sessionID, output);
return output;
_inventoryController.MoveItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -38,10 +37,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse RemoveItem(PmcData pmcData, InventoryRemoveRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.RemoveItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.RemoveItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -54,10 +51,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse SplitItem(PmcData pmcData, InventorySplitRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.SplitItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.SplitItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -70,10 +65,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse MergeItem(PmcData pmcData, InventoryMergeRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.MergeItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.MergeItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -86,10 +79,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse TransferItem(PmcData pmcData, InventoryTransferRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.TransferItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.TransferItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -101,10 +92,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse SwapItem(PmcData pmcData, InventorySwapRequestData info, string sessionID)
{
// _inventoryController.SwapItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
return _inventoryController.SwapItem(pmcData, info, sessionID);
}
/// <summary>
@@ -116,10 +104,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse FoldItem(PmcData pmcData, InventoryFoldRequestData info, string sessionID)
{
// _inventoryController.FoldItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
return _inventoryController.FoldItem(pmcData, info, sessionID);
}
/// <summary>
@@ -131,10 +116,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse ToggleItem(PmcData pmcData, InventoryToggleRequestData info, string sessionID)
{
// _inventoryController.ToggleItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
return _inventoryController.ToggleItem(pmcData, info, sessionID);
}
/// <summary>
@@ -146,10 +128,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse TagItem(PmcData pmcData, InventoryTagRequestData info, string sessionID)
{
// _inventoryController.TagItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
return _inventoryController.TagItem(pmcData, info, sessionID);
}
/// <summary>
@@ -162,10 +141,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse BindItem(PmcData pmcData, InventoryBindRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.BindItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.BindItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -178,10 +155,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse UnBindItem(PmcData pmcData, InventoryBindRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.UnBindItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.UnBindItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -194,10 +169,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse ExamineItem(PmcData pmcData, InventoryExamineRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.ExamineItem(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.ExamineItem(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -209,10 +182,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse ReadEncyclopedia(PmcData pmcData, InventoryReadEncyclopediaRequestData info, string sessionID)
{
// _inventoryController.ReadEncyclopedia(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
return _inventoryController.ReadEncyclopedia(pmcData, info, sessionID);
}
/// <summary>
@@ -225,10 +195,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse SortInventory(PmcData pmcData, InventorySortRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.SortInventory(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.SortInventory(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -241,10 +209,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse CreateMapMarker(PmcData pmcData, InventoryCreateMarkerRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.CreateMapMarker(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.CreateMapMarker(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -257,10 +223,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse DeleteMapMarker(PmcData pmcData, InventoryDeleteMarkerRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.DeleteMapMarker(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.DeleteMapMarker(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -273,10 +237,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse EditMapMarker(PmcData pmcData, InventoryEditMarkerRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.EditMapMarker(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.EditMapMarker(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -290,10 +252,8 @@ public class InventoryCallbacks(
public ItemEventRouterResponse OpenRandomLootContainer(PmcData pmcData, OpenRandomLootContainerRequestData info, string sessionID,
ItemEventRouterResponse output)
{
// _inventoryController.OpenRandomLootContainer(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.OpenRandomLootContainer(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -306,10 +266,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse RedeemProfileReward(PmcData pmcData, RedeemProfileRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.RedeemProfileReward(pmcData, info, sessionID);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.RedeemProfileReward(pmcData, info, sessionID);
return output;
}
/// <summary>
@@ -322,10 +280,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse SetFavoriteItem(PmcData pmcData, SetFavoriteItems info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.SetFavoriteItem(pmcData, info, sessionID);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.SetFavoriteItem(pmcData, info, sessionID);
return output;
}
/// <summary>
@@ -339,10 +295,8 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse FailQuest(PmcData pmcData, FailQuestRequestData info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.FailQuest(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_questController.FailQuest(pmcData, info, sessionID, output);
return output;
}
/// <summary>
@@ -355,9 +309,7 @@ public class InventoryCallbacks(
/// <returns></returns>
public ItemEventRouterResponse PinOrLock(PmcData pmcData, PinOrLockItemRequest info, string sessionID, ItemEventRouterResponse output)
{
// _inventoryController.PinOrLock(pmcData, info, sessionID, output);
// TODO: InventoryController is not implemented rn
// return output;
throw new NotImplementedException();
_inventoryController.PinOrLock(pmcData, info, sessionID, output);
return output;
}
}
+1 -1
View File
@@ -258,7 +258,7 @@ public class BotController(
requestedBot?.Role,
raidSettings.Location
);
if (convertIntoPmcChanceMinMax is not null && botGenerationDetails.IsPmc is not null && !botGenerationDetails.IsPmc.Value)
if (convertIntoPmcChanceMinMax is not null && !botGenerationDetails.IsPmc.GetValueOrDefault(false))
{
// Bot has % chance to become pmc and isnt one pmc already
var convertToPmc = _botHelper.RollChanceToBePmc(convertIntoPmcChanceMinMax);
@@ -4,6 +4,7 @@ using Core.Helpers;
using Core.Models.Eft.Common;
using Core.Models.Eft.Inventory;
using Core.Models.Eft.ItemEvent;
using Core.Models.Eft.Quests;
using Core.Models.Enums;
using Core.Models.Utils;
using Core.Routers;
@@ -93,4 +94,104 @@ public class InventoryController(
(BackendErrorCodes)228
);
}
public void PinOrLock(PmcData pmcData, PinOrLockItemRequest info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void SetFavoriteItem(PmcData pmcData, SetFavoriteItems info, string sessionId)
{
throw new NotImplementedException();
}
public void RedeemProfileReward(PmcData pmcData, RedeemProfileRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public void OpenRandomLootContainer(PmcData pmcData, OpenRandomLootContainerRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void EditMapMarker(PmcData pmcData, InventoryEditMarkerRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void DeleteMapMarker(PmcData pmcData, InventoryDeleteMarkerRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void CreateMapMarker(PmcData pmcData, InventoryCreateMarkerRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void SortInventory(PmcData pmcData, InventorySortRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse ReadEncyclopedia(PmcData pmcData, InventoryReadEncyclopediaRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public void ExamineItem(PmcData pmcData, InventoryExamineRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void UnBindItem(PmcData pmcData, InventoryBindRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void BindItem(PmcData pmcData, InventoryBindRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse TagItem(PmcData pmcData, InventoryTagRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse ToggleItem(PmcData pmcData, InventoryToggleRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse FoldItem(PmcData pmcData, InventoryFoldRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse SwapItem(PmcData pmcData, InventorySwapRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public void TransferItem(PmcData pmcData, InventoryTransferRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void MergeItem(PmcData pmcData, InventoryMergeRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void SplitItem(PmcData pmcData, InventorySplitRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
public void RemoveItem(PmcData pmcData, InventoryRemoveRequestData info, string sessionId, ItemEventRouterResponse output)
{
throw new NotImplementedException();
}
}
+378 -20
View File
@@ -1,11 +1,19 @@
using System.Runtime.InteropServices.JavaScript;
using SptCommon.Annotations;
using Core.Helpers;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.ItemEvent;
using Core.Models.Eft.Quests;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Models.Utils;
using Core.Routers;
using Core.Servers;
using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
using Product = Core.Models.Eft.ItemEvent.Product;
namespace Core.Controllers;
@@ -15,32 +23,382 @@ public class QuestController(
ISptLogger<QuestController> _logger,
TimeUtil _timeUtil,
HttpResponseUtil _httpResponseUtil,
EventOutputHolder _eventOutputHolder,
DatabaseService _databaseService,
ItemHelper _itemHelper,
DialogueHelper _dialogueHelper,
MailSendService _mailSendService,
ProfileHelper _profileHelper,
TraderHelper _traderHelper,
QuestHelper _questHelper,
QuestRewardHelper _questRewardHelper
QuestRewardHelper _questRewardHelper,
QuestConditionHelper _questConditionHelper,
PlayerService _playerService,
LocaleService _localeService,
LocalisationService _localisationService,
ConfigServer _configServer,
ICloner _cloner
)
{
public ItemEventRouterResponse CompleteQuest(PmcData pmcData, CompleteQuestRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse AcceptRepeatableQuest(PmcData pmcData, AcceptQuestRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse AcceptQuest(PmcData pmcData, AcceptQuestRequestData info, string sessionId)
{
throw new NotImplementedException();
}
public ItemEventRouterResponse HandoverQuest(PmcData pmcData, HandoverQuestRequestData info, string sessionId)
{
throw new NotImplementedException();
}
protected QuestConfig _questConfig = _configServer.GetConfig<QuestConfig>();
protected List<string> _questTypes = ["PickUp", "Exploration", "Elimination"];
public List<Quest> GetClientQuest(string sessionId)
{
return _questHelper.GetClientQuests(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);
if (existingQuestStatus is not null)
{
// Update existing
_questHelper.ResetQuestState(pmcData, QuestStatusEnum.Started, acceptedQuest.QuestId);
// Need to send client an empty list of completedConditions (Unsure if this does anything)
acceptQuestResponse.ProfileChanges[sessionID].QuestsStatus.Add(existingQuestStatus);
}
else
{
// Add new quest to server profile
var newQuest = _questHelper.GetQuestReadyForProfile(pmcData, QuestStatusEnum.Started, acceptedQuest);
pmcData.Quests.Add(newQuest);
}
// Create a dialog message for starting the quest.
// Note that for starting quests, the correct locale field is "description", not "startedMessageText".
var questFromDb = _questHelper.GetQuestFromDb(acceptedQuest.QuestId, pmcData);
AddTaskConditionCountersToProfile(questFromDb.Conditions.AvailableForFinish, pmcData, acceptedQuest.QuestId);
// Get messageId of text to send to player as text message in game
var messageId = _questHelper.GetMessageIdForQuestStart(
questFromDb.StartedMessageText,
questFromDb.Description
);
// Apply non-item rewards to profile + return item rewards
var startedQuestRewardItems = _questRewardHelper.ApplyQuestReward(
pmcData,
acceptedQuest.QuestId,
QuestStatusEnum.Started,
sessionID,
acceptQuestResponse
);
// Send started text + any starting reward items found above to player
_mailSendService.SendLocalisedNpcMessageToPlayer(
sessionID,
_traderHelper.GetTraderById(questFromDb.TraderId).ToString(),
MessageType.QUEST_START,
messageId,
startedQuestRewardItems.ToList(),
_timeUtil.GetHoursAsSeconds((int)_questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData))
);
// Having accepted new quest, look for newly unlocked quests and inform client of them
var newlyAccessibleQuests = _questHelper.GetNewlyAccessibleQuestsWhenStartingQuest(
acceptedQuest.QuestId,
sessionID
);
if (newlyAccessibleQuests.Count > 0)
{
acceptQuestResponse.ProfileChanges[sessionID].Quests.AddRange(newlyAccessibleQuests);
}
return acceptQuestResponse;
}
private void AddTaskConditionCountersToProfile(List<QuestCondition>? questConditions, PmcData pmcData, string questId)
{
foreach (var condition in questConditions)
{
if (pmcData.TaskConditionCounters.TryGetValue(condition.Id, out var counter))
{
_logger.Error(
$"Unable to add new task condition counter: {condition.ConditionType} for qeust: {questId} to profile: {pmcData.SessionId} as it already exists:"
);
}
switch (condition.ConditionType)
{
case "SellItemToTrader":
pmcData.TaskConditionCounters[condition.Id] = new TaskConditionCounter
{
Id = condition.Id,
SourceId = questId,
Type = condition.ConditionType,
Value = 0,
};
break;
}
}
}
public ItemEventRouterResponse AcceptRepeatableQuest(PmcData pmcData, AcceptQuestRequestData acceptedQuest, string sessionID)
{
// Create and store quest status object inside player profile
var newRepeatableQuest = _questHelper.GetQuestReadyForProfile(
pmcData,
QuestStatusEnum.Started,
acceptedQuest
);
pmcData.Quests.Add(newRepeatableQuest);
// Look for the generated quest cache in profile.RepeatableQuests
var repeatableQuestProfile = GetRepeatableQuestFromProfile(pmcData, acceptedQuest);
if (repeatableQuestProfile is null)
{
_logger.Error(
_localisationService.GetText(
"repeatable-accepted_repeatable_quest_not_found_in_active_quests",
acceptedQuest.QuestId
)
);
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()))
{
var fullProfile = _profileHelper.GetFullProfile(sessionID);
if (fullProfile.CharacterData.ScavData.Quests is null)
{
fullProfile.CharacterData.ScavData.Quests = [];
}
fullProfile.CharacterData.ScavData.Quests.Add(newRepeatableQuest);
}
var response = _eventOutputHolder.GetOutput(sessionID);
return response;
}
private RepeatableQuest GetRepeatableQuestFromProfile(PmcData pmcData, AcceptQuestRequestData acceptedQuest)
{
foreach (var repeatableQuest in pmcData.RepeatableQuests)
{
var matchingQuest = repeatableQuest.ActiveQuests.FirstOrDefault(x => x.Id == acceptedQuest.QuestId);
if (matchingQuest is not null)
{
_logger.Debug($"Accepted repeatable quest {acceptedQuest.QuestId} from {repeatableQuest.Name}");
matchingQuest.SptRepatableGroupName = repeatableQuest.Name;
return matchingQuest;
}
}
return null;
}
public ItemEventRouterResponse CompleteQuest(PmcData pmcData, CompleteQuestRequestData info, string sessionId)
{
return _questHelper.CompleteQuest(pmcData, info, sessionId);
}
public ItemEventRouterResponse HandoverQuest(PmcData pmcData, HandoverQuestRequestData handoverQuestRequest, string sessionID)
{
var quest = _questHelper.GetQuestFromDb(handoverQuestRequest.QuestId, pmcData);
List<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
var output = _eventOutputHolder.GetOutput(sessionID);
var isItemHandoverQuest = true;
var handedInCount = 0;
// Decrement number of items handed in
QuestCondition? handoverRequirements = null;
foreach (var condition in quest.Conditions.AvailableForFinish)
{
if (condition.Id == handoverQuestRequest.ConditionId && handoverQuestTypes.Contains(condition.ConditionType))
{
handedInCount = int.Parse((string)condition.Value);
isItemHandoverQuest = condition.ConditionType == handoverQuestTypes.FirstOrDefault();
handoverRequirements = condition;
if (pmcData.TaskConditionCounters.TryGetValue("ConditionId", out var counter))
{
handedInCount -= (int)(counter.Value ?? 0);
if (handedInCount <= 0)
{
_logger.Error(
_localisationService.GetText(
"repeatable-quest_handover_failed_condition_already_satisfied",
new
{
questId = handoverQuestRequest.QuestId,
conditionId = handoverQuestRequest.ConditionId,
profileCounter = counter.Value,
value = handedInCount
}
)
);
return output;
}
break;
}
}
}
if (isItemHandoverQuest && handedInCount == 0)
{
return ShowRepeatableQuestInvalidConditionError(handoverQuestRequest, output);
}
var totalItemCountToRemove = 0;
foreach (var itemHandover in handoverQuestRequest.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 doesnt match what was requested
return ShowQuestItemHandoverMatchError(
handoverQuestRequest,
matchingItemInProfile,
handoverRequirements,
output
);
}
// Remove the right quantity of given items
var itemCountToRemove = Math.Min(itemHandover.Count ?? 0, handedInCount - totalItemCountToRemove);
totalItemCountToRemove += itemCountToRemove;
if (itemHandover.Count - itemCountToRemove > 0)
{
// Remove single item with no children
_questHelper.ChangeItemStack(
pmcData,
itemHandover.Id,
itemHandover.Count - itemCountToRemove ?? 0,
sessionID,
output
);
if (totalItemCountToRemove == handedInCount)
{
break;
}
}
else
{
// Remove item with children
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 Product
{
Id = itemHandover.Id
}
);
// Important: loop backward when removing items from the array we're looping on
while (index-- > 0)
{
if (toRemove.Contains(pmcData.Inventory.Items[index].Id))
{
var removedItem = _cloner.Clone(pmcData.Inventory.Items[index]);
pmcData.Inventory.Items.RemoveAt(index);
// Remove the item
// If the removed item has a numeric `location` property, re-calculate all the child
// element `location` properties of the parent so they are sequential, while retaining order
if (removedItem.Location.GetType() == typeof(int))
{
var childItems = _itemHelper.FindAndReturnChildrenAsItems(
pmcData.Inventory.Items,
removedItem.ParentId
);
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));
for (int i = 0; i < childItems.Count; i++)
{
childItems[i].Location = i;
}
}
}
}
}
}
UpdateProfileTaskConditionCounterValue(
pmcData,
handoverQuestRequest.ConditionId,
handoverQuestRequest.QuestId,
totalItemCountToRemove
);
return output;
}
private ItemEventRouterResponse ShowRepeatableQuestInvalidConditionError(HandoverQuestRequestData handoverQuestRequest, ItemEventRouterResponse output)
{
var errorMessage = _localisationService.GetText(
"repeatable-quest_handover_failed_condition_invalid",
new
{
questId = handoverQuestRequest.QuestId,
conditionId = handoverQuestRequest.ConditionId
}
);
_logger.Error(errorMessage);
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage);
}
private ItemEventRouterResponse ShowQuestItemHandoverMatchError(HandoverQuestRequestData handoverQuestRequest, Item? itemHandedOver,
QuestCondition? handoverRequirements, ItemEventRouterResponse output)
{
var errorMessage = _localisationService.GetText(
"quest-handover_wrong_item",
new
{
questId = handoverQuestRequest.QuestId,
handedInTpl = itemHandedOver?.Template ?? "UNKNOWN",
requiredTpl = handoverRequirements.Target.List.FirstOrDefault(),
}
);
_logger.Error(errorMessage);
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage);
}
private void UpdateProfileTaskConditionCounterValue(PmcData pmcData, string conditionId, string questId, int counterValue)
{
if (pmcData.TaskConditionCounters[conditionId] != null)
{
pmcData.TaskConditionCounters[conditionId].Value += counterValue;
return;
}
pmcData.TaskConditionCounters[conditionId] = new TaskConditionCounter
{
Id = conditionId,
SourceId = questId,
Type = "HandoverItem",
Value = counterValue,
};
}
public ItemEventRouterResponse FailQuest(PmcData pmcData, FailQuestRequestData request, string sessionID, ItemEventRouterResponse output)
{
_questHelper.FailQuest(pmcData, request, sessionID, output);
return output;
}
}
@@ -244,11 +244,11 @@ public class BotEquipmentModGenerator(
* @param modSlot front/back
* @returns Armor IItem
*/
protected Item GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot)
protected Item? GetDefaultPresetArmorSlot(string armorItemTpl, string modSlot)
{
var defaultPreset = _presetHelper.GetDefaultPreset(armorItemTpl);
return defaultPreset?.Items.FirstOrDefault((item) => item.SlotId?.ToLower() == modSlot);
return defaultPreset?.Items?.FirstOrDefault((item) => item.SlotId?.ToLower() == modSlot);
}
@@ -260,11 +260,6 @@ public class BotEquipmentModGenerator(
/// <returns>Weapon + mods array</returns>
public List<Item> GenerateModsForWeapon(string sessionId, GenerateWeaponRequest request)
{
var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
// Get pool of mods that fit weapon
var compatibleModsPool = request.ModPool[request.ParentTemplate.Id];
if (
!(
request.ParentTemplate.Properties.Slots.Any() ||
@@ -288,7 +283,12 @@ public class BotEquipmentModGenerator(
return request.Weapon;
}
var botEquipConfig = _botConfig.Equipment[request.BotData.EquipmentRole];
var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
// Get pool of mods that fit weapon
request.ModPool.TryGetValue(request.ParentTemplate.Id, out var compatibleModsPool);
_botConfig.Equipment.TryGetValue(request.BotData.EquipmentRole, out var botEquipConfig);
var botEquipBlacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
request.BotData.EquipmentRole,
pmcProfile.Info.Level ?? 0
@@ -494,13 +494,26 @@ public class BotEquipmentModGenerator(
if (isRandomisableSlot && !containsModInPool && modToAddTemplate.Value.Properties.Slots.Any())
{
var modFromService = _botEquipmentModPoolService.GetModsForWeaponSlot(modToAddTemplate.Value.Id);
if (modFromService.Keys.Any())
if (modFromService?.Keys.Count > 0)
{
request.ModPool[modToAddTemplate.Value.Id] = modFromService;
containsModInPool = true;
}
}
// Fallback when mods with REQUIRED children are not in the pool, add them and process
if (!containsModInPool && !isRandomisableSlot)
{
// Check for required mods the item we've added needs to be classified as 'valid'
var modFromService = _botEquipmentModPoolService.GetRequiredModsForWeaponSlot(modToAddTemplate.Value.Id);
if (modFromService?.Keys.Count > 0)
{
request.ModPool[modToAddTemplate.Value.Id] = modFromService;
containsModInPool = true;
}
}
if (containsModInPool)
{
GenerateWeaponRequest recursiveRequestData = new()
@@ -871,16 +884,16 @@ public class BotEquipmentModGenerator(
request.Weapon,
request.ModSlot
);
if (chosenModResult.SlotBlocked ?? false && !(parentSlot.Required ?? false))
if (chosenModResult.SlotBlocked.GetValueOrDefault(false) && !parentSlot.Required.GetValueOrDefault(false))
{
// Don't bother trying to fit mod, slot is completely blocked
return null;
}
// Log if mod chosen was incompatible
if (chosenModResult.Incompatible ?? false && !(parentSlot.Required ?? false))
if (chosenModResult.Incompatible.GetValueOrDefault(false) && !(parentSlot.Required.GetValueOrDefault(false)))
{
_logger.Debug(chosenModResult.Reason);
_logger.Debug($"Unable to find compatible mod of type: {parentSlot.Name}, in slot: {request.ModSlot} reason: {chosenModResult.Reason}");
}
// Get random mod to attach from items db for required slots if none found above
@@ -891,14 +904,14 @@ public class BotEquipmentModGenerator(
}
// Compatible item not found + not required
if (!(chosenModResult.Found ?? false) && parentSlot != null && (!parentSlot.Required ?? false))
if (!(chosenModResult.Found.GetValueOrDefault(false)) && parentSlot is not null && (!parentSlot.Required.GetValueOrDefault(false)))
{
return null;
}
if (!(chosenModResult.Found ?? false) && parentSlot != null)
if (!(chosenModResult.Found ?? false) && parentSlot is not null)
{
if (parentSlot.Required ?? false)
if (parentSlot.Required.GetValueOrDefault(false))
{
_logger.Warning(
$"Required slot unable to be filled, {request.ModSlot} on {request.ParentTemplate.Name} {request.ParentTemplate.Id} for weapon: {request.Weapon[0].Template}"
@@ -966,7 +979,7 @@ public class BotEquipmentModGenerator(
// Filter mod pool to only items that appear in parents allowed list
preFilteredModPool = preFilteredModPool.Where((tpl) => parentSlot.Props.Filters[0].Filter.Contains(tpl)).ToList();
if (preFilteredModPool.Count() == 0)
if (preFilteredModPool.Count == 0)
{
return new() { Incompatible = true, Found = false, Reason = "No mods found in parents allowed list" };
}
@@ -995,9 +1008,9 @@ public class BotEquipmentModGenerator(
};
// Limit how many attempts to find a compatible mod can occur before giving up
var maxBlockedAttempts = Math.Round(modPool.Count() * 0.75); // 75% of pool size
var maxBlockedAttempts = Math.Round(modPool.Count * 0.75); // 75% of pool size
var blockedAttemptCount = 0;
string chosenTpl = null;
string chosenTpl;
while (exhaustableModPool.HasValues())
{
chosenTpl = exhaustableModPool.GetRandomValue();
@@ -1015,7 +1028,7 @@ public class BotEquipmentModGenerator(
}
// Success - Default wanted + only 1 item in pool
if (modSpawnType == ModSpawn.DEFAULT_MOD && modPool.Count() == 1)
if (modSpawnType == ModSpawn.DEFAULT_MOD && modPool.Count == 1)
{
chosenModResult.Found = true;
chosenModResult.Incompatible = false;
@@ -1032,15 +1045,20 @@ public class BotEquipmentModGenerator(
if (existingItemBlockingChoice is not null)
{
// Give max of x attempts of picking a mod if blocked by another
if (blockedAttemptCount > maxBlockedAttempts)
// OR Blocked and modpool only had 1 item
if (blockedAttemptCount > maxBlockedAttempts || modPool.Count == 1)
{
blockedAttemptCount = 0; // reset
//chosenModResult.SlotBlocked = true; // Later in code we try to find replacement, but only when "slotBlocked" is not true
chosenModResult.Reason = "Blocked";
break;
}
blockedAttemptCount++;
// Not compatible - Try again
;
continue;
}
@@ -1073,7 +1091,7 @@ public class BotEquipmentModGenerator(
/// <param name="modPool"></param>
/// <param name="tplBlacklist">Tpls that are incompatible and should not be used</param>
/// <returns>string array of compatible mod tpls with weapon</returns>
public List<string> GetFilteredModPool(HashSet<string> modPool, List<string> tplBlacklist)
public List<string> GetFilteredModPool(HashSet<string> modPool, HashSet<string> tplBlacklist)
{
return modPool.Where((tpl) => !tplBlacklist.Contains(tpl)).ToList();
}
@@ -470,7 +470,7 @@ public class BotInventoryGenerator(
// Edge case: Filter the armor items mod pool if bot exists in config dict + config has armor slot
if (_botConfig.Equipment.ContainsKey(settings.BotData.EquipmentRole) &&
settings.RandomisationDetails is not null &&
settings.RandomisationDetails?.RandomisedArmorSlots != null &&
settings.RandomisationDetails.RandomisedArmorSlots.Contains(settings.RootEquipmentSlot.ToString()))
{
// Filter out mods from relevant blacklist
@@ -176,7 +176,7 @@ public class BotWeaponGenerator(
);
}
// Use weapon preset from globals.json if weapon isnt valid
// Use weapon preset from globals.json if weapon isn't valid
if (!IsWeaponValid(weaponWithModsArray, botRole))
{
// Weapon is bad, fall back to weapons preset
@@ -95,6 +95,12 @@ public class ExternalInventoryMagGen(
break;
}
if (defaultMagazineTpl == BaseClasses.MAGAZINE)
{
// Magazine base type, do not use
break;
}
// Set chosen magazine tpl to the weapons default magazine tpl and try to fit into inventory next loop
magazineTpl = defaultMagazineTpl;
magTemplate = _itemHelper.GetItem(magazineTpl).Value;
+7 -2
View File
@@ -29,7 +29,7 @@ public class BotHelper(
/// <returns>BotType object</returns>
public BotType GetBotTemplate(string role)
{
if (!_databaseService.GetBots().Types.TryGetValue(role.ToLower(), out var bot))
if (!_databaseService.GetBots().Types.TryGetValue(role?.ToLower(), out var bot))
{
_logger.Error($"Unable to get bot of type: {role} from DB");
@@ -51,7 +51,7 @@ public class BotHelper(
public bool IsBotBoss(string botRole)
{
return _botConfig.Bosses.Any(x => x.ToLower() == botRole.ToLower());
return _botConfig.Bosses.Any(x => string.Equals(x, botRole, StringComparison.CurrentCultureIgnoreCase));
}
public bool IsBotFollower(string botRole)
@@ -59,6 +59,11 @@ public class BotHelper(
return botRole?.ToLower().StartsWith("follower") ?? false;
}
public bool IsBotZombie(string botRole)
{
return botRole?.ToLower().StartsWith("infected") ?? false;
}
/// <summary>
/// Add a bot to the FRIENDLY_BOT_TYPES list
/// </summary>
@@ -102,6 +102,11 @@ public class DurabilityLimitsHelper(
return "follower";
}
if (_botHelper.IsBotZombie(botRole))
{
return "zombie";
}
var roleExistsInConfig = _botConfig.Durability.BotDurabilities.ContainsKey(botRole);
if (!roleExistsInConfig)
{
@@ -122,26 +127,9 @@ public class DurabilityLimitsHelper(
/// <returns>Current armor durability</returns>
public double GetRandomizedArmorDurability(TemplateItem? itemTemplate, string? botRole, double maxDurability)
{
if (botRole is not null)
{
if (_botHelper.IsBotPmc(botRole))
{
return GenerateArmorDurability("pmc", maxDurability);
}
var durabilityRole = GetDurabilityRole(botRole);
if (_botHelper.IsBotBoss(botRole))
{
return GenerateArmorDurability("boss", maxDurability);
}
if (_botHelper.IsBotFollower(botRole))
{
return GenerateArmorDurability("follower", maxDurability);
}
}
return GenerateArmorDurability(botRole, maxDurability);
return GenerateArmorDurability(durabilityRole, maxDurability);
}
protected double GenerateMaxWeaponDurability(string? botRole = null)
+9 -10
View File
@@ -277,17 +277,16 @@ public class InventoryHelper(
protected List<int> GetSizeByInventoryItemHash(string itemTpl, string itemID, InventoryItemHash inventoryItemHash)
{
var toDo = new List<string> { itemID };
var result = _itemHelper.GetItem(itemTpl);
var tmpItem = result.Value;
var (key, tmpItem) = _itemHelper.GetItem(itemTpl);
// Invalid item
if (!result.Key)
if (!key)
{
_logger.Error(_localisationService.GetText("inventory-invalid_item_missing_from_db", itemTpl));
}
// Item found but no _props property
if (tmpItem is not null && tmpItem.Properties is null)
if (key && tmpItem.Properties is null)
{
_localisationService.GetText("inventory-item_missing_props_property", new {
itemTpl = itemTpl,
@@ -296,7 +295,7 @@ public class InventoryHelper(
}
// No item object or getItem() returned false
if (tmpItem is null && result.Value is null)
if (!key && tmpItem is null)
{
// return default size of 1x1
_logger.Error(_localisationService.GetText("inventory-return_default_size", itemTpl));
@@ -305,7 +304,7 @@ public class InventoryHelper(
}
var rootItem = inventoryItemHash.ByItemId[itemID];
var foldableWeapon = tmpItem.Properties.Foldable;
var isFoldable = tmpItem.Properties.Foldable;
var foldedSlot = tmpItem.Properties.FoldedSlot;
var sizeUp = 0;
@@ -323,10 +322,10 @@ public class InventoryHelper(
// Item types to ignore
var skipThisItems = new List<string> { BaseClasses.BACKPACK, BaseClasses.SEARCHABLE_ITEM, BaseClasses.SIMPLE_CONTAINER };
var rootFolded = rootItem?.Upd?.Foldable?.Folded == true;
var rootIsFolded = rootItem?.Upd?.Foldable?.Folded == true;
// The item itself is collapsible
if (foldableWeapon is not null && string.IsNullOrEmpty(foldedSlot) && rootFolded)
if (isFoldable is not null && string.IsNullOrEmpty(foldedSlot) && rootIsFolded)
{
outX -= tmpItem.Properties.SizeReduceRight.Value;
}
@@ -358,12 +357,12 @@ public class InventoryHelper(
var childFoldable = itm.Properties.Foldable.GetValueOrDefault(false);
var childFolded = item.Upd?.Foldable is not null && item.Upd.Foldable.Folded == true;
if (foldableWeapon is true && foldedSlot == item.SlotId && (rootFolded || childFolded))
if (isFoldable is true && foldedSlot == item.SlotId && (rootIsFolded || childFolded))
{
continue;
}
if (childFoldable && rootFolded && childFolded)
if (childFoldable && rootIsFolded && childFolded)
{
continue;
}
+1 -1
View File
@@ -204,7 +204,7 @@ public class QuestHelper(
*/
public QuestStatus GetQuestReadyForProfile(
PmcData pmcData,
QuestStatus newState,
QuestStatusEnum newState,
AcceptQuestRequestData acceptedQuest
)
{
@@ -47,8 +47,8 @@ public record Quest
[JsonPropertyName("image")]
public string? Image { get; set; }
[JsonPropertyName("type")]
public string? RewardType { get; set; }
[JsonPropertyName("type")] // can be string or QuestTypeEnum
public string? Type { get; set; }
[JsonPropertyName("isKey")]
public bool? IsKey { get; set; }
@@ -43,7 +43,7 @@ public record GenerateWeaponRequest
/** Array of item tpls the weapon does not support */
[JsonPropertyName("conflictingItemTpls")]
public List<string>? ConflictingItemTpls { get; set; }
public HashSet<string>? ConflictingItemTpls { get; set; }
}
public record BotData
@@ -74,7 +74,7 @@ public record ModToSpawnRequest
/// List of item tpls the weapon does not support
/// </summary>
[JsonPropertyName("conflictingItemTpls")]
public List<string>? ConflictingItemTpls { get; set; }
public HashSet<string>? ConflictingItemTpls { get; set; }
[JsonPropertyName("botData")]
public BotData? BotData { get; set; }
@@ -185,11 +185,11 @@ public class SptHttpListener : IHttpListener
public void SendJson(HttpResponse resp, string? output, string sessionID)
{
if (!string.IsNullOrEmpty(output))
resp.Body = new MemoryStream(Encoding.UTF8.GetBytes(output));
resp.StatusCode = 200;
resp.ContentType = "application/json";
resp.Headers.Append("Set-Cookie", $"PHPSESSID={sessionID}");
if (!string.IsNullOrEmpty(output))
resp.Body.WriteAsync(Encoding.UTF8.GetBytes(output)).AsTask().Wait();
resp.StartAsync().Wait();
resp.CompleteAsync().Wait();
}
@@ -54,7 +54,7 @@ public class BotEquipmentFilterService
pmcProfile.Info.Level ?? 0
);
var botEquipConfig = _botEquipmentConfig[botRole];
var botEquipConfig = _botEquipmentConfig[botRole.ToLower()];
var randomisationDetails = _botHelper.GetBotRandomizationDetails(botLevel, botEquipConfig);
if (botEquipmentBlacklist is not null || botEquipmentWhitelist is not null)
@@ -170,6 +170,31 @@ public class BotEquipmentModPoolService
return _weaponModPool[itemTpl];
}
public Dictionary<string, HashSet<string>>? GetRequiredModsForWeaponSlot(string itemTpl)
{
var result = new Dictionary<string, HashSet<string>>();
// Get item from db
var itemDb = _itemHelper.GetItem(itemTpl).Value;
if (itemDb.Properties.Slots is not null)
{
// Loop over slots flagged as 'required'
foreach (var slot in itemDb.Properties.Slots.Where(slot => slot.Required.GetValueOrDefault(false)))
{
// Create dict entry for mod slot
result.Add(slot.Name, []);
// Add compatible tpls to dicts hashset
foreach (var compatibleItemTpl in slot.Props.Filters.FirstOrDefault().Filter)
{
result[slot.Name].Add(compatibleItemTpl);
}
}
}
return result;
}
/**
* Create weapon mod pool and set generated flag to true
*/
@@ -22,141 +22,141 @@ public class BaseInteractionRequestDataConverter : JsonConverter<BaseInteraction
{
using var jsonDocument = JsonDocument.ParseValue(ref reader);
var jsonText = jsonDocument.RootElement.GetRawText();
var value = JsonSerializer.Deserialize<BaseInteractionRequestData>(jsonText, options);
return ConvertToCorrectType(value, jsonText, options);
var value = JsonSerializer.Deserialize<BaseInteractionRequestData>(jsonText);
return ConvertToCorrectType(value, jsonText);
}
private BaseInteractionRequestData? ConvertToCorrectType(BaseInteractionRequestData? value, string jsonText, JsonSerializerOptions options)
private BaseInteractionRequestData? ConvertToCorrectType(BaseInteractionRequestData? value, string jsonText)
{
switch (value.Action)
{
case "CustomizationBuy":
return JsonSerializer.Deserialize<BuyClothingRequestData>(jsonText, options);
return JsonSerializer.Deserialize<BuyClothingRequestData>(jsonText);
case "CustomizationSet":
return JsonSerializer.Deserialize<CustomizationSetRequest>(jsonText, options);
return JsonSerializer.Deserialize<CustomizationSetRequest>(jsonText);
case "Eat":
return JsonSerializer.Deserialize<OffraidEatRequestData>(jsonText, options);
return JsonSerializer.Deserialize<OffraidEatRequestData>(jsonText);
case "Heal":
return JsonSerializer.Deserialize<OffraidHealRequestData>(jsonText, options);
return JsonSerializer.Deserialize<OffraidHealRequestData>(jsonText);
case "RestoreHealth":
return JsonSerializer.Deserialize<HealthTreatmentRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HealthTreatmentRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_UPGRADE:
return JsonSerializer.Deserialize<HideoutUpgradeRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutUpgradeRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_UPGRADE_COMPLETE:
return JsonSerializer.Deserialize<HideoutUpgradeCompleteRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutUpgradeCompleteRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_PUT_ITEMS_IN_AREA_SLOTS:
return JsonSerializer.Deserialize<HideoutPutItemInRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutPutItemInRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_TAKE_ITEMS_FROM_AREA_SLOTS:
return JsonSerializer.Deserialize<HideoutTakeItemOutRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutTakeItemOutRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_TOGGLE_AREA:
return JsonSerializer.Deserialize<HideoutToggleAreaRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutToggleAreaRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_SINGLE_PRODUCTION_START:
return JsonSerializer.Deserialize<HideoutSingleProductionStartRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutSingleProductionStartRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_SCAV_CASE_PRODUCTION_START:
return JsonSerializer.Deserialize<HideoutScavCaseStartRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutScavCaseStartRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_CONTINUOUS_PRODUCTION_START:
return JsonSerializer.Deserialize<HideoutContinuousProductionStartRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutContinuousProductionStartRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_TAKE_PRODUCTION:
return JsonSerializer.Deserialize<HideoutTakeProductionRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutTakeProductionRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_RECORD_SHOOTING_RANGE_POINTS:
return JsonSerializer.Deserialize<RecordShootingRangePoints>(jsonText, options);
return JsonSerializer.Deserialize<RecordShootingRangePoints>(jsonText);
case HideoutEventActions.HIDEOUT_IMPROVE_AREA:
return JsonSerializer.Deserialize<HideoutImproveAreaRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutImproveAreaRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_CANCEL_PRODUCTION_COMMAND:
return JsonSerializer.Deserialize<HideoutImproveAreaRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutImproveAreaRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_CIRCLE_OF_CULTIST_PRODUCTION_START:
return JsonSerializer.Deserialize<HideoutCircleOfCultistProductionStartRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutCircleOfCultistProductionStartRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_DELETE_PRODUCTION_COMMAND:
return JsonSerializer.Deserialize<HideoutDeleteProductionRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutDeleteProductionRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_CUSTOMIZATION_APPLY_COMMAND:
return JsonSerializer.Deserialize<HideoutCustomizationApplyRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HideoutCustomizationApplyRequestData>(jsonText);
case HideoutEventActions.HIDEOUT_CUSTOMIZATION_SET_MANNEQUIN_POSE:
return JsonSerializer.Deserialize<HideoutCustomizationSetMannequinPoseRequest>(jsonText, options);
return JsonSerializer.Deserialize<HideoutCustomizationSetMannequinPoseRequest>(jsonText);
case "Insure":
return JsonSerializer.Deserialize<InsureRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InsureRequestData>(jsonText);
/////////////////////////////////////////// InventoryBaseActionRequestData
case "AddToWishList":
return JsonSerializer.Deserialize<AddToWishlistRequest>(jsonText, options);
return JsonSerializer.Deserialize<AddToWishlistRequest>(jsonText);
case "RemoveFromWishList":
return JsonSerializer.Deserialize<RemoveFromWishlistRequest>(jsonText, options);
return JsonSerializer.Deserialize<RemoveFromWishlistRequest>(jsonText);
case "ChangeWishlistItemCategory":
return JsonSerializer.Deserialize<ChangeWishlistItemCategoryRequest>(jsonText, options);
return JsonSerializer.Deserialize<ChangeWishlistItemCategoryRequest>(jsonText);
case "TradingConfirm":
return JsonSerializer.Deserialize<ProcessBaseTradeRequestData>(jsonText, options);
return JsonSerializer.Deserialize<ProcessBaseTradeRequestData>(jsonText);
case "RagFairBuyOffer":
return JsonSerializer.Deserialize<ProcessRagfairTradeRequestData>(jsonText, options);
return JsonSerializer.Deserialize<ProcessRagfairTradeRequestData>(jsonText);
case "SellAllFromSavage":
return JsonSerializer.Deserialize<SellScavItemsToFenceRequestData>(jsonText, options);
return JsonSerializer.Deserialize<SellScavItemsToFenceRequestData>(jsonText);
case "Repair":
return JsonSerializer.Deserialize<RepairActionDataRequest>(jsonText, options);
return JsonSerializer.Deserialize<RepairActionDataRequest>(jsonText);
case "TraderRepair":
return JsonSerializer.Deserialize<TraderRepairActionDataRequest>(jsonText, options);
return JsonSerializer.Deserialize<TraderRepairActionDataRequest>(jsonText);
case "RagFairAddOffer":
return JsonSerializer.Deserialize<AddOfferRequestData>(jsonText, options);
return JsonSerializer.Deserialize<AddOfferRequestData>(jsonText);
case "RagFairRemoveOffer":
return JsonSerializer.Deserialize<RemoveOfferRequestData>(jsonText, options);
return JsonSerializer.Deserialize<RemoveOfferRequestData>(jsonText);
case "RagFairRenewOffer":
return JsonSerializer.Deserialize<ExtendOfferRequestData>(jsonText, options);
return JsonSerializer.Deserialize<ExtendOfferRequestData>(jsonText);
case "QuestAccept":
return JsonSerializer.Deserialize<AcceptQuestRequestData>(jsonText, options);
return JsonSerializer.Deserialize<AcceptQuestRequestData>(jsonText);
case "QuestComplete":
return JsonSerializer.Deserialize<CompleteQuestRequestData>(jsonText, options);
return JsonSerializer.Deserialize<CompleteQuestRequestData>(jsonText);
case "QuestHandover":
return JsonSerializer.Deserialize<HandoverQuestRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HandoverQuestRequestData>(jsonText);
case "RepeatableQuestChange":
return JsonSerializer.Deserialize<RepeatableQuestChangeRequest>(jsonText, options);
return JsonSerializer.Deserialize<RepeatableQuestChangeRequest>(jsonText);
case "AddNote":
case "EditNote":
case "DeleteNote":
return JsonSerializer.Deserialize<NoteActionData>(jsonText, options);
return JsonSerializer.Deserialize<NoteActionData>(jsonText);
case ItemEventActions.MOVE:
return JsonSerializer.Deserialize<InventoryMoveRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryMoveRequestData>(jsonText);
case ItemEventActions.REMOVE:
return JsonSerializer.Deserialize<InventoryRemoveRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryRemoveRequestData>(jsonText);
case ItemEventActions.SPLIT:
return JsonSerializer.Deserialize<InventorySplitRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventorySplitRequestData>(jsonText);
case ItemEventActions.MERGE:
return JsonSerializer.Deserialize<InventoryMergeRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryMergeRequestData>(jsonText);
case ItemEventActions.TRANSFER:
return JsonSerializer.Deserialize<InventoryTransferRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryTransferRequestData>(jsonText);
case ItemEventActions.SWAP:
return JsonSerializer.Deserialize<InventorySwapRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventorySwapRequestData>(jsonText);
case ItemEventActions.FOLD:
return JsonSerializer.Deserialize<InventoryFoldRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryFoldRequestData>(jsonText);
case ItemEventActions.TOGGLE:
return JsonSerializer.Deserialize<InventoryToggleRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryToggleRequestData>(jsonText);
case ItemEventActions.TAG:
return JsonSerializer.Deserialize<InventoryTagRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryTagRequestData>(jsonText);
case ItemEventActions.BIND:
return JsonSerializer.Deserialize<InventoryBindRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryBindRequestData>(jsonText);
case ItemEventActions.UNBIND:
return JsonSerializer.Deserialize<InventoryBindRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryBindRequestData>(jsonText);
case ItemEventActions.EXAMINE:
return JsonSerializer.Deserialize<InventoryExamineRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryExamineRequestData>(jsonText);
case ItemEventActions.READ_ENCYCLOPEDIA:
return JsonSerializer.Deserialize<InventoryReadEncyclopediaRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryReadEncyclopediaRequestData>(jsonText);
case ItemEventActions.APPLY_INVENTORY_CHANGES:
return JsonSerializer.Deserialize<InventorySortRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventorySortRequestData>(jsonText);
case ItemEventActions.CREATE_MAP_MARKER:
return JsonSerializer.Deserialize<InventoryCreateMarkerRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryCreateMarkerRequestData>(jsonText);
case ItemEventActions.DELETE_MAP_MARKER:
return JsonSerializer.Deserialize<InventoryDeleteMarkerRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryDeleteMarkerRequestData>(jsonText);
case ItemEventActions.EDIT_MAP_MARKER:
return JsonSerializer.Deserialize<InventoryEditMarkerRequestData>(jsonText, options);
return JsonSerializer.Deserialize<InventoryEditMarkerRequestData>(jsonText);
case ItemEventActions.OPEN_RANDOM_LOOT_CONTAINER:
return JsonSerializer.Deserialize<OpenRandomLootContainerRequestData>(jsonText, options);
return JsonSerializer.Deserialize<OpenRandomLootContainerRequestData>(jsonText);
case ItemEventActions.HIDEOUT_QTE_EVENT:
return JsonSerializer.Deserialize<HandleQTEEventRequestData>(jsonText, options);
return JsonSerializer.Deserialize<HandleQTEEventRequestData>(jsonText);
case ItemEventActions.REDEEM_PROFILE_REWARD:
return JsonSerializer.Deserialize<RedeemProfileRequestData>(jsonText, options);
return JsonSerializer.Deserialize<RedeemProfileRequestData>(jsonText);
case ItemEventActions.SET_FAVORITE_ITEMS:
return JsonSerializer.Deserialize<SetFavoriteItems>(jsonText, options);
return JsonSerializer.Deserialize<SetFavoriteItems>(jsonText);
case ItemEventActions.QUEST_FAIL:
return JsonSerializer.Deserialize<FailQuestRequestData>(jsonText, options);
return JsonSerializer.Deserialize<FailQuestRequestData>(jsonText);
case ItemEventActions.PIN_LOCK:
return JsonSerializer.Deserialize<PinOrLockItemRequest>(jsonText, options);
return JsonSerializer.Deserialize<PinOrLockItemRequest>(jsonText);
default:
throw new Exception($"Unhandled action type {value.Action}, make sure the BaseInteractionRequestDataConverter has the deserialization for this action handled.");
}
+60 -1
View File
@@ -288,7 +288,63 @@
"minDelta": 0,
"minLimitPercent": 15
}
}
},
"zombie": {
"armor": {
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
},
"weapon": {
"lowestMax": 90,
"highestMax": 100,
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
}
},
"shooterbtr": {
"armor": {
"maxDelta": 0,
"minDelta": 0,
"minLimitPercent": 0
},
"weapon": {
"lowestMax": 100,
"highestMax": 100,
"maxDelta": 0,
"minDelta": 0,
"minLimitPercent": 0
}
},
"skier": {
"armor": {
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
},
"weapon": {
"lowestMax": 60,
"highestMax": 100,
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
}
},
"peacemaker": {
"armor": {
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
},
"weapon": {
"lowestMax": 60,
"highestMax": 100,
"maxDelta": 10,
"minDelta": 0,
"minLimitPercent": 15
}
}
}
},
"lootItemResourceRandomization": {
@@ -925,6 +981,9 @@
},
"assaultgroup": {},
"gifter": {
"nvgIsActiveChanceDayPercent": 0,
"nvgIsActiveChanceNightPercent": 90,
"faceShieldIsActiveChancePercent": 0,
"lightIsActiveDayChancePercent": 25,
"lightIsActiveNightChancePercent": 75,
"laserIsActiveChancePercent": 75