Format Style Fixes
This commit is contained in:
@@ -6,12 +6,7 @@ namespace Benchmarks.Mock;
|
|||||||
|
|
||||||
public class MockLogger<T> : ISptLogger<T>
|
public class MockLogger<T> : ISptLogger<T>
|
||||||
{
|
{
|
||||||
public void LogWithColor(
|
public void LogWithColor(string data, LogTextColor? textColor = null, LogBackgroundColor? backgroundColor = null, Exception? ex = null)
|
||||||
string data,
|
|
||||||
LogTextColor? textColor = null,
|
|
||||||
LogBackgroundColor? backgroundColor = null,
|
|
||||||
Exception? ex = null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@@ -72,12 +67,7 @@ public class MockLogger<T> : ISptLogger<T>
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LogWithColor(
|
public void LogWithColor(string data, Exception? ex = null, LogTextColor? textColor = null, LogBackgroundColor? backgroundColor = null)
|
||||||
string data,
|
|
||||||
Exception? ex = null,
|
|
||||||
LogTextColor? textColor = null,
|
|
||||||
LogBackgroundColor? backgroundColor = null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine(data);
|
Console.WriteLine(data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ public static class MemberInfoExtensions
|
|||||||
public static string GetJsonName(this MemberInfo memberInfo)
|
public static string GetJsonName(this MemberInfo memberInfo)
|
||||||
{
|
{
|
||||||
return Attribute.IsDefined(memberInfo, typeof(JsonPropertyNameAttribute))
|
return Attribute.IsDefined(memberInfo, typeof(JsonPropertyNameAttribute))
|
||||||
? (
|
? (Attribute.GetCustomAttribute(memberInfo, typeof(JsonPropertyNameAttribute)) as JsonPropertyNameAttribute).Name
|
||||||
Attribute.GetCustomAttribute(memberInfo, typeof(JsonPropertyNameAttribute))
|
|
||||||
as JsonPropertyNameAttribute
|
|
||||||
).Name
|
|
||||||
: memberInfo.Name;
|
: memberInfo.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ namespace SPTarkov.Common.Extensions;
|
|||||||
|
|
||||||
public static class ObjectExtensions
|
public static class ObjectExtensions
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _indexedProperties =
|
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _indexedProperties = new();
|
||||||
new();
|
|
||||||
private static readonly Lock _indexedPropertiesLockObject = new();
|
private static readonly Lock _indexedPropertiesLockObject = new();
|
||||||
|
|
||||||
private static bool TryGetCachedProperty(Type type, string key, out PropertyInfo cachedProperty)
|
private static bool TryGetCachedProperty(Type type, string key, out PropertyInfo cachedProperty)
|
||||||
@@ -16,8 +15,7 @@ public static class ObjectExtensions
|
|||||||
{
|
{
|
||||||
if (!_indexedProperties.TryGetValue(type, out var properties))
|
if (!_indexedProperties.TryGetValue(type, out var properties))
|
||||||
{
|
{
|
||||||
properties = type.GetProperties()
|
properties = type.GetProperties().ToDictionary(prop => prop.GetJsonName(), prop => prop);
|
||||||
.ToDictionary(prop => prop.GetJsonName(), prop => prop);
|
|
||||||
_indexedProperties.Add(type, properties);
|
_indexedProperties.Add(type, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ public static class StringExtensions
|
|||||||
private static readonly Dictionary<string, Regex> _regexCache = new();
|
private static readonly Dictionary<string, Regex> _regexCache = new();
|
||||||
private static readonly Lock _regexCacheLock = new();
|
private static readonly Lock _regexCacheLock = new();
|
||||||
|
|
||||||
public static string RegexReplace(
|
public static string RegexReplace(this string source, [StringSyntax(StringSyntaxAttribute.Regex)] string regexString, string newValue)
|
||||||
this string source,
|
|
||||||
[StringSyntax(StringSyntaxAttribute.Regex)] string regexString,
|
|
||||||
string newValue
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
Regex regex;
|
Regex regex;
|
||||||
lock (_regexCacheLock)
|
lock (_regexCacheLock)
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
namespace SPTarkov.DI.Annotations;
|
namespace SPTarkov.DI.Annotations;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||||
public class Injectable(
|
public class Injectable(InjectionType injectionType = InjectionType.Scoped, Type? typeOverride = null, int typePriority = int.MaxValue)
|
||||||
InjectionType injectionType = InjectionType.Scoped,
|
: Attribute
|
||||||
Type? typeOverride = null,
|
|
||||||
int typePriority = int.MaxValue
|
|
||||||
) : Attribute
|
|
||||||
{
|
{
|
||||||
public InjectionType InjectionType { get; set; } = injectionType;
|
public InjectionType InjectionType { get; set; } = injectionType;
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
public void AddInjectableTypesFromTypeList(IEnumerable<Type> types)
|
public void AddInjectableTypesFromTypeList(IEnumerable<Type> types)
|
||||||
{
|
{
|
||||||
var typesToInject = types.Where(type =>
|
var typesToInject = types.Where(type =>
|
||||||
Attribute.IsDefined(type, typeof(Injectable))
|
Attribute.IsDefined(type, typeof(Injectable)) && !_injectedTypeNames.ContainsKey($"{type.Namespace}.{type.Name}")
|
||||||
&& !_injectedTypeNames.ContainsKey($"{type.Namespace}.{type.Name}")
|
|
||||||
);
|
);
|
||||||
if (typesToInject.Any())
|
if (typesToInject.Any())
|
||||||
{
|
{
|
||||||
@@ -52,9 +51,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
{
|
{
|
||||||
if (_oneTimeUseFlag)
|
if (_oneTimeUseFlag)
|
||||||
{
|
{
|
||||||
throw new Exception(
|
throw new Exception("Invalid usage of DependencyInjectionHandler, this is a one time use service!");
|
||||||
"Invalid usage of DependencyInjectionHandler, this is a one time use service!"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_oneTimeUseFlag = true;
|
_oneTimeUseFlag = true;
|
||||||
var typeRefValues = _injectedTypeNames.Values.Select(t => new TypeRefContainer(
|
var typeRefValues = _injectedTypeNames.Values.Select(t => new TypeRefContainer(
|
||||||
@@ -74,33 +71,19 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
// All the components without the removed overrides
|
// All the components without the removed overrides
|
||||||
var cleanedComponents = typeRefValues.Where(tr =>
|
var cleanedComponents = typeRefValues.Where(tr =>
|
||||||
{
|
{
|
||||||
var name = string.IsNullOrEmpty(tr.Type.FullName)
|
var name = string.IsNullOrEmpty(tr.Type.FullName) ? $"{tr.Type.Namespace}.{tr.Type.Name}" : tr.Type.FullName!;
|
||||||
? $"{tr.Type.Namespace}.{tr.Type.Name}"
|
|
||||||
: tr.Type.FullName!;
|
|
||||||
return !componentsToRemove.Contains(name);
|
return !componentsToRemove.Contains(name);
|
||||||
});
|
});
|
||||||
// All the components sorted and ready to be inserted into the DI container
|
// All the components sorted and ready to be inserted into the DI container
|
||||||
var sortedInjectableTypes = cleanedComponents.OrderBy(tRef =>
|
var sortedInjectableTypes = cleanedComponents.OrderBy(tRef => tRef.InjectableAttribute.TypePriority);
|
||||||
tRef.InjectableAttribute.TypePriority
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach (var typeRefToInject in sortedInjectableTypes)
|
foreach (var typeRefToInject in sortedInjectableTypes)
|
||||||
{
|
{
|
||||||
var nodes = new Queue<TypeRefContainer>();
|
var nodes = new Queue<TypeRefContainer>();
|
||||||
nodes.Enqueue(typeRefToInject);
|
nodes.Enqueue(typeRefToInject);
|
||||||
foreach (
|
foreach (var implementedInterface in typeRefToInject.Type.GetInterfaces().Where(t => !t.Namespace.StartsWith("System")))
|
||||||
var implementedInterface in typeRefToInject
|
|
||||||
.Type.GetInterfaces()
|
|
||||||
.Where(t => !t.Namespace.StartsWith("System"))
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
nodes.Enqueue(
|
nodes.Enqueue(new TypeRefContainer(typeRefToInject.InjectableAttribute, typeRefToInject.Type, implementedInterface));
|
||||||
new TypeRefContainer(
|
|
||||||
typeRefToInject.InjectableAttribute,
|
|
||||||
typeRefToInject.Type,
|
|
||||||
implementedInterface
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nodes.Any())
|
while (nodes.Any())
|
||||||
@@ -108,13 +91,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
var node = nodes.Dequeue();
|
var node = nodes.Dequeue();
|
||||||
if (node.Type.BaseType != null && node.Type.BaseType != typeof(object))
|
if (node.Type.BaseType != null && node.Type.BaseType != typeof(object))
|
||||||
{
|
{
|
||||||
nodes.Enqueue(
|
nodes.Enqueue(new TypeRefContainer(node.InjectableAttribute, typeRefToInject.Type, node.Type.BaseType));
|
||||||
new TypeRefContainer(
|
|
||||||
node.InjectableAttribute,
|
|
||||||
typeRefToInject.Type,
|
|
||||||
node.Type.BaseType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.Type.IsGenericType)
|
if (node.Type.IsGenericType)
|
||||||
@@ -123,11 +100,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RegisterComponent(
|
RegisterComponent(node.InjectableAttribute.InjectionType, node.Type, node.ParentType);
|
||||||
node.InjectableAttribute.InjectionType,
|
|
||||||
node.Type,
|
|
||||||
node.ParentType
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,10 +110,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_allLoadedTypes ??= AppDomain
|
_allLoadedTypes ??= AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).ToList();
|
||||||
.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(t => t.GetTypes())
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException ex)
|
catch (ReflectionTypeLoadException ex)
|
||||||
{
|
{
|
||||||
@@ -153,11 +123,7 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var matchedConstructors = _allConstructors.Where(c =>
|
var matchedConstructors = _allConstructors.Where(c =>
|
||||||
c.GetParameters()
|
c.GetParameters().Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition().FullName == typeName)
|
||||||
.Any(p =>
|
|
||||||
p.ParameterType.IsGenericType
|
|
||||||
&& p.ParameterType.GetGenericTypeDefinition().FullName == typeName
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var constructorInfos = matchedConstructors.ToList();
|
var constructorInfos = matchedConstructors.ToList();
|
||||||
@@ -169,19 +135,11 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
foreach (var matchedConstructor in constructorInfos)
|
foreach (var matchedConstructor in constructorInfos)
|
||||||
{
|
{
|
||||||
var constructorParams = matchedConstructor.GetParameters();
|
var constructorParams = matchedConstructor.GetParameters();
|
||||||
foreach (
|
foreach (var parameterInfo in constructorParams.Where(x => IsMatchingGenericType(x, typeName)))
|
||||||
var parameterInfo in constructorParams.Where(x =>
|
|
||||||
IsMatchingGenericType(x, typeName)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var parameters = parameterInfo.ParameterType.GetGenericArguments();
|
var parameters = parameterInfo.ParameterType.GetGenericArguments();
|
||||||
var typedGeneric = typeRef.ParentType.MakeGenericType(parameters);
|
var typedGeneric = typeRef.ParentType.MakeGenericType(parameters);
|
||||||
RegisterComponent(
|
RegisterComponent(typeRef.InjectableAttribute.InjectionType, parameterInfo.ParameterType, typedGeneric);
|
||||||
typeRef.InjectableAttribute.InjectionType,
|
|
||||||
parameterInfo.ParameterType,
|
|
||||||
typedGeneric
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,15 +152,10 @@ public class DependencyInjectionHandler(IServiceCollection serviceCollection)
|
|||||||
|
|
||||||
private static bool IsMatchingGenericType(ParameterInfo paramInfo, string typeName)
|
private static bool IsMatchingGenericType(ParameterInfo paramInfo, string typeName)
|
||||||
{
|
{
|
||||||
return paramInfo.ParameterType.IsGenericType
|
return paramInfo.ParameterType.IsGenericType && paramInfo.ParameterType.GetGenericTypeDefinition().FullName == typeName;
|
||||||
&& paramInfo.ParameterType.GetGenericTypeDefinition().FullName == typeName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterComponent(
|
private void RegisterComponent(InjectionType injectionType, Type registrableInterface, Type implementationType)
|
||||||
InjectionType injectionType,
|
|
||||||
Type registrableInterface,
|
|
||||||
Type implementationType
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
switch (injectionType)
|
switch (injectionType)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,10 +14,7 @@
|
|||||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.7" />
|
||||||
Include="Microsoft.Extensions.DependencyInjection.Abstractions"
|
|
||||||
Version="9.0.7"
|
|
||||||
/>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SPTarkov.Common\SPTarkov.Common.csproj" />
|
<ProjectReference Include="..\SPTarkov.Common\SPTarkov.Common.csproj" />
|
||||||
|
|||||||
@@ -27,16 +27,9 @@ public class CodeGenerator
|
|||||||
return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
|
return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (code.OpCode == OpCodes.Ldfld || code.OpCode == OpCodes.Ldflda || code.OpCode == OpCodes.Stfld)
|
||||||
code.OpCode == OpCodes.Ldfld
|
|
||||||
|| code.OpCode == OpCodes.Ldflda
|
|
||||||
|| code.OpCode == OpCodes.Stfld
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new CodeInstruction(
|
return new CodeInstruction(code.OpCode, AccessTools.Field(code.CallerType, code.OperandTarget as string))
|
||||||
code.OpCode,
|
|
||||||
AccessTools.Field(code.CallerType, code.OperandTarget as string)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
labels = GetLabelList(code),
|
labels = GetLabelList(code),
|
||||||
};
|
};
|
||||||
@@ -44,10 +37,7 @@ public class CodeGenerator
|
|||||||
|
|
||||||
if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
|
if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(
|
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters))
|
||||||
code.OpCode,
|
|
||||||
AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
labels = GetLabelList(code),
|
labels = GetLabelList(code),
|
||||||
};
|
};
|
||||||
@@ -55,10 +45,7 @@ public class CodeGenerator
|
|||||||
|
|
||||||
if (code.OpCode == OpCodes.Box)
|
if (code.OpCode == OpCodes.Box)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, code.CallerType)
|
return new CodeInstruction(code.OpCode, code.CallerType) { labels = GetLabelList(code) };
|
||||||
{
|
|
||||||
labels = GetLabelList(code),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -70,18 +57,12 @@ public class CodeGenerator
|
|||||||
|| code.OpCode == OpCodes.Br_S
|
|| code.OpCode == OpCodes.Br_S
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, code.OperandTarget)
|
return new CodeInstruction(code.OpCode, code.OperandTarget) { labels = GetLabelList(code) };
|
||||||
{
|
|
||||||
labels = GetLabelList(code),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Ldftn)
|
if (code.OpCode == OpCodes.Ldftn)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(
|
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters))
|
||||||
code.OpCode,
|
|
||||||
AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
labels = GetLabelList(code),
|
labels = GetLabelList(code),
|
||||||
};
|
};
|
||||||
@@ -91,8 +72,7 @@ public class CodeGenerator
|
|||||||
{
|
{
|
||||||
return new CodeInstruction(
|
return new CodeInstruction(
|
||||||
code.OpCode,
|
code.OpCode,
|
||||||
code.CallerType.GetConstructors()
|
code.CallerType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)
|
||||||
.FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
labels = GetLabelList(code),
|
labels = GetLabelList(code),
|
||||||
|
|||||||
@@ -24,13 +24,7 @@ public class CodeWithLabel : Code
|
|||||||
Label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeWithLabel(
|
public CodeWithLabel(OpCode opCode, Label label, Type callerType, object operandTarget, Type[] parameters = null)
|
||||||
OpCode opCode,
|
|
||||||
Label label,
|
|
||||||
Type callerType,
|
|
||||||
object operandTarget,
|
|
||||||
Type[] parameters = null
|
|
||||||
)
|
|
||||||
: base(opCode, callerType, operandTarget, parameters)
|
: base(opCode, callerType, operandTarget, parameters)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = label;
|
||||||
|
|||||||
@@ -33,9 +33,7 @@ public abstract class AbstractPatch
|
|||||||
&& _ilManipulatorList.Count == 0
|
&& _ilManipulatorList.Count == 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
throw new Exception(
|
throw new Exception($"{_harmony.Id}: At least one of the patch methods must be specified");
|
||||||
$"{_harmony.Id}: At least one of the patch methods must be specified"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,14 +53,7 @@ public abstract class AbstractPatch
|
|||||||
var T = GetType();
|
var T = GetType();
|
||||||
var methods = new List<HarmonyMethod>();
|
var methods = new List<HarmonyMethod>();
|
||||||
|
|
||||||
foreach (
|
foreach (var method in T.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly))
|
||||||
var method in T.GetMethods(
|
|
||||||
BindingFlags.Static
|
|
||||||
| BindingFlags.NonPublic
|
|
||||||
| BindingFlags.Public
|
|
||||||
| BindingFlags.DeclaredOnly
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (method.GetCustomAttribute(attributeType) != null)
|
if (method.GetCustomAttribute(attributeType) != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class AchievementCallbacks(
|
public class AchievementCallbacks(AchievementController achievementController, HttpResponseUtil httpResponseUtil)
|
||||||
AchievementController achievementController,
|
|
||||||
HttpResponseUtil httpResponseUtil
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/achievement/list
|
/// Handle client/achievement/list
|
||||||
@@ -18,9 +15,7 @@ public class AchievementCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetAchievements(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetAchievements(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(achievementController.GetAchievements(sessionID)));
|
||||||
httpResponseUtil.GetBody(achievementController.GetAchievements(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -29,8 +24,6 @@ public class AchievementCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> Statistic(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> Statistic(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(achievementController.GetAchievementStatics(sessionID)));
|
||||||
httpResponseUtil.GetBody(achievementController.GetAchievementStatics(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ public class BotCallbacks(BotController botController, HttpResponseUtil httpResp
|
|||||||
{
|
{
|
||||||
var splitUrl = url.Split('/');
|
var splitUrl = url.Split('/');
|
||||||
var type = splitUrl[^1];
|
var type = splitUrl[^1];
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(botController.GetBotPresetGenerationLimit(type)));
|
||||||
httpResponseUtil.NoBody(botController.GetBotPresetGenerationLimit(type))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,44 +33,28 @@ public class BotCallbacks(BotController botController, HttpResponseUtil httpResp
|
|||||||
var difficulty = splitUrl[^1];
|
var difficulty = splitUrl[^1];
|
||||||
if (difficulty == "core")
|
if (difficulty == "core")
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(botController.GetBotCoreDifficulty()));
|
||||||
httpResponseUtil.NoBody(botController.GetBotCoreDifficulty())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(botController.GetBotDifficulty(sessionID, type, difficulty)));
|
||||||
httpResponseUtil.NoBody(botController.GetBotDifficulty(sessionID, type, difficulty))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle singleplayer/settings/bot/difficulties
|
/// Handle singleplayer/settings/bot/difficulties
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetAllBotDifficulties(
|
public ValueTask<string> GetAllBotDifficulties(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(botController.GetAllBotDifficulties()));
|
||||||
httpResponseUtil.NoBody(botController.GetAllBotDifficulties())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/bot/generate
|
/// Handle client/game/bot/generate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GenerateBots(
|
public ValueTask<string> GenerateBots(string url, GenerateBotsRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GenerateBotsRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(botController.Generate(sessionID, info)));
|
||||||
httpResponseUtil.GetBody(botController.Generate(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ public class BtrDeliveryCallbacks(
|
|||||||
SaveServer saveServer
|
SaveServer saveServer
|
||||||
) : IOnUpdate
|
) : IOnUpdate
|
||||||
{
|
{
|
||||||
private readonly BtrDeliveryConfig _btrDeliveryConfig =
|
private readonly BtrDeliveryConfig _btrDeliveryConfig = configServer.GetConfig<BtrDeliveryConfig>();
|
||||||
configServer.GetConfig<BtrDeliveryConfig>();
|
|
||||||
|
|
||||||
public Task<bool> OnUpdate(long secondsSinceLastRun)
|
public Task<bool> OnUpdate(long secondsSinceLastRun)
|
||||||
{
|
{
|
||||||
@@ -80,13 +79,9 @@ public class BtrDeliveryCallbacks(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Found {deliveryList.Count} BTR delivery package(s) in profile {sessionId}");
|
||||||
$"Found {deliveryList.Count} BTR delivery package(s) in profile {sessionId}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return deliveryList
|
return deliveryList.Where(toBeDelivered => currentTime >= toBeDelivered.ScheduledTime).ToList();
|
||||||
.Where(toBeDelivered => currentTime >= toBeDelivered.ScheduledTime)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ public class BuildsCallbacks(HttpResponseUtil httpResponseUtil, BuildController
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetBuilds(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetBuilds(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(buildController.GetUserBuilds(sessionID)));
|
||||||
httpResponseUtil.GetBody(buildController.GetUserBuilds(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -29,11 +27,7 @@ public class BuildsCallbacks(HttpResponseUtil httpResponseUtil, BuildController
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> CreateMagazineTemplate(
|
public ValueTask<string> CreateMagazineTemplate(string url, SetMagazineRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SetMagazineRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
buildController.CreateMagazineTemplate(sessionID, request);
|
buildController.CreateMagazineTemplate(sessionID, request);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -43,11 +37,7 @@ public class BuildsCallbacks(HttpResponseUtil httpResponseUtil, BuildController
|
|||||||
/// Handle client/builds/weapon/save
|
/// Handle client/builds/weapon/save
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SetWeapon(
|
public ValueTask<string> SetWeapon(string url, PresetBuildActionRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
PresetBuildActionRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
buildController.SaveWeaponBuild(sessionID, request);
|
buildController.SaveWeaponBuild(sessionID, request);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -57,11 +47,7 @@ public class BuildsCallbacks(HttpResponseUtil httpResponseUtil, BuildController
|
|||||||
/// Handle client/builds/equipment/save
|
/// Handle client/builds/equipment/save
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SetEquipment(
|
public ValueTask<string> SetEquipment(string url, PresetBuildActionRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
PresetBuildActionRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
buildController.SaveEquipmentBuild(sessionID, request);
|
buildController.SaveEquipmentBuild(sessionID, request);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -71,11 +57,7 @@ public class BuildsCallbacks(HttpResponseUtil httpResponseUtil, BuildController
|
|||||||
/// Handle client/builds/delete
|
/// Handle client/builds/delete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> DeleteBuild(
|
public ValueTask<string> DeleteBuild(string url, RemoveBuildRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
RemoveBuildRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
buildController.RemoveBuild(sessionID, request);
|
buildController.RemoveBuild(sessionID, request);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
|
|||||||
@@ -42,26 +42,15 @@ public class ClientLogCallbacks(
|
|||||||
? serverLocalisationService.GetText("release-beta-disclaimer-mods-enabled")
|
? serverLocalisationService.GetText("release-beta-disclaimer-mods-enabled")
|
||||||
: serverLocalisationService.GetText("release-beta-disclaimer");
|
: serverLocalisationService.GetText("release-beta-disclaimer");
|
||||||
|
|
||||||
data.BetaDisclaimerAcceptText = serverLocalisationService.GetText(
|
data.BetaDisclaimerAcceptText = serverLocalisationService.GetText("release-beta-disclaimer-accept");
|
||||||
"release-beta-disclaimer-accept"
|
|
||||||
);
|
|
||||||
data.ServerModsLoadedText = serverLocalisationService.GetText("release-server-mods-loaded");
|
data.ServerModsLoadedText = serverLocalisationService.GetText("release-server-mods-loaded");
|
||||||
data.ServerModsLoadedDebugText = serverLocalisationService.GetText(
|
data.ServerModsLoadedDebugText = serverLocalisationService.GetText("release-server-mods-debug-message");
|
||||||
"release-server-mods-debug-message"
|
|
||||||
);
|
|
||||||
data.ClientModsLoadedText = serverLocalisationService.GetText("release-plugins-loaded");
|
data.ClientModsLoadedText = serverLocalisationService.GetText("release-plugins-loaded");
|
||||||
data.ClientModsLoadedDebugText = serverLocalisationService.GetText(
|
data.ClientModsLoadedDebugText = serverLocalisationService.GetText("release-plugins-loaded-debug-message");
|
||||||
"release-plugins-loaded-debug-message"
|
data.IllegalPluginsLoadedText = serverLocalisationService.GetText("release-illegal-plugins-loaded");
|
||||||
);
|
data.IllegalPluginsExceptionText = serverLocalisationService.GetText("release-illegal-plugins-exception");
|
||||||
data.IllegalPluginsLoadedText = serverLocalisationService.GetText(
|
|
||||||
"release-illegal-plugins-loaded"
|
|
||||||
);
|
|
||||||
data.IllegalPluginsExceptionText = serverLocalisationService.GetText(
|
|
||||||
"release-illegal-plugins-exception"
|
|
||||||
);
|
|
||||||
data.ReleaseSummaryText = serverLocalisationService.GetText("release-summary");
|
data.ReleaseSummaryText = serverLocalisationService.GetText("release-summary");
|
||||||
data.IsBeta =
|
data.IsBeta = ProgramStatics.ENTRY_TYPE() is EntryType.BLEEDING_EDGE or EntryType.BLEEDING_EDGE_MODS;
|
||||||
ProgramStatics.ENTRY_TYPE() is EntryType.BLEEDING_EDGE or EntryType.BLEEDING_EDGE_MODS;
|
|
||||||
data.IsModdable = ProgramStatics.MODS();
|
data.IsModdable = ProgramStatics.MODS();
|
||||||
data.IsModded = loadedMods.Count > 0;
|
data.IsModded = loadedMods.Count > 0;
|
||||||
|
|
||||||
|
|||||||
@@ -20,15 +20,9 @@ public class CustomizationCallbacks(
|
|||||||
/// Handle client/trading/customization/storage
|
/// Handle client/trading/customization/storage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetCustomisationUnlocks(
|
public ValueTask<string> GetCustomisationUnlocks(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(saveServer.GetProfile(sessionID).CustomisationUnlocks));
|
||||||
httpResponseUtil.GetBody(saveServer.GetProfile(sessionID).CustomisationUnlocks)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,20 +34,14 @@ public class CustomizationCallbacks(
|
|||||||
var splitUrl = url.Split('/');
|
var splitUrl = url.Split('/');
|
||||||
var traderId = splitUrl[^3];
|
var traderId = splitUrl[^3];
|
||||||
|
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(customizationController.GetTraderSuits(traderId, sessionID)));
|
||||||
httpResponseUtil.GetBody(customizationController.GetTraderSuits(traderId, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle CustomizationBuy event
|
/// Handle CustomizationBuy event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse BuyCustomisation(
|
public ItemEventRouterResponse BuyCustomisation(PmcData pmcData, BuyClothingRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
BuyClothingRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return customizationController.BuyCustomisation(pmcData, request, sessionID);
|
return customizationController.BuyCustomisation(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -62,15 +50,9 @@ public class CustomizationCallbacks(
|
|||||||
/// Handle client/hideout/customization/offer/list
|
/// Handle client/hideout/customization/offer/list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutCustomisation(
|
public ValueTask<string> GetHideoutCustomisation(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(customizationController.GetHideoutCustomisation(sessionID)));
|
||||||
httpResponseUtil.GetBody(customizationController.GetHideoutCustomisation(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -79,20 +61,14 @@ public class CustomizationCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetStorage(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetStorage(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(customizationController.GetCustomisationStorage(sessionID)));
|
||||||
httpResponseUtil.GetBody(customizationController.GetCustomisationStorage(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle CustomizationSet
|
/// Handle CustomizationSet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SetCustomisation(
|
public ItemEventRouterResponse SetCustomisation(PmcData pmcData, CustomizationSetRequest request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
CustomizationSetRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return customizationController.SetCustomisation(sessionID, request, pmcData);
|
return customizationController.SetCustomisation(sessionID, request, pmcData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTemplateSuits(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetTemplateSuits(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(databaseService.GetTemplates().Customization));
|
||||||
httpResponseUtil.GetBody(databaseService.GetTemplates().Customization)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -73,9 +71,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTemplateCharacter(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetTemplateCharacter(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(databaseService.GetTemplates().Character));
|
||||||
httpResponseUtil.GetBody(databaseService.GetTemplates().Character)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -84,9 +80,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutSettings(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetHideoutSettings(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(databaseService.GetHideout().Settings));
|
||||||
httpResponseUtil.GetBody(databaseService.GetHideout().Settings)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -104,9 +98,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutProduction(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetHideoutProduction(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(databaseService.GetHideout().Production));
|
||||||
httpResponseUtil.GetBody(databaseService.GetHideout().Production)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -115,9 +107,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocalesLanguages(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetLocalesLanguages(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(databaseService.GetLocales().Languages));
|
||||||
httpResponseUtil.GetBody(databaseService.GetLocales().Languages)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -128,8 +118,7 @@ public class DataCallbacks(
|
|||||||
{
|
{
|
||||||
var localeId = url.Replace("/client/menu/locale/", "");
|
var localeId = url.Replace("/client/menu/locale/", "");
|
||||||
var locales = databaseService.GetLocales();
|
var locales = databaseService.GetLocales();
|
||||||
var result =
|
var result = locales.Menu?[localeId] ?? locales.Menu?.FirstOrDefault(m => m.Key == "en").Value;
|
||||||
locales.Menu?[localeId] ?? locales.Menu?.FirstOrDefault(m => m.Key == "en").Value;
|
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
@@ -157,9 +146,7 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetQteList(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetQteList(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetUnclearedBody(hideoutController.GetQteList(sessionID)));
|
||||||
httpResponseUtil.GetUnclearedBody(hideoutController.GetQteList(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -170,8 +157,6 @@ public class DataCallbacks(
|
|||||||
{
|
{
|
||||||
var traderId = url.Replace("/client/items/prices/", "");
|
var traderId = url.Replace("/client/items/prices/", "");
|
||||||
|
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(traderController.GetItemPrices(sessionID, traderId)));
|
||||||
httpResponseUtil.GetBody(traderController.GetItemPrices(sessionID, traderId))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(TypePriority = OnUpdateOrder.DialogueCallbacks)]
|
[Injectable(TypePriority = OnUpdateOrder.DialogueCallbacks)]
|
||||||
public class DialogueCallbacks(
|
public class DialogueCallbacks(TimeUtil timeUtil, HttpResponseUtil httpResponseUtil, DialogueController dialogueController) : IOnUpdate
|
||||||
TimeUtil timeUtil,
|
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
DialogueController dialogueController
|
|
||||||
) : IOnUpdate
|
|
||||||
{
|
{
|
||||||
public Task<bool> OnUpdate(long timeSinceLastRun)
|
public Task<bool> OnUpdate(long timeSinceLastRun)
|
||||||
{
|
{
|
||||||
@@ -26,26 +22,16 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/list
|
/// Handle client/friend/list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetFriendList(
|
public virtual ValueTask<string> GetFriendList(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.GetFriendList(sessionID)));
|
||||||
httpResponseUtil.GetBody(dialogueController.GetFriendList(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/chatServer/list
|
/// Handle client/chatServer/list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetChatServerList(
|
public virtual ValueTask<string> GetChatServerList(string url, GetChatServerListRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetChatServerListRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var chatServer = new List<ChatServer>
|
var chatServer = new List<ChatServer>
|
||||||
{
|
{
|
||||||
@@ -71,20 +57,9 @@ public class DialogueCallbacks(
|
|||||||
/// TODO: request properties are not handled
|
/// TODO: request properties are not handled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetMailDialogList(
|
public virtual ValueTask<string> GetMailDialogList(string url, GetMailDialogListRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetMailDialogListRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.GenerateDialogueList(sessionID), 0, null, false));
|
||||||
httpResponseUtil.GetBody(
|
|
||||||
dialogueController.GenerateDialogueList(sessionID),
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -94,48 +69,25 @@ public class DialogueCallbacks(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetMailDialogView(
|
public virtual ValueTask<string> GetMailDialogView(string url, GetMailDialogViewRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetMailDialogViewRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.GenerateDialogueView(request, sessionID), 0, null, false));
|
||||||
httpResponseUtil.GetBody(
|
|
||||||
dialogueController.GenerateDialogueView(request, sessionID),
|
|
||||||
0,
|
|
||||||
null,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/mail/dialog/info
|
/// Handle client/mail/dialog/info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetMailDialogInfo(
|
public virtual ValueTask<string> GetMailDialogInfo(string url, GetMailDialogInfoRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetMailDialogInfoRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.GetDialogueInfo(request.DialogId, sessionID)));
|
||||||
httpResponseUtil.GetBody(
|
|
||||||
dialogueController.GetDialogueInfo(request.DialogId, sessionID)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/mail/dialog/remove
|
/// Handle client/mail/dialog/remove
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> RemoveDialog(
|
public virtual ValueTask<string> RemoveDialog(string url, RemoveDialogRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
RemoveDialogRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.RemoveDialogue(request.DialogId, sessionID);
|
dialogueController.RemoveDialogue(request.DialogId, sessionID);
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -145,11 +97,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/pin
|
/// Handle client/mail/dialog/pin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> PinDialog(
|
public virtual ValueTask<string> PinDialog(string url, PinDialogRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
PinDialogRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.SetDialoguePin(request.DialogId, true, sessionID);
|
dialogueController.SetDialoguePin(request.DialogId, true, sessionID);
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -159,11 +107,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/unpin
|
/// Handle client/mail/dialog/unpin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> UnpinDialog(
|
public virtual ValueTask<string> UnpinDialog(string url, PinDialogRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
PinDialogRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.SetDialoguePin(request.DialogId, false, sessionID);
|
dialogueController.SetDialoguePin(request.DialogId, false, sessionID);
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -173,11 +117,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/read
|
/// Handle client/mail/dialog/read
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> SetRead(
|
public virtual ValueTask<string> SetRead(string url, SetDialogReadRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SetDialogReadRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.SetRead(request.Dialogs, sessionID);
|
dialogueController.SetRead(request.Dialogs, sessionID);
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -187,28 +127,16 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/getAllAttachments
|
/// Handle client/mail/dialog/getAllAttachments
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetAllAttachments(
|
public virtual ValueTask<string> GetAllAttachments(string url, GetAllAttachmentsRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetAllAttachmentsRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.GetAllAttachments(request.DialogId, sessionID)));
|
||||||
httpResponseUtil.GetBody(
|
|
||||||
dialogueController.GetAllAttachments(request.DialogId, sessionID)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/mail/msg/send
|
/// Handle client/mail/msg/send
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual async ValueTask<string> SendMessage(
|
public virtual async ValueTask<string> SendMessage(string url, SendMessageRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SendMessageRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return httpResponseUtil.GetBody(await dialogueController.SendMessage(sessionID, request));
|
return httpResponseUtil.GetBody(await dialogueController.SendMessage(sessionID, request));
|
||||||
}
|
}
|
||||||
@@ -235,26 +163,16 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/send
|
/// Handle client/friend/request/send
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> SendFriendRequest(
|
public virtual ValueTask<string> SendFriendRequest(string url, FriendRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
FriendRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(dialogueController.SendFriendRequest(sessionID, request)));
|
||||||
httpResponseUtil.GetBody(dialogueController.SendFriendRequest(sessionID, request))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/friend/request/accept-all
|
/// Handle client/friend/request/accept-all
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> AcceptAllFriendRequests(
|
public virtual ValueTask<string> AcceptAllFriendRequests(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -263,11 +181,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/accept
|
/// Handle client/friend/request/accept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> AcceptFriendRequest(
|
public virtual ValueTask<string> AcceptFriendRequest(string url, AcceptFriendRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
AcceptFriendRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -276,11 +190,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/decline
|
/// Handle client/friend/request/decline
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> DeclineFriendRequest(
|
public virtual ValueTask<string> DeclineFriendRequest(string url, DeclineFriendRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
DeclineFriendRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -289,11 +199,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/cancel
|
/// Handle client/friend/request/cancel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> CancelFriendRequest(
|
public virtual ValueTask<string> CancelFriendRequest(string url, CancelFriendRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
CancelFriendRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -302,11 +208,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/delete
|
/// Handle client/friend/delete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> DeleteFriend(
|
public virtual ValueTask<string> DeleteFriend(string url, DeleteFriendRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
DeleteFriendRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.DeleteFriend(sessionID, request);
|
dialogueController.DeleteFriend(sessionID, request);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -316,11 +218,7 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/ignore/set
|
/// Handle client/friend/ignore/set
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> IgnoreFriend(
|
public virtual ValueTask<string> IgnoreFriend(string url, UIDRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
UIDRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -329,58 +227,34 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/ignore/remove
|
/// Handle client/friend/ignore/remove
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> UnIgnoreFriend(
|
public virtual ValueTask<string> UnIgnoreFriend(string url, UIDRequestData request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
UIDRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> ClearMail(
|
public virtual ValueTask<string> ClearMail(string url, ClearMailMessageRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ClearMailMessageRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
dialogueController.ClearMessages(sessionID, request);
|
dialogueController.ClearMessages(sessionID, request);
|
||||||
|
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> CreateGroupMail(
|
public virtual ValueTask<string> CreateGroupMail(string url, CreateGroupMailRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
CreateGroupMailRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyArrayResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> ChangeMailGroupOwner(
|
public virtual ValueTask<string> ChangeMailGroupOwner(string url, ChangeGroupMailOwnerRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ChangeGroupMailOwnerRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> AddUserToMail(
|
public virtual ValueTask<string> AddUserToMail(string url, AddUserGroupMailRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
AddUserGroupMailRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> RemoveUserFromMail(
|
public virtual ValueTask<string> RemoveUserFromMail(string url, RemoveUserGroupMailRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
RemoveUserGroupMailRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,7 @@ public class GameCallbacks(
|
|||||||
/// Handle client/game/version/validate
|
/// Handle client/game/version/validate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> VersionValidate(
|
public ValueTask<string> VersionValidate(string url, VersionValidateRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
VersionValidateRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -46,9 +42,7 @@ public class GameCallbacks(
|
|||||||
{
|
{
|
||||||
var startTimestampSec = timeUtil.GetTimeStamp();
|
var startTimestampSec = timeUtil.GetTimeStamp();
|
||||||
gameController.GameStart(url, sessionID, startTimestampSec);
|
gameController.GameStart(url, sessionID, startTimestampSec);
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(new GameStartResponse { UtcTime = startTimestampSec }));
|
||||||
httpResponseUtil.GetBody(new GameStartResponse { UtcTime = startTimestampSec })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -66,15 +60,9 @@ public class GameCallbacks(
|
|||||||
/// Handle client/game/config
|
/// Handle client/game/config
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGameConfig(
|
public ValueTask<string> GetGameConfig(string url, GameEmptyCrcRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GameEmptyCrcRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(gameController.GetGameConfig(sessionID)));
|
||||||
httpResponseUtil.GetBody(gameController.GetGameConfig(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -92,9 +80,7 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGameMode(string url, GameModeRequestData info, MongoId sessionID)
|
public ValueTask<string> GetGameMode(string url, GameModeRequestData info, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(gameController.GetGameMode(sessionID, info)));
|
||||||
httpResponseUtil.GetBody(gameController.GetGameMode(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -112,9 +98,7 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetCurrentGroup(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetCurrentGroup(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(gameController.GetCurrentGroup(sessionID)));
|
||||||
httpResponseUtil.GetBody(gameController.GetCurrentGroup(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -123,9 +107,7 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ValidateGameVersion(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> ValidateGameVersion(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(gameController.GetValidGameVersion(sessionID)));
|
||||||
httpResponseUtil.GetBody(gameController.GetValidGameVersion(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -134,9 +116,7 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GameKeepalive(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GameKeepalive(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(gameController.GetKeepAlive(sessionID)));
|
||||||
httpResponseUtil.GetBody(gameController.GetKeepAlive(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -146,9 +126,7 @@ public class GameCallbacks(
|
|||||||
public ValueTask<string> GetVersion(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetVersion(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
// change to be a proper type
|
// change to be a proper type
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(new { Version = watermark.GetInGameVersionLabel() }));
|
||||||
httpResponseUtil.NoBody(new { Version = watermark.GetInGameVersionLabel() })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -166,9 +144,7 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetRaidTime(string url, GetRaidTimeRequest request, MongoId sessionID)
|
public ValueTask<string> GetRaidTime(string url, GetRaidTimeRequest request, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(gameController.GetRaidTime(sessionID, request)));
|
||||||
httpResponseUtil.NoBody(gameController.GetRaidTime(sessionID, request))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -184,11 +160,7 @@ public class GameCallbacks(
|
|||||||
/// Handle client/survey/view
|
/// Handle client/survey/view
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetSurveyView(
|
public ValueTask<string> GetSurveyView(string url, SendSurveyOpinionRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SendSurveyOpinionRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -197,11 +169,7 @@ public class GameCallbacks(
|
|||||||
/// Handle client/survey/opinion
|
/// Handle client/survey/opinion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SendSurveyOpinion(
|
public ValueTask<string> SendSurveyOpinion(string url, SendSurveyOpinionRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SendSurveyOpinionRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class HealthCallbacks(
|
public class HealthCallbacks(HttpResponseUtil httpResponseUtil, ProfileHelper profileHelper, HealthController healthController)
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
ProfileHelper profileHelper,
|
|
||||||
HealthController healthController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom spt server request found in modules/QTEPatch.cs
|
/// Custom spt server request found in modules/QTEPatch.cs
|
||||||
@@ -25,11 +21,7 @@ public class HealthCallbacks(
|
|||||||
/// <returns>empty response, no data sent back to client</returns>
|
/// <returns>empty response, no data sent back to client</returns>
|
||||||
public ValueTask<string> HandleWorkoutEffects(string url, WorkoutData info, MongoId sessionID)
|
public ValueTask<string> HandleWorkoutEffects(string url, WorkoutData info, MongoId sessionID)
|
||||||
{
|
{
|
||||||
healthController.ApplyWorkoutChanges(
|
healthController.ApplyWorkoutChanges(profileHelper.GetPmcProfile(sessionID), info, sessionID);
|
||||||
profileHelper.GetPmcProfile(sessionID),
|
|
||||||
info,
|
|
||||||
sessionID
|
|
||||||
);
|
|
||||||
return new ValueTask<string>(httpResponseUtil.EmptyResponse());
|
return new ValueTask<string>(httpResponseUtil.EmptyResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +32,7 @@ public class HealthCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse OffraidEat(
|
public ItemEventRouterResponse OffraidEat(PmcData pmcData, OffraidEatRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
OffraidEatRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return healthController.OffRaidEat(pmcData, info, sessionID);
|
return healthController.OffRaidEat(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -56,11 +44,7 @@ public class HealthCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse OffraidHeal(
|
public ItemEventRouterResponse OffraidHeal(PmcData pmcData, OffraidHealRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
OffraidHealRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return healthController.OffRaidHeal(pmcData, info, sessionID);
|
return healthController.OffRaidHeal(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -72,11 +56,7 @@ public class HealthCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse HealthTreatment(
|
public ItemEventRouterResponse HealthTreatment(PmcData pmcData, HealthTreatmentRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HealthTreatmentRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return healthController.HealthTreatment(pmcData, info, sessionID);
|
return healthController.HealthTreatment(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ using SPTarkov.Server.Core.Servers;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(TypePriority = OnUpdateOrder.HideoutCallbacks)]
|
[Injectable(TypePriority = OnUpdateOrder.HideoutCallbacks)]
|
||||||
public class HideoutCallbacks(HideoutController hideoutController, ConfigServer configServer)
|
public class HideoutCallbacks(HideoutController hideoutController, ConfigServer configServer) : IOnUpdate
|
||||||
: IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly HideoutConfig _hideoutConfig = configServer.GetConfig<HideoutConfig>();
|
private readonly HideoutConfig _hideoutConfig = configServer.GetConfig<HideoutConfig>();
|
||||||
|
|
||||||
@@ -62,11 +61,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutPutItemsInAreaSlots
|
/// Handle HideoutPutItemsInAreaSlots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse PutItemsInAreaSlots(
|
public ItemEventRouterResponse PutItemsInAreaSlots(PmcData pmcData, HideoutPutItemInRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutPutItemInRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.PutItemsInAreaSlots(pmcData, request, sessionID);
|
return hideoutController.PutItemsInAreaSlots(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -74,11 +69,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutTakeItemsFromAreaSlots event
|
/// Handle HideoutTakeItemsFromAreaSlots event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse TakeItemsFromAreaSlots(
|
public ItemEventRouterResponse TakeItemsFromAreaSlots(PmcData pmcData, HideoutTakeItemOutRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutTakeItemOutRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.TakeItemsFromAreaSlots(pmcData, request, sessionID);
|
return hideoutController.TakeItemsFromAreaSlots(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -86,11 +77,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutToggleArea event
|
/// Handle HideoutToggleArea event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ToggleArea(
|
public ItemEventRouterResponse ToggleArea(PmcData pmcData, HideoutToggleAreaRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutToggleAreaRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.ToggleArea(pmcData, request, sessionID);
|
return hideoutController.ToggleArea(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -110,11 +97,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutScavCaseProductionStart event
|
/// Handle HideoutScavCaseProductionStart event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ScavCaseProductionStart(
|
public ItemEventRouterResponse ScavCaseProductionStart(PmcData pmcData, HideoutScavCaseStartRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutScavCaseStartRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.ScavCaseProductionStart(pmcData, request, sessionID);
|
return hideoutController.ScavCaseProductionStart(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -134,11 +117,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutTakeProduction event
|
/// Handle HideoutTakeProduction event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse TakeProduction(
|
public ItemEventRouterResponse TakeProduction(PmcData pmcData, HideoutTakeProductionRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutTakeProductionRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.TakeProduction(pmcData, request, sessionID);
|
return hideoutController.TakeProduction(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -176,11 +155,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ImproveArea(
|
public ItemEventRouterResponse ImproveArea(PmcData pmcData, HideoutImproveAreaRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutImproveAreaRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.ImproveArea(sessionID, pmcData, request);
|
return hideoutController.ImproveArea(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -188,11 +163,7 @@ public class HideoutCallbacks(HideoutController hideoutController, ConfigServer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - HideoutCancelProductionCommand
|
/// Handle client/game/profile/items/moving - HideoutCancelProductionCommand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse CancelProduction(
|
public ItemEventRouterResponse CancelProduction(PmcData pmcData, HideoutCancelProductionRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutCancelProductionRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return hideoutController.CancelProduction(sessionID, pmcData, request);
|
return hideoutController.CancelProduction(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ public class InraidCallbacks(InRaidController inRaidController, HttpResponseUtil
|
|||||||
/// <param name="info">register player request</param>
|
/// <param name="info">register player request</param>
|
||||||
/// <param name="sessionID">Session id</param>
|
/// <param name="sessionID">Session id</param>
|
||||||
/// <returns>Null http response</returns>
|
/// <returns>Null http response</returns>
|
||||||
public ValueTask<string> RegisterPlayer(
|
public ValueTask<string> RegisterPlayer(string url, RegisterPlayerRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
RegisterPlayerRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
inRaidController.AddPlayer(sessionID, info);
|
inRaidController.AddPlayer(sessionID, info);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -47,24 +43,16 @@ public class InraidCallbacks(InRaidController inRaidController, HttpResponseUtil
|
|||||||
/// <returns>JSON as string</returns>
|
/// <returns>JSON as string</returns>
|
||||||
public ValueTask<string> GetRaidMenuSettings()
|
public ValueTask<string> GetRaidMenuSettings()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(inRaidController.GetInRaidConfig().RaidMenuSettings));
|
||||||
httpResponseUtil.NoBody(inRaidController.GetInRaidConfig().RaidMenuSettings)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle singleplayer/scav/traitorscavhostile
|
/// Handle singleplayer/scav/traitorscavhostile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTraitorScavHostileChance(
|
public ValueTask<string> GetTraitorScavHostileChance(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(inRaidController.GetTraitorScavHostileChance(url, sessionID)));
|
||||||
httpResponseUtil.NoBody(inRaidController.GetTraitorScavHostileChance(url, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -73,8 +61,6 @@ public class InraidCallbacks(InRaidController inRaidController, HttpResponseUtil
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetBossTypes(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetBossTypes(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(inRaidController.GetBossTypes(url, sessionID)));
|
||||||
httpResponseUtil.NoBody(inRaidController.GetBossTypes(url, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,8 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(TypePriority = OnUpdateOrder.InsuranceCallbacks)]
|
[Injectable(TypePriority = OnUpdateOrder.InsuranceCallbacks)]
|
||||||
public class InsuranceCallbacks(
|
public class InsuranceCallbacks(InsuranceController insuranceController, HttpResponseUtil httpResponseUtil, ConfigServer configServer)
|
||||||
InsuranceController insuranceController,
|
: IOnUpdate
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
ConfigServer configServer
|
|
||||||
) : IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly InsuranceConfig _insuranceConfig = configServer.GetConfig<InsuranceConfig>();
|
private readonly InsuranceConfig _insuranceConfig = configServer.GetConfig<InsuranceConfig>();
|
||||||
|
|
||||||
@@ -39,15 +36,9 @@ public class InsuranceCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetInsuranceCost(
|
public ValueTask<string> GetInsuranceCost(string url, GetInsuranceCostRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetInsuranceCostRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(insuranceController.Cost(info, sessionID)));
|
||||||
httpResponseUtil.GetBody(insuranceController.Cost(info, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -57,11 +48,7 @@ public class InsuranceCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse Insure(
|
public ItemEventRouterResponse Insure(PmcData pmcData, InsureRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
InsureRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return insuranceController.Insure(pmcData, info, sessionID);
|
return insuranceController.Insure(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ using SPTarkov.Server.Core.Models.Eft.Quests;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class InventoryCallbacks(
|
public class InventoryCallbacks(InventoryController inventoryController, QuestController questController)
|
||||||
InventoryController inventoryController,
|
|
||||||
QuestController questController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving Move event
|
/// Handle client/game/profile/items/moving Move event
|
||||||
@@ -114,11 +111,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SwapItem(
|
public ItemEventRouterResponse SwapItem(PmcData pmcData, InventorySwapRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
InventorySwapRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return inventoryController.SwapItem(pmcData, info, sessionID);
|
return inventoryController.SwapItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -129,11 +122,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse FoldItem(
|
public ItemEventRouterResponse FoldItem(PmcData pmcData, InventoryFoldRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryFoldRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return inventoryController.FoldItem(pmcData, info, sessionID);
|
return inventoryController.FoldItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -144,11 +133,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ToggleItem(
|
public ItemEventRouterResponse ToggleItem(PmcData pmcData, InventoryToggleRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryToggleRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return inventoryController.ToggleItem(pmcData, info, sessionID);
|
return inventoryController.ToggleItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -159,11 +144,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse TagItem(
|
public ItemEventRouterResponse TagItem(PmcData pmcData, InventoryTagRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryTagRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return inventoryController.TagItem(pmcData, request, sessionId);
|
return inventoryController.TagItem(pmcData, request, sessionId);
|
||||||
}
|
}
|
||||||
@@ -229,11 +210,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ReadEncyclopedia(
|
public ItemEventRouterResponse ReadEncyclopedia(PmcData pmcData, InventoryReadEncyclopediaRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryReadEncyclopediaRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return inventoryController.ReadEncyclopedia(pmcData, info, sessionID);
|
return inventoryController.ReadEncyclopedia(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -376,12 +353,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse FailQuest(
|
public ItemEventRouterResponse FailQuest(PmcData pmcData, FailQuestRequestData info, MongoId sessionID, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
FailQuestRequestData info,
|
|
||||||
MongoId sessionID,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
questController.FailQuest(pmcData, info, sessionID, output);
|
questController.FailQuest(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -394,12 +366,7 @@ public class InventoryCallbacks(
|
|||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse PinOrLock(
|
public ItemEventRouterResponse PinOrLock(PmcData pmcData, PinOrLockItemRequest info, MongoId sessionID, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
PinOrLockItemRequest info,
|
|
||||||
MongoId sessionID,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
inventoryController.PinOrLock(pmcData, info, sessionID, output);
|
inventoryController.PinOrLock(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -10,19 +10,11 @@ namespace SPTarkov.Server.Core.Callbacks;
|
|||||||
[Injectable]
|
[Injectable]
|
||||||
public class ItemEventCallbacks(HttpResponseUtil httpResponseUtil, ItemEventRouter itemEventRouter)
|
public class ItemEventCallbacks(HttpResponseUtil httpResponseUtil, ItemEventRouter itemEventRouter)
|
||||||
{
|
{
|
||||||
public async ValueTask<string> HandleEvents(
|
public async ValueTask<string> HandleEvents(string url, ItemEventRouterRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ItemEventRouterRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var eventResponse = await itemEventRouter.HandleEvents(info, sessionID);
|
var eventResponse = await itemEventRouter.HandleEvents(info, sessionID);
|
||||||
var result = IsCriticalError(eventResponse.Warnings)
|
var result = IsCriticalError(eventResponse.Warnings)
|
||||||
? httpResponseUtil.GetBody(
|
? httpResponseUtil.GetBody(eventResponse, GetErrorCode(eventResponse.Warnings), eventResponse.Warnings[0].ErrorMessage)
|
||||||
eventResponse,
|
|
||||||
GetErrorCode(eventResponse.Warnings),
|
|
||||||
eventResponse.Warnings[0].ErrorMessage
|
|
||||||
)
|
|
||||||
: httpResponseUtil.GetBody(eventResponse);
|
: httpResponseUtil.GetBody(eventResponse);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -41,10 +33,7 @@ public class ItemEventCallbacks(HttpResponseUtil httpResponseUtil, ItemEventRout
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List of non-critical error codes, we return true if any error NOT included is passed in
|
// List of non-critical error codes, we return true if any error NOT included is passed in
|
||||||
var nonCriticalErrorCodes = new HashSet<BackendErrorCodes>
|
var nonCriticalErrorCodes = new HashSet<BackendErrorCodes> { BackendErrorCodes.NotEnoughSpace };
|
||||||
{
|
|
||||||
BackendErrorCodes.NotEnoughSpace,
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var warning in warnings)
|
foreach (var warning in warnings)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -74,26 +74,16 @@ public class LauncherCallbacks(
|
|||||||
|
|
||||||
public ValueTask<string> GetCompatibleTarkovVersion()
|
public ValueTask<string> GetCompatibleTarkovVersion()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(launcherController.GetCompatibleTarkovVersion()));
|
||||||
httpResponseUtil.NoBody(launcherController.GetCompatibleTarkovVersion())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> GetLoadedServerMods()
|
public ValueTask<string> GetLoadedServerMods()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(launcherController.GetLoadedServerMods()));
|
||||||
httpResponseUtil.NoBody(launcherController.GetLoadedServerMods())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> GetServerModsProfileUsed(
|
public ValueTask<string> GetServerModsProfileUsed(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(launcherController.GetServerModsProfileUsed(sessionID)));
|
||||||
httpResponseUtil.NoBody(launcherController.GetServerModsProfileUsed(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,29 +16,17 @@ public class LauncherV2Callbacks(
|
|||||||
{
|
{
|
||||||
public ValueTask<string> Ping()
|
public ValueTask<string> Ping()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(new LauncherV2PingResponse { Response = launcherV2Controller.Ping() }));
|
||||||
httpResponseUtil.NoBody(
|
|
||||||
new LauncherV2PingResponse { Response = launcherV2Controller.Ping() }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Types()
|
public ValueTask<string> Types()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(new LauncherV2TypesResponse { Response = launcherV2Controller.Types() }));
|
||||||
httpResponseUtil.NoBody(
|
|
||||||
new LauncherV2TypesResponse { Response = launcherV2Controller.Types() }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Login(LoginRequestData info)
|
public ValueTask<string> Login(LoginRequestData info)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(new LauncherV2LoginResponse { Response = launcherV2Controller.Login(info) }));
|
||||||
httpResponseUtil.NoBody(
|
|
||||||
new LauncherV2LoginResponse { Response = launcherV2Controller.Login(info) }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<string> Register(RegisterData info)
|
public async ValueTask<string> Register(RegisterData info)
|
||||||
@@ -94,31 +82,20 @@ public class LauncherV2Callbacks(
|
|||||||
|
|
||||||
public ValueTask<string> Mods()
|
public ValueTask<string> Mods()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.NoBody(new LauncherV2ModsResponse { Response = launcherV2Controller.LoadedMods() }));
|
||||||
httpResponseUtil.NoBody(
|
|
||||||
new LauncherV2ModsResponse { Response = launcherV2Controller.LoadedMods() }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Profiles()
|
public ValueTask<string> Profiles()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(
|
||||||
httpResponseUtil.NoBody(
|
httpResponseUtil.NoBody(new LauncherV2ProfilesResponse { Response = profileController.GetMiniProfiles() })
|
||||||
new LauncherV2ProfilesResponse { Response = profileController.GetMiniProfiles() }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Profile(MongoId sessionId)
|
public ValueTask<string> Profile(MongoId sessionId)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(
|
||||||
httpResponseUtil.NoBody(
|
httpResponseUtil.NoBody(new LauncherV2ProfileResponse { Response = launcherV2Controller.GetProfile(sessionId) })
|
||||||
new LauncherV2ProfileResponse
|
|
||||||
{
|
|
||||||
Response = launcherV2Controller.GetProfile(sessionId),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class LocationCallbacks(
|
public class LocationCallbacks(HttpResponseUtil httpResponseUtil, LocationController locationController)
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
LocationController locationController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/locations
|
/// Handle client/locations
|
||||||
@@ -19,23 +16,15 @@ public class LocationCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocationData(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetLocationData(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(locationController.GenerateAll(sessionID)));
|
||||||
httpResponseUtil.GetBody(locationController.GenerateAll(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/airdrop/loot
|
/// Handle client/airdrop/loot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetAirdropLoot(
|
public ValueTask<string> GetAirdropLoot(string url, GetAirdropLootRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetAirdropLootRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(locationController.GetAirDropLoot(info)));
|
||||||
httpResponseUtil.GetBody(locationController.GetAirDropLoot(info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ using static SPTarkov.Server.Core.Services.MatchLocationService;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class MatchCallbacks(
|
public class MatchCallbacks(HttpResponseUtil httpResponseUtil, MatchController matchController, DatabaseService databaseService)
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
MatchController matchController,
|
|
||||||
DatabaseService databaseService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/match/updatePing
|
/// Handle client/match/updatePing
|
||||||
@@ -55,9 +51,7 @@ public class MatchCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GroupCurrent(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GroupCurrent(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(new MatchGroupCurrentResponse { Squad = [] }));
|
||||||
httpResponseUtil.GetBody(new MatchGroupCurrentResponse { Squad = [] })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -82,11 +76,7 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/group/invite/send
|
/// Handle client/match/group/invite/send
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SendGroupInvite(
|
public ValueTask<string> SendGroupInvite(string url, MatchGroupInviteSendRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
MatchGroupInviteSendRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody("2427943f23698ay9f2863735"));
|
return new ValueTask<string>(httpResponseUtil.GetBody("2427943f23698ay9f2863735"));
|
||||||
}
|
}
|
||||||
@@ -107,11 +97,7 @@ public class MatchCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> DeclineGroupInvite(
|
public ValueTask<string> DeclineGroupInvite(string url, RequestIdRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
RequestIdRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -135,11 +121,7 @@ public class MatchCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> TransferGroup(
|
public ValueTask<string> TransferGroup(string url, MatchGroupTransferRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
MatchGroupTransferRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -166,11 +148,7 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/analytics/event-disconnect
|
/// Handle client/analytics/event-disconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> EventDisconnect(
|
public ValueTask<string> EventDisconnect(string url, PutMetricsRequestData request, MongoId sessionId)
|
||||||
string url,
|
|
||||||
PutMetricsRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -190,9 +168,7 @@ public class MatchCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> JoinMatch(string url, MatchGroupJoinRequest request, MongoId sessionID)
|
public ValueTask<string> JoinMatch(string url, MatchGroupJoinRequest request, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(matchController.JoinMatch(request, sessionID)));
|
||||||
httpResponseUtil.GetBody(matchController.JoinMatch(request, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -209,15 +185,9 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/group/status
|
/// Handle client/match/group/status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGroupStatus(
|
public ValueTask<string> GetGroupStatus(string url, MatchGroupStatusRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
MatchGroupStatusRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(matchController.GetGroupStatus(info)));
|
||||||
httpResponseUtil.GetBody(matchController.GetGroupStatus(info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -243,11 +213,7 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/group/player/remove
|
/// Handle client/match/group/player/remove
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> RemovePlayerFromGroup(
|
public ValueTask<string> RemovePlayerFromGroup(string url, MatchGroupPlayerRemoveRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
MatchGroupPlayerRemoveRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -256,26 +222,16 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/local/start
|
/// Handle client/match/local/start
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> StartLocalRaid(
|
public ValueTask<string> StartLocalRaid(string url, StartLocalRaidRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
StartLocalRaidRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(matchController.StartLocalRaid(sessionID, info)));
|
||||||
httpResponseUtil.GetBody(matchController.StartLocalRaid(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/match/local/end
|
/// Handle client/match/local/end
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> EndLocalRaid(
|
public ValueTask<string> EndLocalRaid(string url, EndLocalRaidRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EndLocalRaidRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
matchController.EndLocalRaid(sessionID, info);
|
matchController.EndLocalRaid(sessionID, info);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -285,11 +241,7 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/raid/configuration
|
/// Handle client/raid/configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetRaidConfiguration(
|
public ValueTask<string> GetRaidConfiguration(string url, GetRaidConfigurationRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetRaidConfigurationRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
matchController.ConfigureOfflineRaid(info, sessionID);
|
matchController.ConfigureOfflineRaid(info, sessionID);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -302,11 +254,7 @@ public class MatchCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetConfigurationByProfile(
|
public ValueTask<string> GetConfigurationByProfile(string url, GetRaidConfigurationRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetRaidConfigurationRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -335,11 +283,7 @@ public class MatchCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/match/group/start_game
|
/// Handle client/match/group/start_game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Task<string> StartGameAsGroupLeader(
|
public Task<string> StartGameAsGroupLeader(string url, MatchGroupStartGameRequest? request, MongoId? sessionId)
|
||||||
string url,
|
|
||||||
MatchGroupStartGameRequest? request,
|
|
||||||
MongoId? sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// returns a ProfileStatusResponse object
|
// returns a ProfileStatusResponse object
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ public class NoteCallbacks(NoteController noteController)
|
|||||||
/// <param name="request">Add note request</param>
|
/// <param name="request">Add note request</param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse AddNote(
|
public ItemEventRouterResponse AddNote(PmcData pmcData, NoteActionRequest request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return noteController.AddNote(pmcData, request, sessionID);
|
return noteController.AddNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -33,11 +29,7 @@ public class NoteCallbacks(NoteController noteController)
|
|||||||
/// <param name="request">Edit note request</param>
|
/// <param name="request">Edit note request</param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse EditNote(
|
public ItemEventRouterResponse EditNote(PmcData pmcData, NoteActionRequest request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return noteController.EditNote(pmcData, request, sessionID);
|
return noteController.EditNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -49,11 +41,7 @@ public class NoteCallbacks(NoteController noteController)
|
|||||||
/// <param name="request">Delete note request</param>
|
/// <param name="request">Delete note request</param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse DeleteNote(
|
public ItemEventRouterResponse DeleteNote(PmcData pmcData, NoteActionRequest request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return noteController.DeleteNote(pmcData, request, sessionID);
|
return noteController.DeleteNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ public class NotifierCallbacks(
|
|||||||
*/
|
*/
|
||||||
notifierController
|
notifierController
|
||||||
.NotifyAsync(tmpSessionID)
|
.NotifyAsync(tmpSessionID)
|
||||||
.ContinueWith(messages =>
|
.ContinueWith(messages => messages.Result.Select(message => string.Join("\n", jsonUtil.Serialize(message))))
|
||||||
messages.Result.Select(message => string.Join("\n", jsonUtil.Serialize(message)))
|
|
||||||
)
|
|
||||||
.ContinueWith(text => httpServerHelper.SendTextJson(resp, text.Result));
|
.ContinueWith(text => httpServerHelper.SendTextJson(resp, text.Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,15 +55,9 @@ public class NotifierCallbacks(
|
|||||||
/// Handle client/notifier/channel/create
|
/// Handle client/notifier/channel/create
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> CreateNotifierChannel(
|
public ValueTask<string> CreateNotifierChannel(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
string url,
|
|
||||||
EmptyRequestData _,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(notifierController.GetChannel(sessionID)));
|
||||||
httpResponseUtil.GetBody(notifierController.GetChannel(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -74,9 +66,7 @@ public class NotifierCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SelectProfile(string url, UIDRequestData info, MongoId sessionID)
|
public ValueTask<string> SelectProfile(string url, UIDRequestData info, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(new SelectProfileResponse { Status = "ok" }));
|
||||||
httpResponseUtil.GetBody(new SelectProfileResponse { Status = "ok" })
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class PrestigeCallbacks(
|
public class PrestigeCallbacks(HttpResponseUtil httpResponseUtil, PrestigeController prestigeController)
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
PrestigeController prestigeController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/prestige/list
|
/// Handle client/prestige/list
|
||||||
@@ -22,9 +19,7 @@ public class PrestigeCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetPrestige(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetPrestige(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(prestigeController.GetPrestige(sessionID)));
|
||||||
httpResponseUtil.GetBody(prestigeController.GetPrestige(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -34,11 +29,7 @@ public class PrestigeCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async ValueTask<string> ObtainPrestige(
|
public async ValueTask<string> ObtainPrestige(string url, ObtainPrestigeRequestList info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ObtainPrestigeRequestList info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
await prestigeController.ObtainPrestige(sessionID, info);
|
await prestigeController.ObtainPrestige(sessionID, info);
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ public class ProfileCallbacks(
|
|||||||
/// Handle client/game/profile/create
|
/// Handle client/game/profile/create
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async ValueTask<string> CreateProfile(
|
public async ValueTask<string> CreateProfile(string url, ProfileCreateRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ProfileCreateRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var id = await profileController.CreateProfile(info, sessionID);
|
var id = await profileController.CreateProfile(info, sessionID);
|
||||||
return httpResponse.GetBody(new CreateProfileResponse { UserId = id });
|
return httpResponse.GetBody(new CreateProfileResponse { UserId = id });
|
||||||
@@ -40,9 +36,7 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetProfileData(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetProfileData(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(profileController.GetCompleteProfile(sessionID)));
|
||||||
httpResponse.GetBody(profileController.GetCompleteProfile(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,22 +47,14 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> RegenerateScav(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> RegenerateScav(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(new List<PmcData> { profileController.GeneratePlayerScav(sessionID) }));
|
||||||
httpResponse.GetBody(
|
|
||||||
new List<PmcData> { profileController.GeneratePlayerScav(sessionID) }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/voice/change event
|
/// Handle client/game/profile/voice/change event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ChangeVoice(
|
public ValueTask<string> ChangeVoice(string url, ProfileChangeVoiceRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
ProfileChangeVoiceRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
profileController.ChangeVoice(info, sessionID);
|
profileController.ChangeVoice(info, sessionID);
|
||||||
return new ValueTask<string>(httpResponse.NullResponse());
|
return new ValueTask<string>(httpResponse.NullResponse());
|
||||||
@@ -79,35 +65,19 @@ public class ProfileCallbacks(
|
|||||||
/// Client allows player to adjust their profile name
|
/// Client allows player to adjust their profile name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Client response as string</returns>
|
/// <returns>Client response as string</returns>
|
||||||
public ValueTask<string> ChangeNickname(
|
public ValueTask<string> ChangeNickname(string url, ProfileChangeNicknameRequestData info, MongoId sessionId)
|
||||||
string url,
|
|
||||||
ProfileChangeNicknameRequestData info,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = profileController.ChangeNickname(info, sessionId);
|
var output = profileController.ChangeNickname(info, sessionId);
|
||||||
|
|
||||||
return output switch
|
return output switch
|
||||||
{
|
{
|
||||||
NicknameValidationResult.Taken => new ValueTask<string>(
|
NicknameValidationResult.Taken => new ValueTask<string>(
|
||||||
httpResponse.GetBody<object?>(
|
httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotUnique, $"{BackendErrorCodes.NicknameNotUnique} - ")
|
||||||
null,
|
|
||||||
BackendErrorCodes.NicknameNotUnique,
|
|
||||||
$"{BackendErrorCodes.NicknameNotUnique} - "
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
NicknameValidationResult.Short => new ValueTask<string>(
|
NicknameValidationResult.Short => new ValueTask<string>(
|
||||||
httpResponse.GetBody<object?>(
|
httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotValid, $"{BackendErrorCodes.NicknameNotValid} - ")
|
||||||
null,
|
|
||||||
BackendErrorCodes.NicknameNotValid,
|
|
||||||
$"{BackendErrorCodes.NicknameNotValid} - "
|
|
||||||
)
|
|
||||||
),
|
|
||||||
_ => new ValueTask<string>(
|
|
||||||
httpResponse.GetBody<object>(
|
|
||||||
new { status = 0, NicknameChangeDate = timeUtil.GetTimeStamp() }
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|
_ => new ValueTask<string>(httpResponse.GetBody<object>(new { status = 0, NicknameChangeDate = timeUtil.GetTimeStamp() })),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,27 +85,15 @@ public class ProfileCallbacks(
|
|||||||
/// Handle client/game/profile/nickname/validate
|
/// Handle client/game/profile/nickname/validate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Client response as string</returns>
|
/// <returns>Client response as string</returns>
|
||||||
public ValueTask<string> ValidateNickname(
|
public ValueTask<string> ValidateNickname(string url, ValidateNicknameRequestData info, MongoId sessionId)
|
||||||
string url,
|
|
||||||
ValidateNicknameRequestData info,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return profileController.ValidateNickname(info, sessionId) switch
|
return profileController.ValidateNickname(info, sessionId) switch
|
||||||
{
|
{
|
||||||
NicknameValidationResult.Taken => new ValueTask<string>(
|
NicknameValidationResult.Taken => new ValueTask<string>(
|
||||||
httpResponse.GetBody<object?>(
|
httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotUnique, $"{BackendErrorCodes.NicknameNotUnique} - ")
|
||||||
null,
|
|
||||||
BackendErrorCodes.NicknameNotUnique,
|
|
||||||
$"{BackendErrorCodes.NicknameNotUnique} - "
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
NicknameValidationResult.Short => new ValueTask<string>(
|
NicknameValidationResult.Short => new ValueTask<string>(
|
||||||
httpResponse.GetBody<object?>(
|
httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotValid, $"{BackendErrorCodes.NicknameNotValid} - ")
|
||||||
null,
|
|
||||||
BackendErrorCodes.NicknameNotValid,
|
|
||||||
$"{BackendErrorCodes.NicknameNotValid} - "
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
_ => new ValueTask<string>(httpResponse.GetBody(new { status = "ok" })),
|
_ => new ValueTask<string>(httpResponse.GetBody(new { status = "ok" })),
|
||||||
};
|
};
|
||||||
@@ -164,9 +122,7 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetProfileStatus(string url, EmptyRequestData _, MongoId sessionId)
|
public ValueTask<string> GetProfileStatus(string url, EmptyRequestData _, MongoId sessionId)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(profileController.GetProfileStatus(sessionId)));
|
||||||
httpResponse.GetBody(profileController.GetProfileStatus(sessionId))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -174,60 +130,36 @@ public class ProfileCallbacks(
|
|||||||
/// Called when viewing another players profile
|
/// Called when viewing another players profile
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetOtherProfile(
|
public ValueTask<string> GetOtherProfile(string url, GetOtherProfileRequest request, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetOtherProfileRequest request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(profileController.GetOtherProfile(sessionID, request)));
|
||||||
httpResponse.GetBody(profileController.GetOtherProfile(sessionID, request))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/profile/settings
|
/// Handle client/profile/settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetProfileSettings(
|
public ValueTask<string> GetProfileSettings(string url, GetProfileSettingsRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetProfileSettingsRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(profileController.SetChosenProfileIcon(sessionID, info)));
|
||||||
httpResponse.GetBody(profileController.SetChosenProfileIcon(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/search
|
/// Handle client/game/profile/search
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SearchProfiles(
|
public ValueTask<string> SearchProfiles(string url, SearchProfilesRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SearchProfilesRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.GetBody(profileController.SearchProfiles(info, sessionID)));
|
||||||
httpResponse.GetBody(profileController.SearchProfiles(info, sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle launcher/profile/info
|
/// Handle launcher/profile/info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetMiniProfile(
|
public ValueTask<string> GetMiniProfile(string url, GetMiniProfileRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetMiniProfileRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponse.NoBody(profileController.GetMiniProfile(sessionID)));
|
||||||
httpResponse.NoBody(profileController.GetMiniProfile(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -22,11 +22,7 @@ public class QuestCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ChangeRepeatableQuest(
|
public ItemEventRouterResponse ChangeRepeatableQuest(PmcData pmcData, RepeatableQuestChangeRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
RepeatableQuestChangeRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return repeatableQuestController.ChangeRepeatableQuest(pmcData, info, sessionID);
|
return repeatableQuestController.ChangeRepeatableQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -38,11 +34,7 @@ public class QuestCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse AcceptQuest(
|
public ItemEventRouterResponse AcceptQuest(PmcData pmcData, AcceptQuestRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AcceptQuestRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (info.Type == "repeatable")
|
if (info.Type == "repeatable")
|
||||||
{
|
{
|
||||||
@@ -59,11 +51,7 @@ public class QuestCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse CompleteQuest(
|
public ItemEventRouterResponse CompleteQuest(PmcData pmcData, CompleteQuestRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
CompleteQuestRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return questController.CompleteQuest(pmcData, info, sessionID);
|
return questController.CompleteQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -75,11 +63,7 @@ public class QuestCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse HandoverQuest(
|
public ItemEventRouterResponse HandoverQuest(PmcData pmcData, HandoverQuestRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HandoverQuestRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return questController.HandoverQuest(pmcData, info, sessionID);
|
return questController.HandoverQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -93,9 +77,7 @@ public class QuestCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ListQuests(string url, ListQuestsRequestData info, MongoId sessionID)
|
public ValueTask<string> ListQuests(string url, ListQuestsRequestData info, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(questController.GetClientQuests(sessionID)));
|
||||||
httpResponseUtil.GetBody(questController.GetClientQuests(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -107,8 +89,6 @@ public class QuestCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ActivityPeriods(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> ActivityPeriods(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(repeatableQuestController.GetClientRepeatableQuests(sessionID)));
|
||||||
httpResponseUtil.GetBody(repeatableQuestController.GetClientRepeatableQuests(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ public class RagfairCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> Search(string url, SearchRequestData info, MongoId sessionID)
|
public ValueTask<string> Search(string url, SearchRequestData info, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(ragfairController.GetOffers(sessionID, info)));
|
||||||
httpResponseUtil.GetBody(ragfairController.GetOffers(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -74,15 +72,9 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetMarketPrice(
|
public ValueTask<string> GetMarketPrice(string url, GetMarketPriceRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetMarketPriceRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(ragfairController.GetItemMinAvgMaxFleaPriceValues(info)));
|
||||||
httpResponseUtil.GetBody(ragfairController.GetItemMinAvgMaxFleaPriceValues(info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -92,11 +84,7 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse AddOffer(
|
public ItemEventRouterResponse AddOffer(PmcData pmcData, AddOfferRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AddOfferRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return ragfairController.AddPlayerOffer(pmcData, info, sessionID);
|
return ragfairController.AddPlayerOffer(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -108,11 +96,7 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse RemoveOffer(
|
public ItemEventRouterResponse RemoveOffer(PmcData pmcData, RemoveOfferRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
RemoveOfferRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return ragfairController.FlagOfferForRemoval(info.OfferId, sessionID);
|
return ragfairController.FlagOfferForRemoval(info.OfferId, sessionID);
|
||||||
}
|
}
|
||||||
@@ -124,11 +108,7 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ExtendOffer(
|
public ItemEventRouterResponse ExtendOffer(PmcData pmcData, ExtendOfferRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ExtendOfferRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return ragfairController.ExtendOffer(info, sessionID);
|
return ragfairController.ExtendOffer(info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -143,9 +123,7 @@ public class RagfairCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetFleaPrices(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetFleaPrices(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(ragfairController.GetAllFleaPrices()));
|
||||||
httpResponseUtil.GetBody(ragfairController.GetAllFleaPrices())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -155,20 +133,12 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SendReport(
|
public ValueTask<string> SendReport(string url, SendRagfairReportRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
SendRagfairReportRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> StorePlayerOfferTaxAmount(
|
public ValueTask<string> StorePlayerOfferTaxAmount(string url, StorePlayerOfferTaxAmountRequestData info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
StorePlayerOfferTaxAmountRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ragfairTaxService.StoreClientOfferTaxValue(sessionID, info);
|
ragfairTaxService.StoreClientOfferTaxValue(sessionID, info);
|
||||||
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
return new ValueTask<string>(httpResponseUtil.NullResponse());
|
||||||
@@ -181,14 +151,8 @@ public class RagfairCallbacks(
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetFleaOfferById(
|
public ValueTask<string> GetFleaOfferById(string url, GetRagfairOfferByIdRequest info, MongoId sessionID)
|
||||||
string url,
|
|
||||||
GetRagfairOfferByIdRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(ragfairController.GetOfferByInternalId(sessionID, info)));
|
||||||
httpResponseUtil.GetBody(ragfairController.GetOfferByInternalId(sessionID, info))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ public class RepairCallbacks(RepairController _repairController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse TraderRepair(
|
public ItemEventRouterResponse TraderRepair(PmcData pmcData, TraderRepairActionDataRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
TraderRepairActionDataRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return _repairController.TraderRepair(sessionID, info, pmcData);
|
return _repairController.TraderRepair(sessionID, info, pmcData);
|
||||||
}
|
}
|
||||||
@@ -35,11 +31,7 @@ public class RepairCallbacks(RepairController _repairController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse Repair(
|
public ItemEventRouterResponse Repair(PmcData pmcData, RepairActionDataRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
RepairActionDataRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return _repairController.RepairWithKit(sessionID, info, pmcData);
|
return _repairController.RepairWithKit(sessionID, info, pmcData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(TypePriority = OnLoadOrder.SaveCallbacks)]
|
[Injectable(TypePriority = OnLoadOrder.SaveCallbacks)]
|
||||||
public class SaveCallbacks(
|
public class SaveCallbacks(SaveServer saveServer, ConfigServer configServer, BackupService backupService) : IOnLoad, IOnUpdate
|
||||||
SaveServer saveServer,
|
|
||||||
ConfigServer configServer,
|
|
||||||
BackupService backupService
|
|
||||||
) : IOnLoad, IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly CoreConfig _coreConfig = configServer.GetConfig<CoreConfig>();
|
private readonly CoreConfig _coreConfig = configServer.GetConfig<CoreConfig>();
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ public class TradeCallbacks(TradeController tradeController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ProcessTrade(
|
public ItemEventRouterResponse ProcessTrade(PmcData pmcData, ProcessBaseTradeRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ProcessBaseTradeRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return tradeController.ConfirmTrading(pmcData, info, sessionID);
|
return tradeController.ConfirmTrading(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -33,11 +29,7 @@ public class TradeCallbacks(TradeController tradeController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ProcessRagfairTrade(
|
public ItemEventRouterResponse ProcessRagfairTrade(PmcData pmcData, ProcessRagfairTradeRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ProcessRagfairTradeRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return tradeController.ConfirmRagfairTrading(pmcData, info, sessionID);
|
return tradeController.ConfirmRagfairTrading(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -49,11 +41,7 @@ public class TradeCallbacks(TradeController tradeController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SellAllFromSavage(
|
public ItemEventRouterResponse SellAllFromSavage(PmcData pmcData, SellScavItemsToFenceRequestData info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
SellScavItemsToFenceRequestData info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return tradeController.SellScavItemsToFence(pmcData, info, sessionID);
|
return tradeController.SellScavItemsToFence(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(TypePriority = OnLoadOrder.TraderCallbacks)]
|
[Injectable(TypePriority = OnLoadOrder.TraderCallbacks)]
|
||||||
public class TraderCallbacks(
|
public class TraderCallbacks(HttpResponseUtil httpResponseUtil, TraderController traderController, ConfigServer configServer)
|
||||||
HttpResponseUtil httpResponseUtil,
|
: IOnLoad,
|
||||||
TraderController traderController,
|
IOnUpdate
|
||||||
ConfigServer configServer
|
|
||||||
) : IOnLoad, IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly TraderConfig _traderConfig = configServer.GetConfig<TraderConfig>();
|
private readonly TraderConfig _traderConfig = configServer.GetConfig<TraderConfig>();
|
||||||
|
|
||||||
@@ -36,9 +34,7 @@ public class TraderCallbacks(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ValueTask<string> GetTraderSettings(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetTraderSettings(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(traderController.GetAllTraders(sessionID)));
|
||||||
httpResponseUtil.GetBody(traderController.GetAllTraders(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -47,9 +43,7 @@ public class TraderCallbacks(
|
|||||||
public ValueTask<string> GetTrader(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetTrader(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
var traderID = url.Replace("/client/trading/api/getTrader/", "");
|
var traderID = url.Replace("/client/trading/api/getTrader/", "");
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(traderController.GetTrader(sessionID, traderID)));
|
||||||
httpResponseUtil.GetBody(traderController.GetTrader(sessionID, traderID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -59,9 +53,7 @@ public class TraderCallbacks(
|
|||||||
public ValueTask<string> GetAssort(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetAssort(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
var traderID = url.Replace("/client/trading/api/getTraderAssort/", "");
|
var traderID = url.Replace("/client/trading/api/getTraderAssort/", "");
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(traderController.GetAssort(sessionID, traderID)));
|
||||||
httpResponseUtil.GetBody(traderController.GetAssort(sessionID, traderID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class WeatherCallbacks(
|
public class WeatherCallbacks(HttpResponseUtil httpResponseUtil, WeatherController weatherController)
|
||||||
HttpResponseUtil httpResponseUtil,
|
|
||||||
WeatherController weatherController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/weather
|
/// Handle client/weather
|
||||||
@@ -33,8 +30,6 @@ public class WeatherCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocalWeather(string url, EmptyRequestData _, MongoId sessionID)
|
public ValueTask<string> GetLocalWeather(string url, EmptyRequestData _, MongoId sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(
|
return new ValueTask<string>(httpResponseUtil.GetBody(weatherController.GenerateLocal(sessionID)));
|
||||||
httpResponseUtil.GetBody(weatherController.GenerateLocal(sessionID))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ public class WishlistCallbacks(WishlistController wishlistController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse AddToWishlist(
|
public ItemEventRouterResponse AddToWishlist(PmcData pmcData, AddToWishlistRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AddToWishlistRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return wishlistController.AddToWishList(pmcData, info, sessionID);
|
return wishlistController.AddToWishList(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -33,11 +29,7 @@ public class WishlistCallbacks(WishlistController wishlistController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse RemoveFromWishlist(
|
public ItemEventRouterResponse RemoveFromWishlist(PmcData pmcData, RemoveFromWishlistRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
RemoveFromWishlistRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return wishlistController.RemoveFromWishList(pmcData, info, sessionID);
|
return wishlistController.RemoveFromWishList(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -49,11 +41,7 @@ public class WishlistCallbacks(WishlistController wishlistController)
|
|||||||
/// <param name="info"></param>
|
/// <param name="info"></param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ChangeWishlistItemCategory(
|
public ItemEventRouterResponse ChangeWishlistItemCategory(PmcData pmcData, ChangeWishlistItemCategoryRequest info, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ChangeWishlistItemCategoryRequest info,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return wishlistController.ChangeWishListItemCategory(pmcData, info, sessionID);
|
return wishlistController.ChangeWishListItemCategory(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class AchievementController(
|
public class AchievementController(ProfileHelper profileHelper, DatabaseService databaseService, ConfigServer configServer)
|
||||||
ProfileHelper profileHelper,
|
|
||||||
DatabaseService databaseService,
|
|
||||||
ConfigServer configServer
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
protected readonly CoreConfig coreConfig = configServer.GetConfig<CoreConfig>();
|
protected readonly CoreConfig coreConfig = configServer.GetConfig<CoreConfig>();
|
||||||
|
|
||||||
@@ -37,11 +33,7 @@ public class AchievementController(
|
|||||||
var stats = new Dictionary<string, int>();
|
var stats = new Dictionary<string, int>();
|
||||||
var profiles = profileHelper
|
var profiles = profileHelper
|
||||||
.GetProfiles()
|
.GetProfiles()
|
||||||
.Where(kvp =>
|
.Where(kvp => !coreConfig.Features.AchievementProfileIdBlacklist.Contains(kvp.Value.ProfileInfo.ProfileId))
|
||||||
!coreConfig.Features.AchievementProfileIdBlacklist.Contains(
|
|
||||||
kvp.Value.ProfileInfo.ProfileId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
|
|
||||||
var achievements = databaseService.GetAchievements();
|
var achievements = databaseService.GetAchievements();
|
||||||
@@ -70,8 +62,7 @@ public class AchievementController(
|
|||||||
var percentage = 0;
|
var percentage = 0;
|
||||||
if (profiles.Count > 0)
|
if (profiles.Count > 0)
|
||||||
{
|
{
|
||||||
percentage = (int)
|
percentage = (int)Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
|
||||||
Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.Add(achievementId, percentage);
|
stats.Add(achievementId, percentage);
|
||||||
|
|||||||
@@ -51,9 +51,7 @@ public class BotController(
|
|||||||
{
|
{
|
||||||
if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
|
if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("bot-bot_preset_count_value_missing", type));
|
||||||
_serverLocalisationService.GetText("bot-bot_preset_count_value_missing", type)
|
|
||||||
);
|
|
||||||
|
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
@@ -80,38 +78,23 @@ public class BotController(
|
|||||||
/// <param name="diffLevel">difficulty level server requested settings for</param>
|
/// <param name="diffLevel">difficulty level server requested settings for</param>
|
||||||
/// <param name="ignoreRaidSettings">OPTIONAL - should raid settings chosen pre-raid be ignored</param>
|
/// <param name="ignoreRaidSettings">OPTIONAL - should raid settings chosen pre-raid be ignored</param>
|
||||||
/// <returns>Difficulty object</returns>
|
/// <returns>Difficulty object</returns>
|
||||||
public DifficultyCategories GetBotDifficulty(
|
public DifficultyCategories GetBotDifficulty(MongoId sessionId, string type, string diffLevel, bool ignoreRaidSettings = false)
|
||||||
MongoId sessionId,
|
|
||||||
string type,
|
|
||||||
string diffLevel,
|
|
||||||
bool ignoreRaidSettings = false
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var difficulty = diffLevel.ToLowerInvariant();
|
var difficulty = diffLevel.ToLowerInvariant();
|
||||||
|
|
||||||
var raidConfig = _profileActivityService
|
var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId).RaidConfiguration;
|
||||||
.GetProfileActivityRaidData(sessionId)
|
|
||||||
.RaidConfiguration;
|
|
||||||
|
|
||||||
if (!(raidConfig != null || ignoreRaidSettings))
|
if (!(raidConfig != null || ignoreRaidSettings))
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION"));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"bot-missing_application_context",
|
|
||||||
"RAID_CONFIGURATION"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check value chosen in pre-raid difficulty dropdown
|
// Check value chosen in pre-raid difficulty dropdown
|
||||||
// If value is not 'asonline', change requested difficulty to be what was chosen in dropdown
|
// If value is not 'asonline', change requested difficulty to be what was chosen in dropdown
|
||||||
var botDifficultyDropDownValue =
|
var botDifficultyDropDownValue = raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLowerInvariant() ?? "asonline";
|
||||||
raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLowerInvariant() ?? "asonline";
|
|
||||||
if (botDifficultyDropDownValue != "asonline")
|
if (botDifficultyDropDownValue != "asonline")
|
||||||
{
|
{
|
||||||
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(
|
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
|
||||||
botDifficultyDropDownValue
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var botDb = _databaseService.GetBots();
|
var botDb = _databaseService.GetBots();
|
||||||
@@ -147,9 +130,7 @@ public class BotController(
|
|||||||
result[botTypeLower] = result[Roles.Assault];
|
result[botTypeLower] = result[Roles.Assault];
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug($"Unable to find bot: {botTypeLower} in db, copying: '{Roles.Assault}'");
|
||||||
$"Unable to find bot: {botTypeLower} in db, copying: '{Roles.Assault}'"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -158,9 +139,7 @@ public class BotController(
|
|||||||
if (botDetails?.BotDifficulty is null)
|
if (botDetails?.BotDifficulty is null)
|
||||||
{
|
{
|
||||||
// Bot has no difficulty values, skip
|
// Bot has no difficulty values, skip
|
||||||
_logger.Warning(
|
_logger.Warning($"Unable to find bot: {botTypeLower} difficulty values in db, skipping");
|
||||||
$"Unable to find bot: {botTypeLower} difficulty values in db, skipping"
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,11 +153,7 @@ public class BotController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/hard/impossible
|
// Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/hard/impossible
|
||||||
result[botNameKey]
|
result[botNameKey].TryAdd(difficultyName, GetBotDifficulty(string.Empty, botNameKey, difficultyName, true));
|
||||||
.TryAdd(
|
|
||||||
difficultyName,
|
|
||||||
GetBotDifficulty(string.Empty, botNameKey, difficultyName, true)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,17 +180,11 @@ public class BotController(
|
|||||||
/// <param name="pmcProfile">Player generating bots</param>
|
/// <param name="pmcProfile">Player generating bots</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>List of generated bots</returns>
|
/// <returns>List of generated bots</returns>
|
||||||
protected List<BotBase> GenerateBotWaves(
|
protected List<BotBase> GenerateBotWaves(GenerateBotsRequestData request, PmcData? pmcProfile, MongoId sessionId)
|
||||||
GenerateBotsRequestData request,
|
|
||||||
PmcData? pmcProfile,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var generatedBotList = new List<BotBase>();
|
var generatedBotList = new List<BotBase>();
|
||||||
var raidSettings = GetMostRecentRaidSettings(sessionId);
|
var raidSettings = GetMostRecentRaidSettings(sessionId);
|
||||||
var allPmcsHaveSameNameAsPlayer = _randomUtil.GetChance100(
|
var allPmcsHaveSameNameAsPlayer = _randomUtil.GetChance100(_pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance);
|
||||||
_pmcConfig.AllPMCsHavePlayerNameWithRandomPrefixChance
|
|
||||||
);
|
|
||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
// Map conditions to promises for bot generation
|
// Map conditions to promises for bot generation
|
||||||
@@ -232,12 +201,7 @@ public class BotController(
|
|||||||
raidSettings
|
raidSettings
|
||||||
);
|
);
|
||||||
|
|
||||||
GenerateBotWave(
|
GenerateBotWave(condition, botWaveGenerationDetails, generatedBotList, sessionId);
|
||||||
condition,
|
|
||||||
botWaveGenerationDetails,
|
|
||||||
generatedBotList,
|
|
||||||
sessionId
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.ToArray()
|
.ToArray()
|
||||||
@@ -247,9 +211,7 @@ public class BotController(
|
|||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
|
||||||
$"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return generatedBotList;
|
return generatedBotList;
|
||||||
@@ -270,17 +232,12 @@ public class BotController(
|
|||||||
MongoId sessionId
|
MongoId sessionId
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var isEventBot = generateRequest.Role?.Contains(
|
var isEventBot = generateRequest.Role?.Contains("event", StringComparison.OrdinalIgnoreCase);
|
||||||
"event",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
);
|
|
||||||
if (isEventBot.GetValueOrDefault(false))
|
if (isEventBot.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
// Add eventRole data + reassign role property to be base type
|
// Add eventRole data + reassign role property to be base type
|
||||||
botGenerationDetails.EventRole = generateRequest.Role;
|
botGenerationDetails.EventRole = generateRequest.Role;
|
||||||
botGenerationDetails.Role = _seasonalEventService.GetBaseRoleForEventBot(
|
botGenerationDetails.Role = _seasonalEventService.GetBaseRoleForEventBot(botGenerationDetails.EventRole);
|
||||||
botGenerationDetails.EventRole
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var role = botGenerationDetails.EventRole ?? botGenerationDetails.Role;
|
var role = botGenerationDetails.EventRole ?? botGenerationDetails.Role;
|
||||||
@@ -308,16 +265,11 @@ public class BotController(
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bot = _botGenerator.PrepareAndGenerateBot(
|
bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(botGenerationDetails));
|
||||||
sessionId,
|
|
||||||
_cloner.Clone(botGenerationDetails)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error($"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}");
|
||||||
$"Failed to generate bot: {botGenerationDetails.Role} #{i + 1}: {e.Message} {e.StackTrace}"
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,17 +305,11 @@ public class BotController(
|
|||||||
/// <returns>GetRaidConfigurationRequestData if it exists</returns>
|
/// <returns>GetRaidConfigurationRequestData if it exists</returns>
|
||||||
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(MongoId sessionId)
|
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(MongoId sessionId)
|
||||||
{
|
{
|
||||||
var raidConfiguration = _profileActivityService
|
var raidConfiguration = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
|
||||||
.GetProfileActivityRaidData(sessionId)
|
|
||||||
?.RaidConfiguration;
|
|
||||||
|
|
||||||
if (raidConfiguration is null)
|
if (raidConfiguration is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext"));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"bot-unable_to_load_raid_settings_from_appcontext"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return raidConfiguration;
|
return raidConfiguration;
|
||||||
@@ -376,10 +322,7 @@ public class BotController(
|
|||||||
/// <returns>MinMax values</returns>
|
/// <returns>MinMax values</returns>
|
||||||
protected MinMax<int> GetPmcLevelRangeForMap(string? location)
|
protected MinMax<int> GetPmcLevelRangeForMap(string? location)
|
||||||
{
|
{
|
||||||
return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(
|
return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(location?.ToLowerInvariant() ?? "", null);
|
||||||
location?.ToLowerInvariant() ?? "",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -402,18 +345,13 @@ public class BotController(
|
|||||||
return new BotGenerationDetails
|
return new BotGenerationDetails
|
||||||
{
|
{
|
||||||
IsPmc = generateAsPmc,
|
IsPmc = generateAsPmc,
|
||||||
Side = generateAsPmc
|
Side = generateAsPmc ? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty) : "Savage",
|
||||||
? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty)
|
|
||||||
: "Savage",
|
|
||||||
Role = condition.Role,
|
Role = condition.Role,
|
||||||
PlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
PlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
PlayerName = pmcProfile?.Info?.Nickname,
|
PlayerName = pmcProfile?.Info?.Nickname,
|
||||||
BotRelativeLevelDeltaMax = _pmcConfig.BotRelativeLevelDeltaMax,
|
BotRelativeLevelDeltaMax = _pmcConfig.BotRelativeLevelDeltaMax,
|
||||||
BotRelativeLevelDeltaMin = _pmcConfig.BotRelativeLevelDeltaMin,
|
BotRelativeLevelDeltaMin = _pmcConfig.BotRelativeLevelDeltaMin,
|
||||||
BotCountToGenerate = Math.Max(
|
BotCountToGenerate = Math.Max(GetBotPresetGenerationLimit(condition.Role), condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
|
||||||
GetBotPresetGenerationLimit(condition.Role),
|
|
||||||
condition.Limit
|
|
||||||
), // Choose largest between value passed in from request vs what's in bot.config
|
|
||||||
BotDifficulty = condition.Difficulty,
|
BotDifficulty = condition.Difficulty,
|
||||||
LocationSpecificPmcLevelOverride = GetPmcLevelRangeForMap(raidSettings?.Location), // Min/max levels for PMCs to generate within
|
LocationSpecificPmcLevelOverride = GetPmcLevelRangeForMap(raidSettings?.Location), // Min/max levels for PMCs to generate within
|
||||||
IsPlayerScav = false,
|
IsPlayerScav = false,
|
||||||
@@ -437,12 +375,7 @@ public class BotController(
|
|||||||
|
|
||||||
if (location == "default")
|
if (location == "default")
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("bot-no_bot_cap_found_for_location", location.ToLowerInvariant()));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"bot-no_bot_cap_found_for_location",
|
|
||||||
location.ToLowerInvariant()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return maxCap;
|
return maxCap;
|
||||||
|
|||||||
@@ -41,32 +41,24 @@ public class BuildController(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Ensure the secure container in the default presets match what the player has equipped
|
// Ensure the secure container in the default presets match what the player has equipped
|
||||||
var defaultEquipmentPresetsClone = cloner
|
var defaultEquipmentPresetsClone = cloner.Clone(databaseService.GetTemplates().DefaultEquipmentPresets).ToList();
|
||||||
.Clone(databaseService.GetTemplates().DefaultEquipmentPresets)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Get players secure container
|
// Get players secure container
|
||||||
var playerSecureContainer =
|
var playerSecureContainer = profile.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x =>
|
||||||
profile.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x =>
|
x.SlotId == secureContainerSlotId
|
||||||
x.SlotId == secureContainerSlotId
|
);
|
||||||
);
|
|
||||||
|
|
||||||
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone
|
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone
|
||||||
.FirstOrDefault()
|
.FirstOrDefault()
|
||||||
?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
|
?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
|
||||||
|
|
||||||
if (
|
if (playerSecureContainer is not null && playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template)
|
||||||
playerSecureContainer is not null
|
|
||||||
&& playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template
|
|
||||||
)
|
|
||||||
// Default equipment presets' secure container tpl doesn't match players secure container tpl
|
// Default equipment presets' secure container tpl doesn't match players secure container tpl
|
||||||
{
|
{
|
||||||
foreach (var defaultPreset in defaultEquipmentPresetsClone)
|
foreach (var defaultPreset in defaultEquipmentPresetsClone)
|
||||||
{
|
{
|
||||||
// Find presets secure container
|
// Find presets secure container
|
||||||
var secureContainer = defaultPreset.Items?.FirstOrDefault(item =>
|
var secureContainer = defaultPreset.Items?.FirstOrDefault(item => item.SlotId == secureContainerSlotId);
|
||||||
item.SlotId == secureContainerSlotId
|
|
||||||
);
|
|
||||||
if (secureContainer is not null)
|
if (secureContainer is not null)
|
||||||
{
|
{
|
||||||
secureContainer.Template = playerSecureContainer.Template;
|
secureContainer.Template = playerSecureContainer.Template;
|
||||||
@@ -133,9 +125,7 @@ public class BuildController(
|
|||||||
var profile = profileHelper.GetFullProfile(sessionID);
|
var profile = profileHelper.GetFullProfile(sessionID);
|
||||||
var pmcData = profile.CharacterData.PmcData;
|
var pmcData = profile.CharacterData.PmcData;
|
||||||
|
|
||||||
var existingSavedEquipmentBuilds = saveServer
|
var existingSavedEquipmentBuilds = saveServer.GetProfile(sessionID).UserBuildData.EquipmentBuilds;
|
||||||
.GetProfile(sessionID)
|
|
||||||
.UserBuildData.EquipmentBuilds;
|
|
||||||
|
|
||||||
// Replace duplicate ID's. The first item is the base item.
|
// Replace duplicate ID's. The first item is the base item.
|
||||||
// Root ID and the base item ID need to match.
|
// Root ID and the base item ID need to match.
|
||||||
@@ -150,9 +140,7 @@ public class BuildController(
|
|||||||
Items = request.Items.ToList(),
|
Items = request.Items.ToList(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build =>
|
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build => build.Name == request.Name || build.Id == request.Id);
|
||||||
build.Name == request.Name || build.Id == request.Id
|
|
||||||
);
|
|
||||||
if (existingBuild is not null)
|
if (existingBuild is not null)
|
||||||
{
|
{
|
||||||
// Already exists, replace
|
// Already exists, replace
|
||||||
@@ -198,9 +186,7 @@ public class BuildController(
|
|||||||
profile.UserBuildData.MagazineBuilds ??= [];
|
profile.UserBuildData.MagazineBuilds ??= [];
|
||||||
|
|
||||||
// Check if template with desired name already exists and remove it
|
// Check if template with desired name already exists and remove it
|
||||||
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item =>
|
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item => item.Name == request.Name);
|
||||||
item.Name == request.Name
|
|
||||||
);
|
|
||||||
if (magazineBuildToRemove is not null)
|
if (magazineBuildToRemove is not null)
|
||||||
{
|
{
|
||||||
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
|
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
|
||||||
@@ -224,9 +210,7 @@ public class BuildController(
|
|||||||
var magazineBuilds = profile.UserBuildData.MagazineBuilds;
|
var magazineBuilds = profile.UserBuildData.MagazineBuilds;
|
||||||
|
|
||||||
// Check for id in weapon array first
|
// Check for id in weapon array first
|
||||||
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild =>
|
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild => weaponBuild.Id == idToRemove);
|
||||||
weaponBuild.Id == idToRemove
|
|
||||||
);
|
|
||||||
if (matchingWeaponBuild is not null)
|
if (matchingWeaponBuild is not null)
|
||||||
{
|
{
|
||||||
weaponBuilds.Remove(matchingWeaponBuild);
|
weaponBuilds.Remove(matchingWeaponBuild);
|
||||||
@@ -235,9 +219,7 @@ public class BuildController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Id not found in weapons, try equipment
|
// Id not found in weapons, try equipment
|
||||||
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild =>
|
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild => equipmentBuild.Id == idToRemove);
|
||||||
equipmentBuild.Id == idToRemove
|
|
||||||
);
|
|
||||||
if (matchingEquipmentBuild is not null)
|
if (matchingEquipmentBuild is not null)
|
||||||
{
|
{
|
||||||
equipmentBuilds.Remove(matchingEquipmentBuild);
|
equipmentBuilds.Remove(matchingEquipmentBuild);
|
||||||
@@ -246,9 +228,7 @@ public class BuildController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Id not found in weapons/equipment, try mags
|
// Id not found in weapons/equipment, try mags
|
||||||
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild =>
|
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild => magBuild.Id == idToRemove);
|
||||||
magBuild.Id == idToRemove
|
|
||||||
);
|
|
||||||
if (matchingMagazineBuild is not null)
|
if (matchingMagazineBuild is not null)
|
||||||
{
|
{
|
||||||
magazineBuilds.Remove(matchingMagazineBuild);
|
magazineBuilds.Remove(matchingMagazineBuild);
|
||||||
@@ -257,8 +237,6 @@ public class BuildController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not found in weapons,equipment or magazines, not good
|
// Not found in weapons,equipment or magazines, not good
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("build-unable_to_delete_preset", idToRemove));
|
||||||
serverLocalisationService.GetText("build-unable_to_delete_preset", idToRemove)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,18 +42,12 @@ public class CustomizationController(
|
|||||||
|
|
||||||
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId));
|
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId));
|
||||||
matchingSuits = matchingSuits?.Where(s =>
|
matchingSuits = matchingSuits?.Where(s =>
|
||||||
clothing[s.SuiteId]?.Properties?.Side?.Contains(pmcData?.Info?.Side ?? string.Empty)
|
clothing[s.SuiteId]?.Properties?.Side?.Contains(pmcData?.Info?.Side ?? string.Empty) ?? false
|
||||||
?? false
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (matchingSuits == null)
|
if (matchingSuits == null)
|
||||||
{
|
{
|
||||||
throw new Exception(
|
throw new Exception(serverLocalisationService.GetText("customisation-unable_to_get_trader_suits", traderId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"customisation-unable_to_get_trader_suits",
|
|
||||||
traderId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchingSuits.ToList();
|
return matchingSuits.ToList();
|
||||||
@@ -67,23 +61,14 @@ public class CustomizationController(
|
|||||||
/// <param name="buyClothingRequest">Request object</param>
|
/// <param name="buyClothingRequest">Request object</param>
|
||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse BuyCustomisation(
|
public ItemEventRouterResponse BuyCustomisation(PmcData pmcData, BuyClothingRequestData buyClothingRequest, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
BuyClothingRequestData buyClothingRequest,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
var traderOffer = GetTraderClothingOffer(sessionId, buyClothingRequest.Offer);
|
var traderOffer = GetTraderClothingOffer(sessionId, buyClothingRequest.Offer);
|
||||||
if (traderOffer is null)
|
if (traderOffer is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("customisation-unable_to_find_suit_by_id", buyClothingRequest.Offer));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"customisation-unable_to_find_suit_by_id",
|
|
||||||
buyClothingRequest.Offer
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +115,7 @@ public class CustomizationController(
|
|||||||
var fullProfile = profileHelper.GetFullProfile(sessionId);
|
var fullProfile = profileHelper.GetFullProfile(sessionId);
|
||||||
|
|
||||||
// Check if clothing can be found by id
|
// Check if clothing can be found by id
|
||||||
return fullProfile.CustomisationUnlocks.Exists(customisation =>
|
return fullProfile.CustomisationUnlocks.Exists(customisation => Equals(customisation.Id, suitId));
|
||||||
Equals(customisation.Id, suitId)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -146,12 +129,7 @@ public class CustomizationController(
|
|||||||
var foundSuit = GetAllTraderSuits(sessionId).FirstOrDefault(s => s.Id == offerId);
|
var foundSuit = GetAllTraderSuits(sessionId).FirstOrDefault(s => s.Id == offerId);
|
||||||
if (foundSuit is null)
|
if (foundSuit is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("customisation-unable_to_find_suit_with_id", offerId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"customisation-unable_to_find_suit_with_id",
|
|
||||||
offerId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundSuit;
|
return foundSuit;
|
||||||
@@ -180,14 +158,7 @@ public class CustomizationController(
|
|||||||
{
|
{
|
||||||
var options = new ProcessBuyTradeRequestData
|
var options = new ProcessBuyTradeRequestData
|
||||||
{
|
{
|
||||||
SchemeItems =
|
SchemeItems = [new IdWithCount { Count = inventoryItemToProcess.Count.Value, Id = inventoryItemToProcess.Id }],
|
||||||
[
|
|
||||||
new IdWithCount
|
|
||||||
{
|
|
||||||
Count = inventoryItemToProcess.Count.Value,
|
|
||||||
Id = inventoryItemToProcess.Id,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TransactionId = Traders.RAGMAN,
|
TransactionId = Traders.RAGMAN,
|
||||||
Action = "BuyCustomization",
|
Action = "BuyCustomization",
|
||||||
Type = "",
|
Type = "",
|
||||||
@@ -212,10 +183,7 @@ public class CustomizationController(
|
|||||||
|
|
||||||
foreach (var (traderId, trader) in traders)
|
foreach (var (traderId, trader) in traders)
|
||||||
{
|
{
|
||||||
if (
|
if (trader.Base?.CustomizationSeller is not null && trader.Base.CustomizationSeller.Value)
|
||||||
trader.Base?.CustomizationSeller is not null
|
|
||||||
&& trader.Base.CustomizationSeller.Value
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
result.AddRange(GetTraderSuits(traderId, sessionId));
|
result.AddRange(GetTraderSuits(traderId, sessionId));
|
||||||
}
|
}
|
||||||
@@ -241,9 +209,7 @@ public class CustomizationController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<CustomisationStorage> GetCustomisationStorage(MongoId sessionId)
|
public List<CustomisationStorage> GetCustomisationStorage(MongoId sessionId)
|
||||||
{
|
{
|
||||||
var customisationResultsClone = cloner.Clone(
|
var customisationResultsClone = cloner.Clone(databaseService.GetTemplates().CustomisationStorage);
|
||||||
databaseService.GetTemplates().CustomisationStorage
|
|
||||||
);
|
|
||||||
|
|
||||||
var profile = profileHelper.GetFullProfile(sessionId);
|
var profile = profileHelper.GetFullProfile(sessionId);
|
||||||
if (profile is null)
|
if (profile is null)
|
||||||
@@ -263,11 +229,7 @@ public class CustomizationController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse SetCustomisation(
|
public ItemEventRouterResponse SetCustomisation(MongoId sessionId, CustomizationSetRequest request, PmcData pmcData)
|
||||||
MongoId sessionId,
|
|
||||||
CustomizationSetRequest request,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var customisation in request.Customizations)
|
foreach (var customisation in request.Customizations)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,12 +38,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
if (_dialogueChatBots.Any(cb => cb.GetChatBot().Id == chatBot.GetChatBot().Id))
|
if (_dialogueChatBots.Any(cb => cb.GetChatBot().Id == chatBot.GetChatBot().Id))
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("dialog-chatbot_id_already_exists", chatBot.GetChatBot().Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"dialog-chatbot_id_already_exists",
|
|
||||||
chatBot.GetChatBot().Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogueChatBots.Add(chatBot);
|
_dialogueChatBots.Add(chatBot);
|
||||||
@@ -190,11 +185,7 @@ public class DialogueController(
|
|||||||
/// <param name="messageType">What type of message is being sent</param>
|
/// <param name="messageType">What type of message is being sent</param>
|
||||||
/// <param name="sessionId">Player id</param>
|
/// <param name="sessionId">Player id</param>
|
||||||
/// <returns>UserDialogInfo list</returns>
|
/// <returns>UserDialogInfo list</returns>
|
||||||
public virtual List<UserDialogInfo> GetDialogueUsers(
|
public virtual List<UserDialogInfo> GetDialogueUsers(Dialogue? dialog, MessageType? messageType, MongoId sessionId)
|
||||||
Dialogue? dialog,
|
|
||||||
MessageType? messageType,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var profile = saveServer.GetProfile(sessionId);
|
var profile = saveServer.GetProfile(sessionId);
|
||||||
|
|
||||||
@@ -202,9 +193,7 @@ public class DialogueController(
|
|||||||
if (
|
if (
|
||||||
messageType == MessageType.UserMessage
|
messageType == MessageType.UserMessage
|
||||||
&& dialog?.Users is not null
|
&& dialog?.Users is not null
|
||||||
&& dialog.Users.All(userDialog =>
|
&& dialog.Users.All(userDialog => userDialog.Id != profile.CharacterData?.PmcData?.SessionId)
|
||||||
userDialog.Id != profile.CharacterData?.PmcData?.SessionId
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
dialog.Users.Add(
|
dialog.Users.Add(
|
||||||
@@ -218,11 +207,7 @@ public class DialogueController(
|
|||||||
Nickname = profile.CharacterData?.PmcData?.Info?.Nickname,
|
Nickname = profile.CharacterData?.PmcData?.Info?.Nickname,
|
||||||
Side = profile.CharacterData?.PmcData?.Info?.Side,
|
Side = profile.CharacterData?.PmcData?.Info?.Side,
|
||||||
MemberCategory = profile.CharacterData?.PmcData?.Info?.MemberCategory,
|
MemberCategory = profile.CharacterData?.PmcData?.Info?.MemberCategory,
|
||||||
SelectedMemberCategory = profile
|
SelectedMemberCategory = profile.CharacterData?.PmcData?.Info?.SelectedMemberCategory,
|
||||||
.CharacterData
|
|
||||||
?.PmcData
|
|
||||||
?.Info
|
|
||||||
?.SelectedMemberCategory,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -240,10 +225,7 @@ public class DialogueController(
|
|||||||
/// <param name="request">Get dialog request</param>
|
/// <param name="request">Get dialog request</param>
|
||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <returns>GetMailDialogViewResponseData object</returns>
|
/// <returns>GetMailDialogViewResponseData object</returns>
|
||||||
public virtual GetMailDialogViewResponseData GenerateDialogueView(
|
public virtual GetMailDialogViewResponseData GenerateDialogueView(GetMailDialogViewRequestData request, MongoId sessionId)
|
||||||
GetMailDialogViewRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var dialogueId = request.DialogId;
|
var dialogueId = request.DialogId;
|
||||||
var fullProfile = saveServer.GetProfile(sessionId);
|
var fullProfile = saveServer.GetProfile(sessionId);
|
||||||
@@ -279,18 +261,11 @@ public class DialogueController(
|
|||||||
/// <param name="profile">Player profile</param>
|
/// <param name="profile">Player profile</param>
|
||||||
/// <param name="request">get dialog request</param>
|
/// <param name="request">get dialog request</param>
|
||||||
/// <returns>Dialogue</returns>
|
/// <returns>Dialogue</returns>
|
||||||
protected Dialogue GetDialogByIdFromProfile(
|
protected Dialogue GetDialogByIdFromProfile(SptProfile profile, GetMailDialogViewRequestData request)
|
||||||
SptProfile profile,
|
|
||||||
GetMailDialogViewRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (
|
if (profile.DialogueRecords is null || profile.DialogueRecords.ContainsKey(request.DialogId!))
|
||||||
profile.DialogueRecords is null
|
|
||||||
|| profile.DialogueRecords.ContainsKey(request.DialogId!)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return profile.DialogueRecords?[request.DialogId!]
|
return profile.DialogueRecords?[request.DialogId!] ?? throw new NullReferenceException();
|
||||||
?? throw new NullReferenceException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.DialogueRecords[request.DialogId!] = new Dialogue
|
profile.DialogueRecords[request.DialogId!] = new Dialogue
|
||||||
@@ -310,9 +285,7 @@ public class DialogueController(
|
|||||||
|
|
||||||
var dialogue = profile.DialogueRecords[request.DialogId!];
|
var dialogue = profile.DialogueRecords[request.DialogId!];
|
||||||
dialogue.Users = [];
|
dialogue.Users = [];
|
||||||
var chatBot = _dialogueChatBots.FirstOrDefault(cb =>
|
var chatBot = _dialogueChatBots.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId);
|
||||||
cb.GetChatBot().Id == request.DialogId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (chatBot is null)
|
if (chatBot is null)
|
||||||
{
|
{
|
||||||
@@ -331,10 +304,7 @@ public class DialogueController(
|
|||||||
/// <param name="fullProfile">Player profile</param>
|
/// <param name="fullProfile">Player profile</param>
|
||||||
/// <param name="userDialogs">The participants of the mail</param>
|
/// <param name="userDialogs">The participants of the mail</param>
|
||||||
/// <returns>UserDialogInfo list</returns>
|
/// <returns>UserDialogInfo list</returns>
|
||||||
protected List<UserDialogInfo> GetProfilesForMail(
|
protected List<UserDialogInfo> GetProfilesForMail(SptProfile fullProfile, List<UserDialogInfo>? userDialogs)
|
||||||
SptProfile fullProfile,
|
|
||||||
List<UserDialogInfo>? userDialogs
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
List<UserDialogInfo> result = [];
|
List<UserDialogInfo> result = [];
|
||||||
if (userDialogs is null)
|
if (userDialogs is null)
|
||||||
@@ -383,10 +353,7 @@ public class DialogueController(
|
|||||||
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
|
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
|
||||||
foreach (var message in activeMessages)
|
foreach (var message in activeMessages)
|
||||||
{
|
{
|
||||||
if (
|
if (message.HasRewards.GetValueOrDefault(false) && !message.RewardCollected.GetValueOrDefault(false))
|
||||||
message.HasRewards.GetValueOrDefault(false)
|
|
||||||
&& !message.RewardCollected.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
newAttachmentCount++;
|
newAttachmentCount++;
|
||||||
}
|
}
|
||||||
@@ -436,12 +403,7 @@ public class DialogueController(
|
|||||||
var profile = saveServer.GetProfile(sessionId);
|
var profile = saveServer.GetProfile(sessionId);
|
||||||
if (!profile.DialogueRecords.Remove(dialogueId))
|
if (!profile.DialogueRecords.Remove(dialogueId))
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("dialogue-unable_to_find_in_profile", new { sessionId, dialogueId }));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"dialogue-unable_to_find_in_profile",
|
|
||||||
new { sessionId, dialogueId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,12 +418,7 @@ public class DialogueController(
|
|||||||
var dialog = dialogueHelper.GetDialogsForProfile(sessionId).GetValueOrDefault(dialogueId);
|
var dialog = dialogueHelper.GetDialogsForProfile(sessionId).GetValueOrDefault(dialogueId);
|
||||||
if (dialog is null)
|
if (dialog is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("dialogue-unable_to_find_in_profile", new { sessionId, dialogueId }));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"dialogue-unable_to_find_in_profile",
|
|
||||||
new { sessionId, dialogueId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -480,12 +437,7 @@ public class DialogueController(
|
|||||||
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
|
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
|
||||||
if (dialogs.Any() != true)
|
if (dialogs.Any() != true)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("dialogue-unable_to_find_dialogs_in_profile", new { sessionId }));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"dialogue-unable_to_find_dialogs_in_profile",
|
|
||||||
new { sessionId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -504,10 +456,7 @@ public class DialogueController(
|
|||||||
/// <param name="dialogueId">Dialog to get mail attachments from</param>
|
/// <param name="dialogueId">Dialog to get mail attachments from</param>
|
||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <returns>GetAllAttachmentsResponse or null if dialogue doesn't exist</returns>
|
/// <returns>GetAllAttachmentsResponse or null if dialogue doesn't exist</returns>
|
||||||
public virtual GetAllAttachmentsResponse? GetAllAttachments(
|
public virtual GetAllAttachmentsResponse? GetAllAttachments(string dialogueId, MongoId sessionId)
|
||||||
string dialogueId,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
|
var dialogs = dialogueHelper.GetDialogsForProfile(sessionId);
|
||||||
var dialog = dialogs.TryGetValue(dialogueId, out var dialogInfo);
|
var dialog = dialogs.TryGetValue(dialogueId, out var dialogInfo);
|
||||||
@@ -538,16 +487,11 @@ public class DialogueController(
|
|||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual async ValueTask<string> SendMessage(
|
public virtual async ValueTask<string> SendMessage(MongoId sessionId, SendMessageRequest request)
|
||||||
MongoId sessionId,
|
|
||||||
SendMessageRequest request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId, request.Text);
|
mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId, request.Text);
|
||||||
|
|
||||||
var chatBot = _dialogueChatBots.FirstOrDefault(cb =>
|
var chatBot = _dialogueChatBots.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId);
|
||||||
cb.GetChatBot().Id == request.DialogId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (chatBot is not null)
|
if (chatBot is not null)
|
||||||
{
|
{
|
||||||
@@ -619,10 +563,7 @@ public class DialogueController(
|
|||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <param name="request">Sent friend request</param>
|
/// <param name="request">Sent friend request</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual FriendRequestSendResponse SendFriendRequest(
|
public virtual FriendRequestSendResponse SendFriendRequest(MongoId sessionID, FriendRequestData request)
|
||||||
MongoId sessionID,
|
|
||||||
FriendRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// To avoid needing to jump between profiles, auto-accept all friend requests
|
// To avoid needing to jump between profiles, auto-accept all friend requests
|
||||||
var friendProfile = profileHelper.GetFullProfile(request.To.Value);
|
var friendProfile = profileHelper.GetFullProfile(request.To.Value);
|
||||||
@@ -647,9 +588,7 @@ public class DialogueController(
|
|||||||
var notification = new WsFriendsListAccept
|
var notification = new WsFriendsListAccept
|
||||||
{
|
{
|
||||||
EventType = NotificationEventType.friendListRequestAccept,
|
EventType = NotificationEventType.friendListRequestAccept,
|
||||||
Profile = profileHelper.GetChatRoomMemberFromPmcProfile(
|
Profile = profileHelper.GetChatRoomMemberFromPmcProfile(friendProfile.CharacterData.PmcData),
|
||||||
friendProfile.CharacterData.PmcData
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
notificationSendHelper.SendMessage(sessionID, notification);
|
notificationSendHelper.SendMessage(sessionID, notification);
|
||||||
},
|
},
|
||||||
@@ -687,9 +626,7 @@ public class DialogueController(
|
|||||||
var profile = saveServer.GetProfile(sessionId);
|
var profile = saveServer.GetProfile(sessionId);
|
||||||
if (!profile.DialogueRecords.TryGetValue(request.DialogId, out var dialogToClear))
|
if (!profile.DialogueRecords.TryGetValue(request.DialogId, out var dialogToClear))
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}");
|
||||||
$"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,14 +77,8 @@ public class GameController(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<MongoId, int>(
|
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
||||||
new Dictionary<MongoId, int>(),
|
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
||||||
[]
|
|
||||||
);
|
|
||||||
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<MongoId, int>(
|
|
||||||
new Dictionary<MongoId, int>(),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (fullProfile.DialogueRecords is not null)
|
if (fullProfile.DialogueRecords is not null)
|
||||||
{
|
{
|
||||||
@@ -93,9 +87,7 @@ public class GameController(
|
|||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}");
|
||||||
$"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmcProfile = fullProfile.CharacterData.PmcData;
|
var pmcProfile = fullProfile.CharacterData.PmcData;
|
||||||
@@ -122,20 +114,12 @@ public class GameController(
|
|||||||
|
|
||||||
if (pmcProfile.Hideout is not null)
|
if (pmcProfile.Hideout is not null)
|
||||||
{
|
{
|
||||||
profileFixerService.AddMissingHideoutBonusesToProfile(
|
profileFixerService.AddMissingHideoutBonusesToProfile(pmcProfile, databaseService.GetHideout().Areas);
|
||||||
pmcProfile,
|
|
||||||
databaseService.GetHideout().Areas
|
|
||||||
);
|
|
||||||
hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile);
|
hideoutHelper.SetHideoutImprovementsToCompleted(pmcProfile);
|
||||||
pmcProfile.UnlockHideoutWallInProfile();
|
pmcProfile.UnlockHideoutWallInProfile();
|
||||||
|
|
||||||
// Handle if player has been inactive for a long time, catch up on hideout update before the user goes to his hideout
|
// Handle if player has been inactive for a long time, catch up on hideout update before the user goes to his hideout
|
||||||
if (
|
if (!profileActivityService.ActiveWithinLastMinutes(sessionId, _hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes))
|
||||||
!profileActivityService.ActiveWithinLastMinutes(
|
|
||||||
sessionId,
|
|
||||||
_hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
hideoutHelper.UpdatePlayerHideout(sessionId);
|
hideoutHelper.UpdatePlayerHideout(sessionId);
|
||||||
}
|
}
|
||||||
@@ -170,11 +154,8 @@ public class GameController(
|
|||||||
{
|
{
|
||||||
var profile = profileHelper.GetPmcProfile(sessionId);
|
var profile = profileHelper.GetPmcProfile(sessionId);
|
||||||
var gameTime =
|
var gameTime =
|
||||||
profile
|
profile?.Stats?.Eft?.OverallCounters?.Items?.FirstOrDefault(c => c.Key!.Contains("LifeTime") && c.Key.Contains("Pmc"))?.Value
|
||||||
?.Stats?.Eft?.OverallCounters?.Items?.FirstOrDefault(c =>
|
?? 0D;
|
||||||
c.Key!.Contains("LifeTime") && c.Key.Contains("Pmc")
|
|
||||||
)
|
|
||||||
?.Value ?? 0D;
|
|
||||||
|
|
||||||
var config = new GameConfigResponse
|
var config = new GameConfigResponse
|
||||||
{
|
{
|
||||||
@@ -213,11 +194,7 @@ public class GameController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public GameModeResponse GetGameMode(MongoId sessionId, GameModeRequestData requestData)
|
public GameModeResponse GetGameMode(MongoId sessionId, GameModeRequestData requestData)
|
||||||
{
|
{
|
||||||
return new GameModeResponse
|
return new GameModeResponse { GameMode = "pve", BackendUrl = httpServerHelper.GetBackendUrl() };
|
||||||
{
|
|
||||||
GameMode = "pve",
|
|
||||||
BackendUrl = httpServerHelper.GetBackendUrl(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -247,11 +224,7 @@ public class GameController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public CheckVersionResponse GetValidGameVersion(MongoId sessionId)
|
public CheckVersionResponse GetValidGameVersion(MongoId sessionId)
|
||||||
{
|
{
|
||||||
return new CheckVersionResponse
|
return new CheckVersionResponse { IsValid = true, LatestVersion = _coreConfig.CompatibleTarkovVersion };
|
||||||
{
|
|
||||||
IsValid = true,
|
|
||||||
LatestVersion = _coreConfig.CompatibleTarkovVersion,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -294,9 +267,7 @@ public class GameController(
|
|||||||
var botReloadSkill = pmcProfile.GetSkillFromProfile(SkillTypes.BotReload);
|
var botReloadSkill = pmcProfile.GetSkillFromProfile(SkillTypes.BotReload);
|
||||||
if (botReloadSkill?.Progress > 0)
|
if (botReloadSkill?.Progress > 0)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("server_start_player_active_botreload_skill"));
|
||||||
serverLocalisationService.GetText("server_start_player_active_botreload_skill")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,9 +309,7 @@ public class GameController(
|
|||||||
if (pmcProfile.Health?.Energy?.Current - pmcProfile.Health?.Energy?.Maximum <= _deviation)
|
if (pmcProfile.Health?.Energy?.Current - pmcProfile.Health?.Energy?.Maximum <= _deviation)
|
||||||
{
|
{
|
||||||
// Set new value, whatever is smallest
|
// Set new value, whatever is smallest
|
||||||
pmcProfile.Health!.Energy!.Current += Math.Round(
|
pmcProfile.Health!.Energy!.Current += Math.Round(energyRegenPerHour * (diffSeconds!.Value / 3600));
|
||||||
energyRegenPerHour * (diffSeconds!.Value / 3600)
|
|
||||||
);
|
|
||||||
if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum)
|
if (pmcProfile.Health.Energy.Current > pmcProfile.Health.Energy.Maximum)
|
||||||
{
|
{
|
||||||
pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum;
|
pmcProfile.Health.Energy.Current = pmcProfile.Health.Energy.Maximum;
|
||||||
@@ -348,14 +317,9 @@ public class GameController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Player has hydration deficit
|
// Player has hydration deficit
|
||||||
if (
|
if (pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum <= _deviation)
|
||||||
pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum
|
|
||||||
<= _deviation
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
pmcProfile.Health!.Hydration!.Current += Math.Round(
|
pmcProfile.Health!.Hydration!.Current += Math.Round(hydrationRegenPerHour * (diffSeconds!.Value / 3600));
|
||||||
hydrationRegenPerHour * (diffSeconds!.Value / 3600)
|
|
||||||
);
|
|
||||||
if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum)
|
if (pmcProfile.Health.Hydration.Current > pmcProfile.Health.Hydration.Maximum)
|
||||||
{
|
{
|
||||||
pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum;
|
pmcProfile.Health.Hydration.Current = pmcProfile.Health.Hydration.Maximum;
|
||||||
@@ -375,15 +339,9 @@ public class GameController(
|
|||||||
/// <param name="pmcProfile">Player</param>
|
/// <param name="pmcProfile">Player</param>
|
||||||
/// <param name="hpRegenPerHour"></param>
|
/// <param name="hpRegenPerHour"></param>
|
||||||
/// <param name="diffSeconds"></param>
|
/// <param name="diffSeconds"></param>
|
||||||
protected void DecreaseBodyPartEffectTimes(
|
protected void DecreaseBodyPartEffectTimes(PmcData pmcProfile, double hpRegenPerHour, double diffSeconds)
|
||||||
PmcData pmcProfile,
|
|
||||||
double hpRegenPerHour,
|
|
||||||
double diffSeconds
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (
|
foreach (var bodyPart in pmcProfile.Health!.BodyParts!.Select(bodyPartKvP => bodyPartKvP.Value))
|
||||||
var bodyPart in pmcProfile.Health!.BodyParts!.Select(bodyPartKvP => bodyPartKvP.Value)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Check part hp
|
// Check part hp
|
||||||
if (bodyPart.Health!.Current < bodyPart.Health.Maximum)
|
if (bodyPart.Health!.Current < bodyPart.Health.Maximum)
|
||||||
@@ -456,11 +414,7 @@ public class GameController(
|
|||||||
/// <param name="pmcProfile"></param>
|
/// <param name="pmcProfile"></param>
|
||||||
protected void SendMechanicGiftsToNewProfile(PmcData pmcProfile)
|
protected void SendMechanicGiftsToNewProfile(PmcData pmcProfile)
|
||||||
{
|
{
|
||||||
giftService.SendGiftWithSilentReceivedCheck(
|
giftService.SendGiftWithSilentReceivedCheck("MechanicGiftDay1", pmcProfile.SessionId.Value, 1);
|
||||||
"MechanicGiftDay1",
|
|
||||||
pmcProfile.SessionId.Value,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -475,9 +429,7 @@ public class GameController(
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
fullProfile.SptData.Mods.Any(m =>
|
fullProfile.SptData.Mods.Any(m =>
|
||||||
m.Author == mod.ModMetadata.Author
|
m.Author == mod.ModMetadata.Author && m.Version == mod.ModMetadata.Version && m.Name == mod.ModMetadata.Name
|
||||||
&& m.Version == mod.ModMetadata.Version
|
|
||||||
&& m.Name == mod.ModMetadata.Name
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -554,9 +506,7 @@ public class GameController(
|
|||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug($"Profile made with: {fullProfile.SptData?.Version}");
|
logger.Debug($"Profile made with: {fullProfile.SptData?.Version}");
|
||||||
logger.Debug(
|
logger.Debug($"Server version: {ProgramStatics.SPT_VERSION() ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}");
|
||||||
$"Server version: {ProgramStatics.SPT_VERSION() ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}"
|
|
||||||
);
|
|
||||||
logger.Debug($"Debug enabled: {ProgramStatics.DEBUG()}");
|
logger.Debug($"Debug enabled: {ProgramStatics.DEBUG()}");
|
||||||
logger.Debug($"Mods enabled: {ProgramStatics.MODS()}");
|
logger.Debug($"Mods enabled: {ProgramStatics.MODS()}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,24 +34,15 @@ public class HealthController(
|
|||||||
/// <param name="request">Healing request</param>
|
/// <param name="request">Healing request</param>
|
||||||
/// <param name="sessionID">Player id</param>
|
/// <param name="sessionID">Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse OffRaidHeal(
|
public ItemEventRouterResponse OffRaidHeal(PmcData pmcData, OffraidHealRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
OffraidHealRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
// Update medkit used (hpresource)
|
// Update medkit used (hpresource)
|
||||||
var healingItemToUse = pmcData.Inventory.Items.FirstOrDefault(item =>
|
var healingItemToUse = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
|
||||||
item.Id == request.Item
|
|
||||||
);
|
|
||||||
if (healingItemToUse is null)
|
if (healingItemToUse is null)
|
||||||
{
|
{
|
||||||
var errorMessage = serverLocalisationService.GetText(
|
var errorMessage = serverLocalisationService.GetText("health-healing_item_not_found", request.Item);
|
||||||
"health-healing_item_not_found",
|
|
||||||
request.Item
|
|
||||||
);
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
return httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -67,9 +58,7 @@ public class HealthController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get max healing from db
|
// Get max healing from db
|
||||||
var maxHp = itemHelper
|
var maxHp = itemHelper.GetItem(healingItemToUse.Template).Value.Properties.MaxHpResource;
|
||||||
.GetItem(healingItemToUse.Template)
|
|
||||||
.Value.Properties.MaxHpResource;
|
|
||||||
healingItemToUse.Upd.MedKit = new UpdMedKit { HpResource = maxHp - request.Count }; // Subtract amout used from max
|
healingItemToUse.Upd.MedKit = new UpdMedKit { HpResource = maxHp - request.Count }; // Subtract amout used from max
|
||||||
// request.count appears to take into account healing effects removed, e.g. bleeds
|
// request.count appears to take into account healing effects removed, e.g. bleeds
|
||||||
// Salewa heals limb for 20 and fixes light bleed = (20+45 = 65)
|
// Salewa heals limb for 20 and fixes light bleed = (20+45 = 65)
|
||||||
@@ -87,9 +76,7 @@ public class HealthController(
|
|||||||
var bodyPartToHeal = pmcData.Health.BodyParts.GetValueOrDefault(request.Part);
|
var bodyPartToHeal = pmcData.Health.BodyParts.GetValueOrDefault(request.Part);
|
||||||
if (bodyPartToHeal is null)
|
if (bodyPartToHeal is null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}");
|
||||||
$"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -112,12 +99,7 @@ public class HealthController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if healing item removes the effect on limb
|
// Check if healing item removes the effect on limb
|
||||||
if (
|
if (!healItemEffectDetails.TryGetValue(effect, out var matchingEffectFromHealingItem))
|
||||||
!healItemEffectDetails.TryGetValue(
|
|
||||||
effect,
|
|
||||||
out var matchingEffectFromHealingItem
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Healing item doesn't have matching effect, it doesn't remove the effect
|
// Healing item doesn't have matching effect, it doesn't remove the effect
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -149,11 +131,7 @@ public class HealthController(
|
|||||||
/// <param name="request">Eat request</param>
|
/// <param name="request">Eat request</param>
|
||||||
/// <param name="sessionID">Session id</param>
|
/// <param name="sessionID">Session id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse OffRaidEat(
|
public ItemEventRouterResponse OffRaidEat(PmcData pmcData, OffraidEatRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
OffraidEatRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
var resourceLeft = 0d;
|
var resourceLeft = 0d;
|
||||||
@@ -164,16 +142,11 @@ public class HealthController(
|
|||||||
{
|
{
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(
|
||||||
output,
|
output,
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText("health-unable_to_find_item_to_consume", request.Item)
|
||||||
"health-unable_to_find_item_to_consume",
|
|
||||||
request.Item
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var consumedItemMaxResource = itemHelper
|
var consumedItemMaxResource = itemHelper.GetItem(itemToConsume.Template).Value.Properties.MaxResource;
|
||||||
.GetItem(itemToConsume.Template)
|
|
||||||
.Value.Properties.MaxResource;
|
|
||||||
if (consumedItemMaxResource > 1)
|
if (consumedItemMaxResource > 1)
|
||||||
{
|
{
|
||||||
// Ensure item has a upd object
|
// Ensure item has a upd object
|
||||||
@@ -181,10 +154,7 @@ public class HealthController(
|
|||||||
|
|
||||||
if (itemToConsume.Upd.FoodDrink is null)
|
if (itemToConsume.Upd.FoodDrink is null)
|
||||||
{
|
{
|
||||||
itemToConsume.Upd.FoodDrink = new UpdFoodDrink
|
itemToConsume.Upd.FoodDrink = new UpdFoodDrink { HpPercent = consumedItemMaxResource - request.Count };
|
||||||
{
|
|
||||||
HpPercent = consumedItemMaxResource - request.Count,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -210,21 +180,14 @@ public class HealthController(
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case HealthFactor.Hydration:
|
case HealthFactor.Hydration:
|
||||||
ApplyEdibleEffect(
|
ApplyEdibleEffect(pmcData.Health.Hydration, effectProps, foodIsSingleUse, request);
|
||||||
pmcData.Health.Hydration,
|
|
||||||
effectProps,
|
|
||||||
foodIsSingleUse,
|
|
||||||
request
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case HealthFactor.Energy:
|
case HealthFactor.Energy:
|
||||||
ApplyEdibleEffect(pmcData.Health.Energy, effectProps, foodIsSingleUse, request);
|
ApplyEdibleEffect(pmcData.Health.Energy, effectProps, foodIsSingleUse, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.Warning(
|
logger.Warning($"Unhandled effect after consuming: {itemToConsume.Template}, {key}");
|
||||||
$"Unhandled effect after consuming: {itemToConsume.Template}, {key}"
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,11 +242,7 @@ public class HealthController(
|
|||||||
/// <param name="healthTreatmentRequest">Request data from client</param>
|
/// <param name="healthTreatmentRequest">Request data from client</param>
|
||||||
/// <param name="sessionID">Session id</param>
|
/// <param name="sessionID">Session id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse HealthTreatment(
|
public ItemEventRouterResponse HealthTreatment(PmcData pmcData, HealthTreatmentRequestData healthTreatmentRequest, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HealthTreatmentRequestData healthTreatmentRequest,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
var payMoneyRequest = new ProcessBuyTradeRequestData
|
var payMoneyRequest = new ProcessBuyTradeRequestData
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ public class HideoutController(
|
|||||||
ConfigServer configServer
|
ConfigServer configServer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
public static readonly MongoId NameTaskConditionCountersCraftingId = new(
|
public static readonly MongoId NameTaskConditionCountersCraftingId = new("673f5d6fdd6ed700c703afdc");
|
||||||
"673f5d6fdd6ed700c703afdc"
|
|
||||||
);
|
|
||||||
|
|
||||||
protected readonly FrozenSet<HideoutAreas> _areasWithResources =
|
protected readonly FrozenSet<HideoutAreas> _areasWithResources =
|
||||||
[
|
[
|
||||||
@@ -66,19 +64,12 @@ public class HideoutController(
|
|||||||
/// <param name="request">Start upgrade request</param>
|
/// <param name="request">Start upgrade request</param>
|
||||||
/// <param name="sessionID">Session/player id</param>
|
/// <param name="sessionID">Session/player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void StartUpgrade(
|
public void StartUpgrade(PmcData pmcData, HideoutUpgradeRequestData request, MongoId sessionID, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutUpgradeRequestData request,
|
|
||||||
MongoId sessionID,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var items = request
|
var items = request
|
||||||
.Items.Select(reqItem =>
|
.Items.Select(reqItem =>
|
||||||
{
|
{
|
||||||
var item = pmcData.Inventory.Items.FirstOrDefault(invItem =>
|
var item = pmcData.Inventory.Items.FirstOrDefault(invItem => invItem.Id == reqItem.Id);
|
||||||
invItem.Id == reqItem.Id
|
|
||||||
);
|
|
||||||
return new { inventoryItem = item, requestedItem = reqItem };
|
return new { inventoryItem = item, requestedItem = reqItem };
|
||||||
})
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
@@ -88,12 +79,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
if (item.inventoryItem is null)
|
if (item.inventoryItem is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_item_in_inventory", item.requestedItem.Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_item_in_inventory",
|
|
||||||
item.requestedItem.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -115,38 +101,25 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construction time management
|
// Construction time management
|
||||||
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
area.Type == request.AreaType
|
|
||||||
);
|
|
||||||
if (profileHideoutArea is null)
|
if (profileHideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType));
|
||||||
serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType)
|
|
||||||
);
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var hideoutDataDb = databaseService
|
var hideoutDataDb = databaseService.GetTables().Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
.GetTables()
|
|
||||||
.Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
|
||||||
if (hideoutDataDb is null)
|
if (hideoutDataDb is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area_in_database", request.AreaType));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_area_in_database",
|
|
||||||
request.AreaType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctime = hideoutDataDb
|
var ctime = hideoutDataDb.Stages[(profileHideoutArea.Level + 1).ToString()].ConstructionTime;
|
||||||
.Stages[(profileHideoutArea.Level + 1).ToString()]
|
|
||||||
.ConstructionTime;
|
|
||||||
if (ctime > 0)
|
if (ctime > 0)
|
||||||
{
|
{
|
||||||
if (profileHelper.IsDeveloperAccount(sessionID))
|
if (profileHelper.IsDeveloperAccount(sessionID))
|
||||||
@@ -179,14 +152,10 @@ public class HideoutController(
|
|||||||
var hideout = databaseService.GetHideout();
|
var hideout = databaseService.GetHideout();
|
||||||
var globals = databaseService.GetGlobals();
|
var globals = databaseService.GetGlobals();
|
||||||
|
|
||||||
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
area.Type == request.AreaType
|
|
||||||
);
|
|
||||||
if (profileHideoutArea is null)
|
if (profileHideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType));
|
||||||
serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType)
|
|
||||||
);
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -197,33 +166,19 @@ public class HideoutController(
|
|||||||
profileHideoutArea.CompleteTime = 0;
|
profileHideoutArea.CompleteTime = 0;
|
||||||
profileHideoutArea.Constructing = false;
|
profileHideoutArea.Constructing = false;
|
||||||
|
|
||||||
var hideoutData = hideout.Areas.FirstOrDefault(area =>
|
var hideoutData = hideout.Areas.FirstOrDefault(area => area.Type == profileHideoutArea.Type);
|
||||||
area.Type == profileHideoutArea.Type
|
|
||||||
);
|
|
||||||
if (hideoutData is null)
|
if (hideoutData is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area_in_database", request.AreaType));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_area_in_database",
|
|
||||||
request.AreaType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply bonuses
|
// Apply bonuses
|
||||||
if (
|
if (!hideoutData.Stages.TryGetValue(profileHideoutArea.Level.ToString(), out var hideoutStage))
|
||||||
!hideoutData.Stages.TryGetValue(
|
|
||||||
profileHideoutArea.Level.ToString(),
|
|
||||||
out var hideoutStage
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Stage level: {profileHideoutArea.Level} not found for area: {request.AreaType}");
|
||||||
$"Stage level: {profileHideoutArea.Level} not found for area: {request.AreaType}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -239,21 +194,11 @@ public class HideoutController(
|
|||||||
// Upgrade includes a container improvement/addition
|
// Upgrade includes a container improvement/addition
|
||||||
if (!string.IsNullOrEmpty(hideoutStage.Container))
|
if (!string.IsNullOrEmpty(hideoutStage.Container))
|
||||||
{
|
{
|
||||||
AddContainerImprovementToProfile(
|
AddContainerImprovementToProfile(output, sessionID, pmcData, profileHideoutArea, hideoutData, hideoutStage);
|
||||||
output,
|
|
||||||
sessionID,
|
|
||||||
pmcData,
|
|
||||||
profileHideoutArea,
|
|
||||||
hideoutData,
|
|
||||||
hideoutStage
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upgrading water collector / med station
|
// Upgrading water collector / med station
|
||||||
if (
|
if (profileHideoutArea.Type == HideoutAreas.WaterCollector || profileHideoutArea.Type == HideoutAreas.MedStation)
|
||||||
profileHideoutArea.Type == HideoutAreas.WaterCollector
|
|
||||||
|| profileHideoutArea.Type == HideoutAreas.MedStation
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
SetWallVisibleIfPrereqsMet(pmcData);
|
SetWallVisibleIfPrereqsMet(pmcData);
|
||||||
}
|
}
|
||||||
@@ -278,17 +223,11 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Player profile</param>
|
/// <param name="pmcData">Player profile</param>
|
||||||
protected void SetWallVisibleIfPrereqsMet(PmcData pmcData)
|
protected void SetWallVisibleIfPrereqsMet(PmcData pmcData)
|
||||||
{
|
{
|
||||||
var medStation = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var medStation = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == HideoutAreas.MedStation);
|
||||||
area.Type == HideoutAreas.MedStation
|
var waterCollector = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == HideoutAreas.WaterCollector);
|
||||||
);
|
|
||||||
var waterCollector = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
|
||||||
area.Type == HideoutAreas.WaterCollector
|
|
||||||
);
|
|
||||||
if (medStation?.Level >= 1 && waterCollector?.Level >= 1)
|
if (medStation?.Level >= 1 && waterCollector?.Level >= 1)
|
||||||
{
|
{
|
||||||
var wall = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var wall = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == HideoutAreas.EmergencyWall);
|
||||||
area.Type == HideoutAreas.EmergencyWall
|
|
||||||
);
|
|
||||||
if (wall?.Level == 0)
|
if (wall?.Level == 0)
|
||||||
{
|
{
|
||||||
wall.Level = 3;
|
wall.Level = 3;
|
||||||
@@ -319,12 +258,7 @@ public class HideoutController(
|
|||||||
var keyForHideoutAreaStash = ((int)dbHideoutArea.Type).ToString();
|
var keyForHideoutAreaStash = ((int)dbHideoutArea.Type).ToString();
|
||||||
if (!pmcData.Inventory.HideoutAreaStashes.ContainsKey(keyForHideoutAreaStash))
|
if (!pmcData.Inventory.HideoutAreaStashes.ContainsKey(keyForHideoutAreaStash))
|
||||||
{
|
{
|
||||||
if (
|
if (!pmcData.Inventory.HideoutAreaStashes.TryAdd(keyForHideoutAreaStash, dbHideoutArea.Id))
|
||||||
!pmcData.Inventory.HideoutAreaStashes.TryAdd(
|
|
||||||
keyForHideoutAreaStash,
|
|
||||||
dbHideoutArea.Id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Error($"Unable to add key: {dbHideoutArea.Type} to HideoutAreaStashes");
|
logger.Error($"Unable to add key: {dbHideoutArea.Type} to HideoutAreaStashes");
|
||||||
}
|
}
|
||||||
@@ -337,27 +271,13 @@ public class HideoutController(
|
|||||||
if (dbHideoutArea.Type == HideoutAreas.EquipmentPresetsStand)
|
if (dbHideoutArea.Type == HideoutAreas.EquipmentPresetsStand)
|
||||||
// Can have multiple 'standx' children depending on upgrade level
|
// Can have multiple 'standx' children depending on upgrade level
|
||||||
{
|
{
|
||||||
AddMissingPresetStandItemsToProfile(
|
AddMissingPresetStandItemsToProfile(sessionId, hideoutStage, pmcData, dbHideoutArea, output);
|
||||||
sessionId,
|
|
||||||
hideoutStage,
|
|
||||||
pmcData,
|
|
||||||
dbHideoutArea,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AddContainerUpgradeToClientOutput(
|
AddContainerUpgradeToClientOutput(sessionId, keyForHideoutAreaStash, dbHideoutArea, hideoutStage, output);
|
||||||
sessionId,
|
|
||||||
keyForHideoutAreaStash,
|
|
||||||
dbHideoutArea,
|
|
||||||
hideoutStage,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
// Some hideout areas (Gun stand) have child areas linked to it
|
// Some hideout areas (Gun stand) have child areas linked to it
|
||||||
var childDbArea = databaseService
|
var childDbArea = databaseService.GetHideout().Areas.FirstOrDefault(area => area.ParentArea == dbHideoutArea.Id);
|
||||||
.GetHideout()
|
|
||||||
.Areas.FirstOrDefault(area => area.ParentArea == dbHideoutArea.Id);
|
|
||||||
if (childDbArea is null)
|
if (childDbArea is null)
|
||||||
{
|
{
|
||||||
// No child db area, we're complete
|
// No child db area, we're complete
|
||||||
@@ -372,23 +292,14 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set child area level to same as parent area
|
// Set child area level to same as parent area
|
||||||
pmcData
|
pmcData.Hideout.Areas.FirstOrDefault(hideoutArea => hideoutArea.Type == childDbArea.Type).Level = pmcData
|
||||||
.Hideout.Areas.FirstOrDefault(hideoutArea => hideoutArea.Type == childDbArea.Type)
|
|
||||||
.Level = pmcData
|
|
||||||
.Hideout.Areas.FirstOrDefault(area => area.Type == profileParentHideoutArea.Type)
|
.Hideout.Areas.FirstOrDefault(area => area.Type == profileParentHideoutArea.Type)
|
||||||
.Level;
|
.Level;
|
||||||
|
|
||||||
// Add/upgrade stash item in player inventory
|
// Add/upgrade stash item in player inventory
|
||||||
if (
|
if (!childDbArea.Stages.TryGetValue(profileParentHideoutArea.Level.ToString(), out var childDbAreaStage))
|
||||||
!childDbArea.Stages.TryGetValue(
|
|
||||||
profileParentHideoutArea.Level.ToString(),
|
|
||||||
out var childDbAreaStage
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable to find stage: {profileParentHideoutArea.Level} of area: {dbHideoutArea.Id}");
|
||||||
$"Unable to find stage: {profileParentHideoutArea.Level} of area: {dbHideoutArea.Id}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -396,13 +307,7 @@ public class HideoutController(
|
|||||||
AddUpdateInventoryItemToProfile(sessionId, pmcData, childDbArea, childDbAreaStage);
|
AddUpdateInventoryItemToProfile(sessionId, pmcData, childDbArea, childDbAreaStage);
|
||||||
|
|
||||||
// Inform client of the changes
|
// Inform client of the changes
|
||||||
AddContainerUpgradeToClientOutput(
|
AddContainerUpgradeToClientOutput(sessionId, childAreaTypeKey, childDbArea, childDbAreaStage, output);
|
||||||
sessionId,
|
|
||||||
childAreaTypeKey,
|
|
||||||
childDbArea,
|
|
||||||
childDbAreaStage,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -412,16 +317,9 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="dbHideoutArea">Hideout area from db being upgraded</param>
|
/// <param name="dbHideoutArea">Hideout area from db being upgraded</param>
|
||||||
/// <param name="hideoutStage">Stage area upgraded to</param>
|
/// <param name="hideoutStage">Stage area upgraded to</param>
|
||||||
protected void AddUpdateInventoryItemToProfile(
|
protected void AddUpdateInventoryItemToProfile(MongoId sessionId, PmcData pmcData, HideoutArea dbHideoutArea, Stage hideoutStage)
|
||||||
MongoId sessionId,
|
|
||||||
PmcData pmcData,
|
|
||||||
HideoutArea dbHideoutArea,
|
|
||||||
Stage hideoutStage
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var existingInventoryItem = pmcData.Inventory.Items.FirstOrDefault(item =>
|
var existingInventoryItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == dbHideoutArea.Id);
|
||||||
item.Id == dbHideoutArea.Id
|
|
||||||
);
|
|
||||||
if (existingInventoryItem is not null)
|
if (existingInventoryItem is not null)
|
||||||
{
|
{
|
||||||
// Update existing items container tpl to point to new id (tpl)
|
// Update existing items container tpl to point to new id (tpl)
|
||||||
@@ -431,11 +329,7 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add new item as none exists (don't inform client of newContainerItem, will be done in `profileChanges.changedHideoutStashes`)
|
// Add new item as none exists (don't inform client of newContainerItem, will be done in `profileChanges.changedHideoutStashes`)
|
||||||
var newContainerItem = new Item
|
var newContainerItem = new Item { Id = dbHideoutArea.Id, Template = hideoutStage.Container.Value };
|
||||||
{
|
|
||||||
Id = dbHideoutArea.Id,
|
|
||||||
Template = hideoutStage.Container.Value,
|
|
||||||
};
|
|
||||||
pmcData.Inventory.Items.Add(newContainerItem);
|
pmcData.Inventory.Items.Add(newContainerItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,12 +350,14 @@ public class HideoutController(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Ensure ChangedHideoutStashes isn't null
|
// Ensure ChangedHideoutStashes isn't null
|
||||||
output.ProfileChanges[sessionId].ChangedHideoutStashes ??=
|
output.ProfileChanges[sessionId].ChangedHideoutStashes ??= new Dictionary<string, HideoutStashItem>();
|
||||||
new Dictionary<string, HideoutStashItem>();
|
|
||||||
|
|
||||||
// Inform client of changes
|
// Inform client of changes
|
||||||
output.ProfileChanges[sessionId].ChangedHideoutStashes[changedHideoutStashesKey] =
|
output.ProfileChanges[sessionId].ChangedHideoutStashes[changedHideoutStashesKey] = new HideoutStashItem
|
||||||
new HideoutStashItem { Id = hideoutDbData.Id, Template = hideoutStage.Container };
|
{
|
||||||
|
Id = hideoutDbData.Id,
|
||||||
|
Template = hideoutStage.Container,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -482,9 +378,7 @@ public class HideoutController(
|
|||||||
|
|
||||||
var itemsToAdd = addItemToHideoutRequest.Items.Select(kvp =>
|
var itemsToAdd = addItemToHideoutRequest.Items.Select(kvp =>
|
||||||
{
|
{
|
||||||
var item = pmcData.Inventory.Items.FirstOrDefault(invItem =>
|
var item = pmcData.Inventory.Items.FirstOrDefault(invItem => invItem.Id == kvp.Value.Id);
|
||||||
invItem.Id == kvp.Value.Id
|
|
||||||
);
|
|
||||||
return new
|
return new
|
||||||
{
|
{
|
||||||
inventoryItem = item,
|
inventoryItem = item,
|
||||||
@@ -493,17 +387,10 @@ public class HideoutController(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == addItemToHideoutRequest.AreaType);
|
||||||
area.Type == addItemToHideoutRequest.AreaType
|
|
||||||
);
|
|
||||||
if (hideoutArea is null)
|
if (hideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area_in_database", addItemToHideoutRequest.AreaType));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_area_in_database",
|
|
||||||
addItemToHideoutRequest.AreaType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,9 +409,7 @@ public class HideoutController(
|
|||||||
|
|
||||||
// Add item to area.slots
|
// Add item to area.slots
|
||||||
var destinationLocationIndex = int.Parse(item.slot);
|
var destinationLocationIndex = int.Parse(item.slot);
|
||||||
var hideoutSlotIndex = hideoutArea.Slots.FindIndex(slot =>
|
var hideoutSlotIndex = hideoutArea.Slots.FindIndex(slot => slot.LocationIndex == destinationLocationIndex);
|
||||||
slot.LocationIndex == destinationLocationIndex
|
|
||||||
);
|
|
||||||
if (hideoutSlotIndex == -1)
|
if (hideoutSlotIndex == -1)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
@@ -560,33 +445,20 @@ public class HideoutController(
|
|||||||
/// <param name="request">Take item out of area request</param>
|
/// <param name="request">Take item out of area request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse TakeItemsFromAreaSlots(
|
public ItemEventRouterResponse TakeItemsFromAreaSlots(PmcData pmcData, HideoutTakeItemOutRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutTakeItemOutRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
area.Type == request.AreaType
|
|
||||||
);
|
|
||||||
if (hideoutArea is null)
|
if (hideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType));
|
||||||
serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hideoutArea.Slots is null || hideoutArea.Slots.Count == 0)
|
if (hideoutArea.Slots is null || hideoutArea.Slots.Count == 0)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_item_to_remove_from_area", hideoutArea.Type));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_item_to_remove_from_area",
|
|
||||||
hideoutArea.Type
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,12 +472,7 @@ public class HideoutController(
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(
|
throw new Exception(serverLocalisationService.GetText("hideout-unhandled_remove_item_from_area_request", hideoutArea.Type));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unhandled_remove_item_from_area_request",
|
|
||||||
hideoutArea.Type
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -636,9 +503,7 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assume only one item in slot
|
// Assume only one item in slot
|
||||||
var itemToReturn = hideoutArea
|
var itemToReturn = hideoutArea.Slots?.FirstOrDefault(slot => slot.LocationIndex == slotIndexToRemove)?.Items?.FirstOrDefault();
|
||||||
.Slots?.FirstOrDefault(slot => slot.LocationIndex == slotIndexToRemove)
|
|
||||||
?.Items?.FirstOrDefault();
|
|
||||||
if (itemToReturn is null)
|
if (itemToReturn is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
@@ -665,9 +530,7 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove items from slot, keep locationIndex object
|
// Remove items from slot, keep locationIndex object
|
||||||
var hideoutSlotIndex = hideoutArea.Slots.FindIndex(slot =>
|
var hideoutSlotIndex = hideoutArea.Slots.FindIndex(slot => slot.LocationIndex == slotIndexToRemove);
|
||||||
slot.LocationIndex == slotIndexToRemove
|
|
||||||
);
|
|
||||||
hideoutArea.Slots[hideoutSlotIndex].Items = null;
|
hideoutArea.Slots[hideoutSlotIndex].Items = null;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@@ -681,25 +544,17 @@ public class HideoutController(
|
|||||||
/// <param name="request">Toggle area request</param>
|
/// <param name="request">Toggle area request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse ToggleArea(
|
public ItemEventRouterResponse ToggleArea(PmcData pmcData, HideoutToggleAreaRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutToggleAreaRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
// Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress)
|
// Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress)
|
||||||
hideoutHelper.UpdatePlayerHideout(sessionID);
|
hideoutHelper.UpdatePlayerHideout(sessionID);
|
||||||
|
|
||||||
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var hideoutArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
area.Type == request.AreaType
|
|
||||||
);
|
|
||||||
if (hideoutArea is null)
|
if (hideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType));
|
||||||
serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,14 +580,10 @@ public class HideoutController(
|
|||||||
hideoutHelper.RegisterProduction(pmcData, request, sessionID);
|
hideoutHelper.RegisterProduction(pmcData, request, sessionID);
|
||||||
|
|
||||||
// Find the recipe of the production
|
// Find the recipe of the production
|
||||||
var recipe = databaseService
|
var recipe = databaseService.GetHideout().Production.Recipes.FirstOrDefault(production => production.Id == request.RecipeId);
|
||||||
.GetHideout()
|
|
||||||
.Production.Recipes.FirstOrDefault(production => production.Id == request.RecipeId);
|
|
||||||
|
|
||||||
// Find the actual amount of items we need to remove because body can send weird data
|
// Find the actual amount of items we need to remove because body can send weird data
|
||||||
var recipeRequirementsClone = cloner.Clone(
|
var recipeRequirementsClone = cloner.Clone(recipe.Requirements.Where(r => r.Type == "Item" || r.Type == "Tool"));
|
||||||
recipe.Requirements.Where(r => r.Type == "Item" || r.Type == "Tool")
|
|
||||||
);
|
|
||||||
|
|
||||||
List<IdWithCount> itemsToDelete = [];
|
List<IdWithCount> itemsToDelete = [];
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
@@ -742,9 +593,7 @@ public class HideoutController(
|
|||||||
foreach (var itemToDelete in itemsToDelete)
|
foreach (var itemToDelete in itemsToDelete)
|
||||||
{
|
{
|
||||||
var itemToCheck = pmcData.Inventory.Items.FirstOrDefault(i => i.Id == itemToDelete.Id);
|
var itemToCheck = pmcData.Inventory.Items.FirstOrDefault(i => i.Id == itemToDelete.Id);
|
||||||
var requirement = recipeRequirementsClone.FirstOrDefault(requirement =>
|
var requirement = recipeRequirementsClone.FirstOrDefault(requirement => requirement.TemplateId == itemToCheck.Template);
|
||||||
requirement.TemplateId == itemToCheck.Template
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle tools not having a `count`, but always only requiring 1
|
// Handle tools not having a `count`, but always only requiring 1
|
||||||
var requiredCount = requirement.Count ?? 1;
|
var requiredCount = requirement.Count ?? 1;
|
||||||
@@ -753,13 +602,7 @@ public class HideoutController(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
inventoryHelper.RemoveItemByCount(
|
inventoryHelper.RemoveItemByCount(pmcData, itemToDelete.Id, requiredCount, sessionID, output);
|
||||||
pmcData,
|
|
||||||
itemToDelete.Id,
|
|
||||||
requiredCount,
|
|
||||||
sessionID,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
// Tools don't have a count
|
// Tools don't have a count
|
||||||
if (requirement.Type != "Tool")
|
if (requirement.Type != "Tool")
|
||||||
@@ -779,19 +622,13 @@ public class HideoutController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse ScavCaseProductionStart(
|
public ItemEventRouterResponse ScavCaseProductionStart(PmcData pmcData, HideoutScavCaseStartRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutScavCaseStartRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
foreach (var requestedItem in request.Items)
|
foreach (var requestedItem in request.Items)
|
||||||
{
|
{
|
||||||
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item =>
|
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == requestedItem.Id);
|
||||||
item.Id == requestedItem.Id
|
|
||||||
);
|
|
||||||
if (inventoryItem is null)
|
if (inventoryItem is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
@@ -803,10 +640,7 @@ public class HideoutController(
|
|||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (inventoryItem.Upd?.StackObjectsCount is not null && inventoryItem.Upd.StackObjectsCount > requestedItem.Count)
|
||||||
inventoryItem.Upd?.StackObjectsCount is not null
|
|
||||||
&& inventoryItem.Upd.StackObjectsCount > requestedItem.Count
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
inventoryItem.Upd.StackObjectsCount -= requestedItem.Count;
|
inventoryItem.Upd.StackObjectsCount -= requestedItem.Count;
|
||||||
}
|
}
|
||||||
@@ -816,17 +650,10 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var recipe = databaseService
|
var recipe = databaseService.GetHideout().Production?.ScavRecipes?.FirstOrDefault(r => r.Id == request.RecipeId);
|
||||||
.GetHideout()
|
|
||||||
.Production?.ScavRecipes?.FirstOrDefault(r => r.Id == request.RecipeId);
|
|
||||||
if (recipe is null)
|
if (recipe is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_scav_case_recipie_in_database", request.RecipeId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_scav_case_recipie_in_database",
|
|
||||||
request.RecipeId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
@@ -840,9 +667,7 @@ public class HideoutController(
|
|||||||
pmcData,
|
pmcData,
|
||||||
recipe.ProductionTime ?? 0,
|
recipe.ProductionTime ?? 0,
|
||||||
SkillTypes.Crafting,
|
SkillTypes.Crafting,
|
||||||
databaseService
|
databaseService.GetGlobals().Configuration.SkillsSettings.Crafting.CraftTimeReductionPerLevel
|
||||||
.GetGlobals()
|
|
||||||
.Configuration.SkillsSettings.Crafting.CraftTimeReductionPerLevel
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var modifiedScavCaseTime = GetScavCaseTime(pmcData, adjustedCraftTime);
|
var modifiedScavCaseTime = GetScavCaseTime(pmcData, adjustedCraftTime);
|
||||||
@@ -900,11 +725,7 @@ public class HideoutController(
|
|||||||
/// <param name="request">Remove production from area request</param>
|
/// <param name="request">Remove production from area request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse TakeProduction(
|
public ItemEventRouterResponse TakeProduction(PmcData pmcData, HideoutTakeProductionRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutTakeProductionRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
var hideoutDb = databaseService.GetHideout();
|
var hideoutDb = databaseService.GetHideout();
|
||||||
@@ -926,9 +747,7 @@ public class HideoutController(
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
var scavCase = hideoutDb.Production.ScavRecipes.FirstOrDefault(r =>
|
var scavCase = hideoutDb.Production.ScavRecipes.FirstOrDefault(r => r.Id == request.RecipeId);
|
||||||
r.Id == request.RecipeId
|
|
||||||
);
|
|
||||||
if (scavCase is not null)
|
if (scavCase is not null)
|
||||||
{
|
{
|
||||||
HandleScavCase(sessionID, pmcData, request, output);
|
HandleScavCase(sessionID, pmcData, request, output);
|
||||||
@@ -936,12 +755,7 @@ public class HideoutController(
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.RecipeId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
|
||||||
request.RecipeId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
@@ -986,19 +800,11 @@ public class HideoutController(
|
|||||||
// If we're unable to find the production, send an error to the client
|
// If we're unable to find the production, send an error to the client
|
||||||
if (prodId is null)
|
if (prodId is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.RecipeId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
|
||||||
request.RecipeId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(
|
httpResponseUtil.AppendErrorToOutput(
|
||||||
output,
|
output,
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.RecipeId)
|
||||||
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
|
||||||
request.RecipeId
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1029,10 +835,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
itemHelper.AddUpdObjectToItem(reward.FirstOrDefault());
|
itemHelper.AddUpdObjectToItem(reward.FirstOrDefault());
|
||||||
|
|
||||||
reward.FirstOrDefault().Upd.RecodableComponent = new UpdRecodableComponent
|
reward.FirstOrDefault().Upd.RecodableComponent = new UpdRecodableComponent { IsEncoded = true };
|
||||||
{
|
|
||||||
IsEncoded = true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1061,9 +864,7 @@ public class HideoutController(
|
|||||||
if (totalCraftingHours / _hideoutConfig.HoursForSkillCrafting >= 1)
|
if (totalCraftingHours / _hideoutConfig.HoursForSkillCrafting >= 1)
|
||||||
{
|
{
|
||||||
// Spent enough time crafting to get a bonus xp multiplier
|
// Spent enough time crafting to get a bonus xp multiplier
|
||||||
var multiplierCrafting = Math.Floor(
|
var multiplierCrafting = Math.Floor(totalCraftingHours.Value / _hideoutConfig.HoursForSkillCrafting);
|
||||||
totalCraftingHours.Value / _hideoutConfig.HoursForSkillCrafting
|
|
||||||
);
|
|
||||||
craftingExpAmount += (int)(1 * multiplierCrafting);
|
craftingExpAmount += (int)(1 * multiplierCrafting);
|
||||||
totalCraftingHours -= _hideoutConfig.HoursForSkillCrafting * multiplierCrafting;
|
totalCraftingHours -= _hideoutConfig.HoursForSkillCrafting * multiplierCrafting;
|
||||||
}
|
}
|
||||||
@@ -1136,11 +937,7 @@ public class HideoutController(
|
|||||||
var intellectAmountToGive = 0.5 * Math.Round((double)(craftingExpAmount / 15));
|
var intellectAmountToGive = 0.5 * Math.Round((double)(craftingExpAmount / 15));
|
||||||
if (intellectAmountToGive > 0)
|
if (intellectAmountToGive > 0)
|
||||||
{
|
{
|
||||||
profileHelper.AddSkillPointsToPlayer(
|
profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.Intellect, intellectAmountToGive);
|
||||||
pmcData,
|
|
||||||
SkillTypes.Intellect,
|
|
||||||
intellectAmountToGive
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1157,11 +954,7 @@ public class HideoutController(
|
|||||||
// production.json is set to
|
// production.json is set to
|
||||||
if (recipe.Continuous.GetValueOrDefault(false))
|
if (recipe.Continuous.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
hideoutProduction.ProductionTime = hideoutHelper.GetAdjustedCraftTimeWithSkills(
|
hideoutProduction.ProductionTime = hideoutHelper.GetAdjustedCraftTimeWithSkills(pmcData, recipe.Id, true);
|
||||||
pmcData,
|
|
||||||
recipe.Id,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag normal (not continuous) crafts as complete
|
// Flag normal (not continuous) crafts as complete
|
||||||
@@ -1177,11 +970,7 @@ public class HideoutController(
|
|||||||
/// <param name="recipe"></param>
|
/// <param name="recipe"></param>
|
||||||
/// <param name="itemAndChildrenToSendToPlayer"></param>
|
/// <param name="itemAndChildrenToSendToPlayer"></param>
|
||||||
/// <param name="rewardIsPreset">Reward is a preset</param>
|
/// <param name="rewardIsPreset">Reward is a preset</param>
|
||||||
protected void HandleStackableState(
|
protected void HandleStackableState(HideoutProduction recipe, List<List<Item>> itemAndChildrenToSendToPlayer, bool rewardIsPreset)
|
||||||
HideoutProduction recipe,
|
|
||||||
List<List<Item>> itemAndChildrenToSendToPlayer,
|
|
||||||
bool rewardIsPreset
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var rewardIsStackable = itemHelper.IsItemTplStackable(recipe.EndProduct);
|
var rewardIsStackable = itemHelper.IsItemTplStackable(recipe.EndProduct);
|
||||||
if (rewardIsStackable.GetValueOrDefault(false))
|
if (rewardIsStackable.GetValueOrDefault(false))
|
||||||
@@ -1206,9 +995,7 @@ public class HideoutController(
|
|||||||
// Add the first reward item to array when not a preset (first preset added above earlier)
|
// Add the first reward item to array when not a preset (first preset added above earlier)
|
||||||
if (!rewardIsPreset)
|
if (!rewardIsPreset)
|
||||||
{
|
{
|
||||||
itemAndChildrenToSendToPlayer.Add(
|
itemAndChildrenToSendToPlayer.Add([new Item { Id = new MongoId(), Template = recipe.EndProduct }]);
|
||||||
[new Item { Id = new MongoId(), Template = recipe.EndProduct }]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add multiple of item if recipe requests it
|
// Add multiple of item if recipe requests it
|
||||||
@@ -1216,10 +1003,7 @@ public class HideoutController(
|
|||||||
var countOfItemsToReward = recipe.Count;
|
var countOfItemsToReward = recipe.Count;
|
||||||
for (var index = 1; index < countOfItemsToReward; index++)
|
for (var index = 1; index < countOfItemsToReward; index++)
|
||||||
{
|
{
|
||||||
var firstItemWithChildrenClone = cloner
|
var firstItemWithChildrenClone = cloner.Clone(itemAndChildrenToSendToPlayer.FirstOrDefault()).ReplaceIDs().ToList();
|
||||||
.Clone(itemAndChildrenToSendToPlayer.FirstOrDefault())
|
|
||||||
.ReplaceIDs()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
itemAndChildrenToSendToPlayer.AddRange([firstItemWithChildrenClone]);
|
itemAndChildrenToSendToPlayer.AddRange([firstItemWithChildrenClone]);
|
||||||
}
|
}
|
||||||
@@ -1249,10 +1033,7 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Profile to get counter from</param>
|
/// <param name="pmcData">Profile to get counter from</param>
|
||||||
/// <param name="recipe">Recipe being crafted</param>
|
/// <param name="recipe">Recipe being crafted</param>
|
||||||
/// <returns>TaskConditionCounter</returns>
|
/// <returns>TaskConditionCounter</returns>
|
||||||
protected TaskConditionCounter GetCustomSptHoursCraftingTaskConditionCounter(
|
protected TaskConditionCounter GetCustomSptHoursCraftingTaskConditionCounter(PmcData pmcData, HideoutProduction recipe)
|
||||||
PmcData pmcData,
|
|
||||||
HideoutProduction recipe
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Add if doesn't exist
|
// Add if doesn't exist
|
||||||
pmcData.TaskConditionCounters.TryAdd(
|
pmcData.TaskConditionCounters.TryAdd(
|
||||||
@@ -1297,12 +1078,7 @@ public class HideoutController(
|
|||||||
|
|
||||||
if (prodId == null)
|
if (prodId == null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_production_in_profile_by_recipie_id", request.RecipeId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
|
||||||
request.RecipeId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output);
|
httpResponseUtil.AppendErrorToOutput(output);
|
||||||
|
|
||||||
@@ -1344,12 +1120,7 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request">QTE result object</param>
|
/// <param name="request">QTE result object</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void HandleQTEEventOutcome(
|
public void HandleQTEEventOutcome(MongoId sessionId, PmcData pmcData, HandleQTEEventRequestData request, ItemEventRouterResponse output)
|
||||||
MongoId sessionId,
|
|
||||||
PmcData pmcData,
|
|
||||||
HandleQTEEventRequestData request,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// {
|
// {
|
||||||
// "Action": "HideoutQuickTimeEvent",
|
// "Action": "HideoutQuickTimeEvent",
|
||||||
@@ -1368,22 +1139,14 @@ public class HideoutController(
|
|||||||
if (outcome)
|
if (outcome)
|
||||||
{
|
{
|
||||||
// Success
|
// Success
|
||||||
pmcData.Health.Energy.Current += relevantQte
|
pmcData.Health.Energy.Current += relevantQte.Results[QteEffectType.singleSuccessEffect].Energy;
|
||||||
.Results[QteEffectType.singleSuccessEffect]
|
pmcData.Health.Hydration.Current += relevantQte.Results[QteEffectType.singleSuccessEffect].Hydration;
|
||||||
.Energy;
|
|
||||||
pmcData.Health.Hydration.Current += relevantQte
|
|
||||||
.Results[QteEffectType.singleSuccessEffect]
|
|
||||||
.Hydration;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Failed
|
// Failed
|
||||||
pmcData.Health.Energy.Current += relevantQte
|
pmcData.Health.Energy.Current += relevantQte.Results[QteEffectType.singleFailEffect].Energy;
|
||||||
.Results[QteEffectType.singleFailEffect]
|
pmcData.Health.Hydration.Current += relevantQte.Results[QteEffectType.singleFailEffect].Hydration;
|
||||||
.Energy;
|
|
||||||
pmcData.Health.Hydration.Current += relevantQte
|
|
||||||
.Results[QteEffectType.singleFailEffect]
|
|
||||||
.Hydration;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1408,21 +1171,17 @@ public class HideoutController(
|
|||||||
protected void HandleMusclePain(PmcData pmcData, QteResult finishEffect)
|
protected void HandleMusclePain(PmcData pmcData, QteResult finishEffect)
|
||||||
{
|
{
|
||||||
var hasMildPain = pmcData.Health.BodyParts["Chest"].Effects?.ContainsKey("MildMusclePain");
|
var hasMildPain = pmcData.Health.BodyParts["Chest"].Effects?.ContainsKey("MildMusclePain");
|
||||||
var hasSeverePain = pmcData
|
var hasSeverePain = pmcData.Health.BodyParts["Chest"].Effects?.ContainsKey("SevereMusclePain");
|
||||||
.Health.BodyParts["Chest"]
|
|
||||||
.Effects?.ContainsKey("SevereMusclePain");
|
|
||||||
|
|
||||||
// Has no muscle pain at all, add mild
|
// Has no muscle pain at all, add mild
|
||||||
if (!hasMildPain.GetValueOrDefault(false) && !hasSeverePain.GetValueOrDefault(false))
|
if (!hasMildPain.GetValueOrDefault(false) && !hasSeverePain.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
// Nullguard
|
// Nullguard
|
||||||
pmcData.Health.BodyParts["Chest"].Effects ??=
|
pmcData.Health.BodyParts["Chest"].Effects ??= new Dictionary<string, BodyPartEffectProperties>();
|
||||||
new Dictionary<string, BodyPartEffectProperties>();
|
pmcData.Health.BodyParts["Chest"].Effects["MildMusclePain"] = new BodyPartEffectProperties
|
||||||
pmcData.Health.BodyParts["Chest"].Effects["MildMusclePain"] =
|
{
|
||||||
new BodyPartEffectProperties
|
Time = finishEffect.RewardEffects.FirstOrDefault().Time, // TODO - remove hard coded access, get value properly
|
||||||
{
|
};
|
||||||
Time = finishEffect.RewardEffects.FirstOrDefault().Time, // TODO - remove hard coded access, get value properly
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1432,11 +1191,10 @@ public class HideoutController(
|
|||||||
// Already has mild pain, remove mild and add severe
|
// Already has mild pain, remove mild and add severe
|
||||||
pmcData.Health.BodyParts["Chest"].Effects.Remove("MildMusclePain");
|
pmcData.Health.BodyParts["Chest"].Effects.Remove("MildMusclePain");
|
||||||
|
|
||||||
pmcData.Health.BodyParts["Chest"].Effects["SevereMusclePain"] =
|
pmcData.Health.BodyParts["Chest"].Effects["SevereMusclePain"] = new BodyPartEffectProperties
|
||||||
new BodyPartEffectProperties
|
{
|
||||||
{
|
Time = finishEffect.RewardEffects.FirstOrDefault().Time,
|
||||||
Time = finishEffect.RewardEffects.FirstOrDefault().Time,
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1446,26 +1204,18 @@ public class HideoutController(
|
|||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request">shooting range score request></param>
|
/// <param name="request">shooting range score request></param>
|
||||||
public void RecordShootingRangePoints(
|
public void RecordShootingRangePoints(MongoId sessionId, PmcData pmcData, RecordShootingRangePoints request)
|
||||||
MongoId sessionId,
|
|
||||||
PmcData pmcData,
|
|
||||||
RecordShootingRangePoints request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const string shootingRangeKey = "ShootingRangePoints";
|
const string shootingRangeKey = "ShootingRangePoints";
|
||||||
var overallCounterItems = pmcData.Stats.Eft.OverallCounters.Items;
|
var overallCounterItems = pmcData.Stats.Eft.OverallCounters.Items;
|
||||||
|
|
||||||
// Find counter by key
|
// Find counter by key
|
||||||
var shootingRangeHighScore = overallCounterItems.FirstOrDefault(counter =>
|
var shootingRangeHighScore = overallCounterItems.FirstOrDefault(counter => counter.Key.Contains(shootingRangeKey));
|
||||||
counter.Key.Contains(shootingRangeKey)
|
|
||||||
);
|
|
||||||
if (shootingRangeHighScore is null)
|
if (shootingRangeHighScore is null)
|
||||||
{
|
{
|
||||||
// Counter not found, add blank one
|
// Counter not found, add blank one
|
||||||
overallCounterItems.Add(new CounterKeyValue { Key = [shootingRangeKey], Value = 0 });
|
overallCounterItems.Add(new CounterKeyValue { Key = [shootingRangeKey], Value = 0 });
|
||||||
shootingRangeHighScore = overallCounterItems.FirstOrDefault(counter =>
|
shootingRangeHighScore = overallCounterItems.FirstOrDefault(counter => counter.Key.Contains(shootingRangeKey));
|
||||||
counter.Key.Contains(shootingRangeKey)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shootingRangeHighScore.Value = request.Points;
|
shootingRangeHighScore.Value = request.Points;
|
||||||
@@ -1478,11 +1228,7 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request">Improve area request</param>
|
/// <param name="request">Improve area request</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse ImproveArea(
|
public ItemEventRouterResponse ImproveArea(MongoId sessionId, PmcData pmcData, HideoutImproveAreaRequestData request)
|
||||||
MongoId sessionId,
|
|
||||||
PmcData pmcData,
|
|
||||||
HideoutImproveAreaRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -1498,12 +1244,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
if (item.inventoryItem is null)
|
if (item.inventoryItem is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_item_in_inventory", item.requestedItem.Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_item_in_inventory",
|
|
||||||
item.requestedItem.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1522,28 +1263,17 @@ public class HideoutController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(x =>
|
var profileHideoutArea = pmcData.Hideout.Areas.FirstOrDefault(x => x.Type == request.AreaType);
|
||||||
x.Type == request.AreaType
|
|
||||||
);
|
|
||||||
if (profileHideoutArea is null)
|
if (profileHideoutArea is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType));
|
||||||
serverLocalisationService.GetText("hideout-unable_to_find_area", request.AreaType)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
var hideoutDbData = databaseService
|
var hideoutDbData = databaseService.GetHideout().Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
||||||
.GetHideout()
|
|
||||||
.Areas.FirstOrDefault(area => area.Type == request.AreaType);
|
|
||||||
if (hideoutDbData is null)
|
if (hideoutDbData is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("hideout-unable_to_find_area_in_database", request.AreaType));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"hideout-unable_to_find_area_in_database",
|
|
||||||
request.AreaType
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output);
|
return httpResponseUtil.AppendErrorToOutput(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1577,11 +1307,7 @@ public class HideoutController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request">Cancel production request data</param>
|
/// <param name="request">Cancel production request data</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse CancelProduction(
|
public ItemEventRouterResponse CancelProduction(MongoId sessionId, PmcData pmcData, HideoutCancelProductionRequestData request)
|
||||||
MongoId sessionId,
|
|
||||||
PmcData pmcData,
|
|
||||||
HideoutCancelProductionRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -1647,21 +1373,15 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
var itemDetails = databaseService
|
var itemDetails = databaseService.GetHideout().Customisation.Globals.FirstOrDefault(cust => cust.Id == request.OfferId);
|
||||||
.GetHideout()
|
|
||||||
.Customisation.Globals.FirstOrDefault(cust => cust.Id == request.OfferId);
|
|
||||||
if (itemDetails is null)
|
if (itemDetails is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable to find customisation: {request.OfferId} in db, cannot apply to hideout");
|
||||||
$"Unable to find customisation: {request.OfferId} in db, cannot apply to hideout"
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmcData.Hideout.Customization[GetHideoutCustomisationType(itemDetails.Type)] = itemDetails
|
pmcData.Hideout.Customization[GetHideoutCustomisationType(itemDetails.Type)] = itemDetails.ItemId.Value;
|
||||||
.ItemId
|
|
||||||
.Value;
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -1734,9 +1454,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
Template = pmcData
|
Template = pmcData
|
||||||
.Inventory.Items.FirstOrDefault(item =>
|
.Inventory.Items.FirstOrDefault(item => item.SlotId == "Pockets" && item.ParentId == pmcData.Inventory.Equipment)
|
||||||
item.SlotId == "Pockets" && item.ParentId == pmcData.Inventory.Equipment
|
|
||||||
)
|
|
||||||
.Template, // Same pocket tpl as players profile (unheard get bigger, matching pockets etc)
|
.Template, // Same pocket tpl as players profile (unheard get bigger, matching pockets etc)
|
||||||
ParentId = standId,
|
ParentId = standId,
|
||||||
SlotId = "Pockets",
|
SlotId = "Pockets",
|
||||||
@@ -1763,9 +1481,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
if (request.Poses is null)
|
if (request.Poses is null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning("this really shouldnt be possible, but a request has come in with a pose change without poses");
|
||||||
"this really shouldnt be possible, but a request has come in with a pose change without poses"
|
|
||||||
);
|
|
||||||
return eventOutputHolder.GetOutput(sessionId);
|
return eventOutputHolder.GetOutput(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1800,10 +1516,7 @@ public class HideoutController(
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
profile.CharacterData.PmcData.Hideout is not null
|
profile.CharacterData.PmcData.Hideout is not null
|
||||||
&& profileActivityService.ActiveWithinLastMinutes(
|
&& profileActivityService.ActiveWithinLastMinutes(sessionId, _hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes)
|
||||||
sessionId,
|
|
||||||
_hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
hideoutHelper.UpdatePlayerHideout(sessionId);
|
hideoutHelper.UpdatePlayerHideout(sessionId);
|
||||||
|
|||||||
@@ -36,10 +36,7 @@ public class InRaidController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="offRaidProfileData"></param>
|
/// <param name="offRaidProfileData"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
public void SavePostRaidProfileForScav(
|
public void SavePostRaidProfileForScav(ScavSaveRequestData offRaidProfileData, MongoId sessionId)
|
||||||
ScavSaveRequestData offRaidProfileData,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var serverScavProfile = profileHelper.GetScavProfile(sessionId);
|
var serverScavProfile = profileHelper.GetScavProfile(sessionId);
|
||||||
|
|
||||||
|
|||||||
@@ -90,9 +90,7 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}");
|
||||||
$"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,9 +169,7 @@ public class InsuranceController(
|
|||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}");
|
||||||
$"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,11 +186,7 @@ public class InsuranceController(
|
|||||||
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
|
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
|
||||||
// and each of their attachments. For example, a gun mapped to each of its attachments.
|
// and each of their attachments. For example, a gun mapped to each of its attachments.
|
||||||
var itemsMap = insured.Items.GenerateItemsMap();
|
var itemsMap = insured.Items.GenerateItemsMap();
|
||||||
var parentAttachmentsMap = PopulateParentAttachmentsMap(
|
var parentAttachmentsMap = PopulateParentAttachmentsMap(rootItemParentId, insured, itemsMap);
|
||||||
rootItemParentId,
|
|
||||||
insured,
|
|
||||||
itemsMap
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check to see if any regular items are present.
|
// Check to see if any regular items are present.
|
||||||
var hasRegularItems = itemsMap.Values.Any(item => !itemHelper.IsAttachmentAttached(item));
|
var hasRegularItems = itemsMap.Values.Any(item => !itemHelper.IsAttachmentAttached(item));
|
||||||
@@ -278,11 +270,7 @@ public class InsuranceController(
|
|||||||
logger.Warning(
|
logger.Warning(
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText(
|
||||||
"insurance-unable_to_find_attachment_in_db",
|
"insurance-unable_to_find_attachment_in_db",
|
||||||
new
|
new { insuredItemId = insuredItem.Id, insuredItemTpl = insuredItem.Template }
|
||||||
{
|
|
||||||
insuredItemId = insuredItem.Id,
|
|
||||||
insuredItemTpl = insuredItem.Template,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -384,11 +372,7 @@ public class InsuranceController(
|
|||||||
/// <param name="insured">Insurance object containing the items to evaluate</param>
|
/// <param name="insured">Insurance object containing the items to evaluate</param>
|
||||||
/// <param name="toDelete">Hashset to keep track of items marked for deletion</param>
|
/// <param name="toDelete">Hashset to keep track of items marked for deletion</param>
|
||||||
/// <param name="parentAttachmentsMap">Dictionary containing parent item IDs to arrays of their attachment items</param>
|
/// <param name="parentAttachmentsMap">Dictionary containing parent item IDs to arrays of their attachment items</param>
|
||||||
protected void ProcessRegularItems(
|
protected void ProcessRegularItems(Insurance insured, HashSet<MongoId> toDelete, Dictionary<MongoId, List<Item>> parentAttachmentsMap)
|
||||||
Insurance insured,
|
|
||||||
HashSet<MongoId> toDelete,
|
|
||||||
Dictionary<MongoId, List<Item>> parentAttachmentsMap
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var insuredItem in insured.Items)
|
foreach (var insuredItem in insured.Items)
|
||||||
{
|
{
|
||||||
@@ -471,35 +455,23 @@ public class InsuranceController(
|
|||||||
/// <param name="attachments">Array of attachment items to sort, filter, and roll</param>
|
/// <param name="attachments">Array of attachment items to sort, filter, and roll</param>
|
||||||
/// <param name="traderId">ID of the trader to that has ensured these items</param>
|
/// <param name="traderId">ID of the trader to that has ensured these items</param>
|
||||||
/// <param name="toDelete">array that accumulates the IDs of the items to be deleted</param>
|
/// <param name="toDelete">array that accumulates the IDs of the items to be deleted</param>
|
||||||
protected void ProcessAttachmentByParent(
|
protected void ProcessAttachmentByParent(IEnumerable<Item> attachments, MongoId traderId, HashSet<MongoId> toDelete)
|
||||||
IEnumerable<Item> attachments,
|
|
||||||
MongoId traderId,
|
|
||||||
HashSet<MongoId> toDelete
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Create dict of item ids + their flea/handbook price (highest is chosen)
|
// Create dict of item ids + their flea/handbook price (highest is chosen)
|
||||||
var weightedAttachmentByPrice = WeightAttachmentsByPrice(attachments);
|
var weightedAttachmentByPrice = WeightAttachmentsByPrice(attachments);
|
||||||
|
|
||||||
// Get how many attachments we want to pull off parent
|
// Get how many attachments we want to pull off parent
|
||||||
var countOfAttachmentsToRemove = GetAttachmentCountToRemove(
|
var countOfAttachmentsToRemove = GetAttachmentCountToRemove(weightedAttachmentByPrice, traderId);
|
||||||
weightedAttachmentByPrice,
|
|
||||||
traderId
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create prob array and add all attachments with rouble price as the weight
|
// Create prob array and add all attachments with rouble price as the weight
|
||||||
var attachmentsProbabilityArray = new ProbabilityObjectArray<MongoId, double?>(cloner);
|
var attachmentsProbabilityArray = new ProbabilityObjectArray<MongoId, double?>(cloner);
|
||||||
foreach (var (itemTpl, price) in weightedAttachmentByPrice)
|
foreach (var (itemTpl, price) in weightedAttachmentByPrice)
|
||||||
{
|
{
|
||||||
attachmentsProbabilityArray.Add(
|
attachmentsProbabilityArray.Add(new ProbabilityObject<MongoId, double?>(itemTpl, price, null));
|
||||||
new ProbabilityObject<MongoId, double?>(itemTpl, price, null)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw x attachments from weighted array to remove from parent, remove from pool after being picked
|
// Draw x attachments from weighted array to remove from parent, remove from pool after being picked
|
||||||
var attachmentIdsToRemove = attachmentsProbabilityArray.Draw(
|
var attachmentIdsToRemove = attachmentsProbabilityArray.Draw((int)countOfAttachmentsToRemove, false);
|
||||||
(int)countOfAttachmentsToRemove,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
foreach (var attachmentId in attachmentIdsToRemove)
|
foreach (var attachmentId in attachmentIdsToRemove)
|
||||||
{
|
{
|
||||||
toDelete.Add(attachmentId);
|
toDelete.Add(attachmentId);
|
||||||
@@ -570,10 +542,7 @@ public class InsuranceController(
|
|||||||
/// <param name="weightedAttachmentByPrice">Dict of item Tpls and their rouble price</param>
|
/// <param name="weightedAttachmentByPrice">Dict of item Tpls and their rouble price</param>
|
||||||
/// <param name="traderId">Trader the attachment is insured against</param>
|
/// <param name="traderId">Trader the attachment is insured against</param>
|
||||||
/// <returns>Attachment count to remove</returns>
|
/// <returns>Attachment count to remove</returns>
|
||||||
protected double GetAttachmentCountToRemove(
|
protected double GetAttachmentCountToRemove(Dictionary<MongoId, double> weightedAttachmentByPrice, MongoId traderId)
|
||||||
Dictionary<MongoId, double> weightedAttachmentByPrice,
|
|
||||||
MongoId traderId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const int removeCount = 0;
|
const int removeCount = 0;
|
||||||
|
|
||||||
@@ -584,9 +553,7 @@ public class InsuranceController(
|
|||||||
|
|
||||||
// Get attachments count above or equal to price set in config
|
// Get attachments count above or equal to price set in config
|
||||||
return weightedAttachmentByPrice
|
return weightedAttachmentByPrice
|
||||||
.Where(attachment =>
|
.Where(attachment => attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken)
|
||||||
attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken
|
|
||||||
)
|
|
||||||
.Count(_ => RollForDelete(traderId) ?? false);
|
.Count(_ => RollForDelete(traderId) ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,12 +592,7 @@ public class InsuranceController(
|
|||||||
else if (insurance.Items?.Count == 0)
|
else if (insurance.Items?.Count == 0)
|
||||||
// Not labs and no items to return
|
// Not labs and no items to return
|
||||||
{
|
{
|
||||||
if (
|
if (traderDialogMessages.TryGetValue("insuranceFailed", out var insuranceFailedTemplates))
|
||||||
traderDialogMessages.TryGetValue(
|
|
||||||
"insuranceFailed",
|
|
||||||
out var insuranceFailedTemplates
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
insurance.MessageTemplateId = randomUtil.GetArrayValue(insuranceFailedTemplates);
|
insurance.MessageTemplateId = randomUtil.GetArrayValue(insuranceFailedTemplates);
|
||||||
}
|
}
|
||||||
@@ -656,11 +618,8 @@ public class InsuranceController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected bool IsMapLabsAndInsuranceDisabled(Insurance insurance, string labsId = "laboratory")
|
protected bool IsMapLabsAndInsuranceDisabled(Insurance insurance, string labsId = "laboratory")
|
||||||
{
|
{
|
||||||
return string.Equals(
|
return string.Equals(insurance.SystemData?.Location, labsId, StringComparison.OrdinalIgnoreCase)
|
||||||
insurance.SystemData?.Location,
|
&& !(databaseService.GetLocation(labsId)?.Base?.Insurance ?? false);
|
||||||
labsId,
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
) && !(databaseService.GetLocation(labsId)?.Base?.Insurance ?? false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -669,16 +628,10 @@ public class InsuranceController(
|
|||||||
/// <param name="insurance">The insured items to process</param>
|
/// <param name="insurance">The insured items to process</param>
|
||||||
/// <param name="labyrinthId">OPTIONAL - id of labyrinth location</param>
|
/// <param name="labyrinthId">OPTIONAL - id of labyrinth location</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected bool IsMapLabyrinthAndInsuranceDisabled(
|
protected bool IsMapLabyrinthAndInsuranceDisabled(Insurance insurance, string labyrinthId = "labyrinth")
|
||||||
Insurance insurance,
|
|
||||||
string labyrinthId = "labyrinth"
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return string.Equals(
|
return string.Equals(insurance.SystemData?.Location, labyrinthId, StringComparison.OrdinalIgnoreCase)
|
||||||
insurance.SystemData?.Location,
|
&& !(databaseService.GetLocation(labyrinthId)?.Base?.Insurance ?? false);
|
||||||
labyrinthId,
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
) && !(databaseService.GetLocation(labyrinthId)?.Base?.Insurance ?? false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -686,10 +639,7 @@ public class InsuranceController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="traderDialogMessages"></param>
|
/// <param name="traderDialogMessages"></param>
|
||||||
/// <param name="insurance"></param>
|
/// <param name="insurance"></param>
|
||||||
protected void HandleLabsInsurance(
|
protected void HandleLabsInsurance(Dictionary<string, List<string>?> traderDialogMessages, Insurance insurance)
|
||||||
Dictionary<string, List<string>?> traderDialogMessages,
|
|
||||||
Insurance insurance
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Use labs specific messages if available, otherwise use default
|
// Use labs specific messages if available, otherwise use default
|
||||||
if (!traderDialogMessages.TryGetValue("insuranceFailedLabs", out var responseMessageIds))
|
if (!traderDialogMessages.TryGetValue("insuranceFailedLabs", out var responseMessageIds))
|
||||||
@@ -708,17 +658,9 @@ public class InsuranceController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="traderDialogMessages"></param>
|
/// <param name="traderDialogMessages"></param>
|
||||||
/// <param name="insurance"></param>
|
/// <param name="insurance"></param>
|
||||||
protected void HandleLabyrinthInsurance(
|
protected void HandleLabyrinthInsurance(Dictionary<string, List<string>?> traderDialogMessages, Insurance insurance)
|
||||||
Dictionary<string, List<string>?> traderDialogMessages,
|
|
||||||
Insurance insurance
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (
|
if (!traderDialogMessages.TryGetValue("insuranceFailedLabyrinth", out var responseMessageIds))
|
||||||
!traderDialogMessages.TryGetValue(
|
|
||||||
"insuranceFailedLabyrinth",
|
|
||||||
out var responseMessageIds
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
traderDialogMessages.TryGetValue("insuranceFailed", out responseMessageIds);
|
traderDialogMessages.TryGetValue("insuranceFailed", out responseMessageIds);
|
||||||
}
|
}
|
||||||
@@ -751,15 +693,11 @@ public class InsuranceController(
|
|||||||
var roll = returnChance >= traderReturnChance;
|
var roll = returnChance >= traderReturnChance;
|
||||||
|
|
||||||
// Log the roll with as much detail as possible.
|
// Log the roll with as much detail as possible.
|
||||||
var itemName = insuredItem is not null
|
var itemName = insuredItem is not null ? $"{itemHelper.GetItemName(insuredItem.Template)}" : "";
|
||||||
? $"{itemHelper.GetItemName(insuredItem.Template)}"
|
|
||||||
: "";
|
|
||||||
var status = roll ? "Delete" : "Keep";
|
var status = roll ? "Delete" : "Keep";
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}");
|
||||||
$"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return roll;
|
return roll;
|
||||||
@@ -772,11 +710,7 @@ public class InsuranceController(
|
|||||||
/// <param name="request">Insurance request</param>
|
/// <param name="request">Insurance request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse object to send to client</returns>
|
/// <returns>ItemEventRouterResponse object to send to client</returns>
|
||||||
public ItemEventRouterResponse Insure(
|
public ItemEventRouterResponse Insure(PmcData pmcData, InsureRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InsureRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
var itemsToInsureCount = request.Items.Count;
|
var itemsToInsureCount = request.Items.Count;
|
||||||
@@ -792,11 +726,7 @@ public class InsuranceController(
|
|||||||
new IdWithCount
|
new IdWithCount
|
||||||
{
|
{
|
||||||
Id = Money.ROUBLES, // TODO: update to handle different currencies
|
Id = Money.ROUBLES, // TODO: update to handle different currencies
|
||||||
Count = insuranceService.GetRoublePriceToInsureItemWithTrader(
|
Count = insuranceService.GetRoublePriceToInsureItemWithTrader(pmcData, inventoryItemsHash[key], request.TransactionId),
|
||||||
pmcData,
|
|
||||||
inventoryItemsHash[key],
|
|
||||||
request.TransactionId
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -824,9 +754,7 @@ public class InsuranceController(
|
|||||||
foreach (var key in request.Items)
|
foreach (var key in request.Items)
|
||||||
{
|
{
|
||||||
var inventoryItem = inventoryItemsHash.GetValueOrDefault(key);
|
var inventoryItem = inventoryItemsHash.GetValueOrDefault(key);
|
||||||
pmcData.InsuredItems.Add(
|
pmcData.InsuredItems.Add(new InsuredItem { TId = request.TransactionId, ItemId = inventoryItem.Id });
|
||||||
new InsuredItem { TId = request.TransactionId, ItemId = inventoryItem.Id }
|
|
||||||
);
|
|
||||||
// If Item is Helmet or Body Armour -> Handle insurance of soft inserts
|
// If Item is Helmet or Body Armour -> Handle insurance of soft inserts
|
||||||
if (itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(inventoryItem.Template))
|
if (itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(inventoryItem.Template))
|
||||||
{
|
{
|
||||||
@@ -834,11 +762,7 @@ public class InsuranceController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profileHelper.AddSkillPointsToPlayer(
|
profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.Charisma, itemsToInsureCount * 0.01);
|
||||||
pmcData,
|
|
||||||
SkillTypes.Charisma,
|
|
||||||
itemsToInsureCount * 0.01
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -849,15 +773,10 @@ public class InsuranceController(
|
|||||||
/// <param name="itemWithSoftInserts">Armor item to be insured</param>
|
/// <param name="itemWithSoftInserts">Armor item to be insured</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request">Insurance request data</param>
|
/// <param name="request">Insurance request data</param>
|
||||||
public void InsureSoftInserts(
|
public void InsureSoftInserts(Item itemWithSoftInserts, PmcData pmcData, InsureRequestData request)
|
||||||
Item itemWithSoftInserts,
|
|
||||||
PmcData pmcData,
|
|
||||||
InsureRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var softInsertSlots = pmcData.Inventory.Items.Where(item =>
|
var softInsertSlots = pmcData.Inventory.Items.Where(item =>
|
||||||
item.ParentId == itemWithSoftInserts.Id
|
item.ParentId == itemWithSoftInserts.Id && itemHelper.IsSoftInsertId(item.SlotId.ToLowerInvariant())
|
||||||
&& itemHelper.IsSoftInsertId(item.SlotId.ToLowerInvariant())
|
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (var softInsertSlot in softInsertSlots)
|
foreach (var softInsertSlot in softInsertSlots)
|
||||||
@@ -867,9 +786,7 @@ public class InsuranceController(
|
|||||||
logger.Debug($"SoftInsertSlots: {softInsertSlot.SlotId}");
|
logger.Debug($"SoftInsertSlots: {softInsertSlot.SlotId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
pmcData.InsuredItems.Add(
|
pmcData.InsuredItems.Add(new InsuredItem { TId = request.TransactionId, ItemId = softInsertSlot.Id });
|
||||||
new InsuredItem { TId = request.TransactionId, ItemId = softInsertSlot.Id }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,9 +817,7 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Item with id: {itemId} missing from player inventory, skipping");
|
||||||
$"Item with id: {itemId} missing from player inventory, skipping"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -911,11 +826,7 @@ public class InsuranceController(
|
|||||||
if (
|
if (
|
||||||
!traderItems.TryAdd(
|
!traderItems.TryAdd(
|
||||||
inventoryItem.Template,
|
inventoryItem.Template,
|
||||||
insuranceService.GetRoublePriceToInsureItemWithTrader(
|
insuranceService.GetRoublePriceToInsureItemWithTrader(pmcData, inventoryItem, traderId)
|
||||||
pmcData,
|
|
||||||
inventoryItem,
|
|
||||||
traderId
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,12 +44,7 @@ public class InventoryController(
|
|||||||
/// <param name="moveRequest">Move request data</param>
|
/// <param name="moveRequest">Move request data</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void MoveItem(
|
public void MoveItem(PmcData pmcData, InventoryMoveRequestData moveRequest, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryMoveRequestData moveRequest,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -57,27 +52,18 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var ownerInventoryItems = inventoryHelper.GetOwnerInventoryItems(
|
var ownerInventoryItems = inventoryHelper.GetOwnerInventoryItems(moveRequest, moveRequest.Item.Value, sessionId);
|
||||||
moveRequest,
|
|
||||||
moveRequest.Item.Value,
|
|
||||||
sessionId
|
|
||||||
);
|
|
||||||
if (ownerInventoryItems.SameInventory.GetValueOrDefault(false))
|
if (ownerInventoryItems.SameInventory.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
// Don't move items from trader to profile, this can happen when editing a traders preset weapons
|
// Don't move items from trader to profile, this can happen when editing a traders preset weapons
|
||||||
if (
|
if (moveRequest.FromOwner?.Type == "Trader" && !ownerInventoryItems.IsMail.GetValueOrDefault(false))
|
||||||
moveRequest.FromOwner?.Type == "Trader"
|
|
||||||
&& !ownerInventoryItems.IsMail.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
AppendTraderExploitErrorResponse(output);
|
AppendTraderExploitErrorResponse(output);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for item in inventory before allowing internal transfer
|
// Check for item in inventory before allowing internal transfer
|
||||||
var originalItemLocation = ownerInventoryItems.From?.FirstOrDefault(item =>
|
var originalItemLocation = ownerInventoryItems.From?.FirstOrDefault(item => item.Id == moveRequest.Item);
|
||||||
item.Id == moveRequest.Item
|
|
||||||
);
|
|
||||||
if (originalItemLocation is null)
|
if (originalItemLocation is null)
|
||||||
{
|
{
|
||||||
// Internal item move but item never existed, possible dupe glitch
|
// Internal item move but item never existed, possible dupe glitch
|
||||||
@@ -87,12 +73,7 @@ public class InventoryController(
|
|||||||
|
|
||||||
var originalLocationSlotId = originalItemLocation.SlotId;
|
var originalLocationSlotId = originalItemLocation.SlotId;
|
||||||
|
|
||||||
var moveResult = inventoryHelper.MoveItemInternal(
|
var moveResult = inventoryHelper.MoveItemInternal(pmcData, ownerInventoryItems.From ?? [], moveRequest, out var errorMessage);
|
||||||
pmcData,
|
|
||||||
ownerInventoryItems.From ?? [],
|
|
||||||
moveRequest,
|
|
||||||
out var errorMessage
|
|
||||||
);
|
|
||||||
if (!moveResult)
|
if (!moveResult)
|
||||||
{
|
{
|
||||||
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -103,14 +84,8 @@ public class InventoryController(
|
|||||||
if (
|
if (
|
||||||
moveRequest.To?.Container != null
|
moveRequest.To?.Container != null
|
||||||
&& (
|
&& (
|
||||||
moveRequest.To.Container.StartsWith(
|
moveRequest.To.Container.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase)
|
||||||
"dogtag",
|
|| originalLocationSlotId.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase)
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
)
|
|
||||||
|| originalLocationSlotId.StartsWith(
|
|
||||||
"dogtag",
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -119,11 +94,7 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inventoryHelper.MoveItemToProfile(
|
inventoryHelper.MoveItemToProfile(ownerInventoryItems.From ?? [], ownerInventoryItems.To ?? [], moveRequest);
|
||||||
ownerInventoryItems.From ?? [],
|
|
||||||
ownerInventoryItems.To ?? [],
|
|
||||||
moveRequest
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,21 +119,12 @@ public class InventoryController(
|
|||||||
/// <param name="request">Pin/Lock request data</param>
|
/// <param name="request">Pin/Lock request data</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void PinOrLock(
|
public void PinOrLock(PmcData pmcData, PinOrLockItemRequest request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
PinOrLockItemRequest request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item =>
|
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item => item.Id == request.Item);
|
||||||
item.Id == request.Item
|
|
||||||
);
|
|
||||||
if (itemToAdjust is null)
|
if (itemToAdjust is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable find item: {request.Item.Value.ToString()} to: {request.State} on player: {sessionId} to: ");
|
||||||
$"Unable find item: {request.Item.Value.ToString()} to: {request.State} on player: {sessionId} to: "
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -192,11 +154,7 @@ public class InventoryController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
public void RedeemProfileReward(
|
public void RedeemProfileReward(PmcData pmcData, RedeemProfileRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
RedeemProfileRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var fullProfile = profileHelper.GetFullProfile(sessionId);
|
var fullProfile = profileHelper.GetFullProfile(sessionId);
|
||||||
foreach (var rewardEvent in request.Events)
|
foreach (var rewardEvent in request.Events)
|
||||||
@@ -204,28 +162,20 @@ public class InventoryController(
|
|||||||
// Hard coded to `SYSTEM` for now
|
// Hard coded to `SYSTEM` for now
|
||||||
// TODO: make this dynamic
|
// TODO: make this dynamic
|
||||||
var dialog = fullProfile.DialogueRecords["59e7125688a45068a6249071"];
|
var dialog = fullProfile.DialogueRecords["59e7125688a45068a6249071"];
|
||||||
var mail = dialog.Messages.FirstOrDefault(message =>
|
var mail = dialog.Messages.FirstOrDefault(message => message.Id == rewardEvent.MessageId);
|
||||||
message.Id == rewardEvent.MessageId
|
var mailEvent = mail.ProfileChangeEvents.FirstOrDefault(changeEvent => changeEvent.Id == rewardEvent.EventId);
|
||||||
);
|
|
||||||
var mailEvent = mail.ProfileChangeEvents.FirstOrDefault(changeEvent =>
|
|
||||||
changeEvent.Id == rewardEvent.EventId
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (mailEvent.Type)
|
switch (mailEvent.Type)
|
||||||
{
|
{
|
||||||
case "TraderSalesSum":
|
case "TraderSalesSum":
|
||||||
pmcData.TradersInfo[mailEvent.Entity].SalesSum = mailEvent.Value;
|
pmcData.TradersInfo[mailEvent.Entity].SalesSum = mailEvent.Value;
|
||||||
traderHelper.LevelUp(mailEvent.Entity, pmcData);
|
traderHelper.LevelUp(mailEvent.Entity, pmcData);
|
||||||
logger.Success(
|
logger.Success($"Set trader {mailEvent.Entity}: Sales Sum to: {mailEvent.Value}");
|
||||||
$"Set trader {mailEvent.Entity}: Sales Sum to: {mailEvent.Value}"
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "TraderStanding":
|
case "TraderStanding":
|
||||||
pmcData.TradersInfo[mailEvent.Entity].Standing = mailEvent.Value;
|
pmcData.TradersInfo[mailEvent.Entity].Standing = mailEvent.Value;
|
||||||
traderHelper.LevelUp(mailEvent.Entity, pmcData);
|
traderHelper.LevelUp(mailEvent.Entity, pmcData);
|
||||||
logger.Success(
|
logger.Success($"Set trader {mailEvent.Entity}: Standing to: {mailEvent.Value}");
|
||||||
$"Set trader {mailEvent.Entity}: Standing to: {mailEvent.Value}"
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "ProfileLevel":
|
case "ProfileLevel":
|
||||||
pmcData.Info.Experience = (int)mailEvent.Value.Value;
|
pmcData.Info.Experience = (int)mailEvent.Value.Value;
|
||||||
@@ -235,9 +185,7 @@ public class InventoryController(
|
|||||||
break;
|
break;
|
||||||
case "SkillPoints":
|
case "SkillPoints":
|
||||||
{
|
{
|
||||||
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x =>
|
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x => x.Id == Enum.Parse<SkillTypes>(mailEvent.Entity));
|
||||||
x.Id == Enum.Parse<SkillTypes>(mailEvent.Entity)
|
|
||||||
);
|
|
||||||
if (profileSkill is null)
|
if (profileSkill is null)
|
||||||
{
|
{
|
||||||
logger.Warning($"Unable to find skill with name: {mailEvent.Entity}");
|
logger.Warning($"Unable to find skill with name: {mailEvent.Entity}");
|
||||||
@@ -250,10 +198,7 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
case "ExamineAllItems":
|
case "ExamineAllItems":
|
||||||
{
|
{
|
||||||
var itemIds = databaseService
|
var itemIds = databaseService.GetItems().Where(x => x.Value.Type != "Node").Select(x => x.Key);
|
||||||
.GetItems()
|
|
||||||
.Where(x => x.Value.Type != "Node")
|
|
||||||
.Select(x => x.Key);
|
|
||||||
FlagItemsAsInspectedAndRewardXp(itemIds, fullProfile);
|
FlagItemsAsInspectedAndRewardXp(itemIds, fullProfile);
|
||||||
logger.Success($"Flagged {itemIds.Count()} items as examined");
|
logger.Success($"Flagged {itemIds.Count()} items as examined");
|
||||||
|
|
||||||
@@ -276,9 +221,7 @@ public class InventoryController(
|
|||||||
var newValue = mailEvent.Value;
|
var newValue = mailEvent.Value;
|
||||||
var hideoutAreaType = Enum.Parse<HideoutAreas>(areaName ?? "NotSet");
|
var hideoutAreaType = Enum.Parse<HideoutAreas>(areaName ?? "NotSet");
|
||||||
|
|
||||||
var desiredArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
var desiredArea = pmcData.Hideout.Areas.FirstOrDefault(area => area.Type == hideoutAreaType);
|
||||||
area.Type == hideoutAreaType
|
|
||||||
);
|
|
||||||
if (desiredArea is not null)
|
if (desiredArea is not null)
|
||||||
{
|
{
|
||||||
desiredArea.Level = (int?)newValue;
|
desiredArea.Level = (int?)newValue;
|
||||||
@@ -299,43 +242,27 @@ public class InventoryController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="itemTpls">Inspected item tpls</param>
|
/// <param name="itemTpls">Inspected item tpls</param>
|
||||||
/// <param name="fullProfile">Profile to add xp to</param>
|
/// <param name="fullProfile">Profile to add xp to</param>
|
||||||
protected void FlagItemsAsInspectedAndRewardXp(
|
protected void FlagItemsAsInspectedAndRewardXp(IEnumerable<MongoId> itemTpls, SptProfile fullProfile)
|
||||||
IEnumerable<MongoId> itemTpls,
|
|
||||||
SptProfile fullProfile
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var itemTpl in itemTpls)
|
foreach (var itemTpl in itemTpls)
|
||||||
{
|
{
|
||||||
var item = itemHelper.GetItem(itemTpl);
|
var item = itemHelper.GetItem(itemTpl);
|
||||||
if (!item.Key)
|
if (!item.Key)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("inventory-unable_to_inspect_item_not_in_db", itemTpl));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"inventory-unable_to_inspect_item_not_in_db",
|
|
||||||
itemTpl
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullProfile.CharacterData.PmcData.Info.Experience += item.Value
|
fullProfile.CharacterData.PmcData.Info.Experience += item.Value.Properties.ExamineExperience;
|
||||||
.Properties
|
|
||||||
.ExamineExperience;
|
|
||||||
fullProfile.CharacterData.PmcData.Encyclopedia[itemTpl] = false;
|
fullProfile.CharacterData.PmcData.Encyclopedia[itemTpl] = false;
|
||||||
|
|
||||||
fullProfile.CharacterData.ScavData.Info.Experience += item.Value
|
fullProfile.CharacterData.ScavData.Info.Experience += item.Value.Properties.ExamineExperience;
|
||||||
.Properties
|
|
||||||
.ExamineExperience;
|
|
||||||
fullProfile.CharacterData.ScavData.Encyclopedia[itemTpl] = false;
|
fullProfile.CharacterData.ScavData.Encyclopedia[itemTpl] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update this with correct calculation using values from globals json
|
// TODO: update this with correct calculation using values from globals json
|
||||||
profileHelper.AddSkillPointsToPlayer(
|
profileHelper.AddSkillPointsToPlayer(fullProfile.CharacterData.PmcData, SkillTypes.Intellect, 0.05 * itemTpls.Count());
|
||||||
fullProfile.CharacterData.PmcData,
|
|
||||||
SkillTypes.Intellect,
|
|
||||||
0.05 * itemTpls.Count()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -379,14 +306,10 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rewardContainerDetails = inventoryHelper.GetRandomLootContainerRewardDetails(
|
var rewardContainerDetails = inventoryHelper.GetRandomLootContainerRewardDetails(openedItem.Template);
|
||||||
openedItem.Template
|
|
||||||
);
|
|
||||||
if (rewardContainerDetails?.RewardCount == null)
|
if (rewardContainerDetails?.RewardCount == null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable to add loot to container: {openedItem.Template}, no rewards found");
|
||||||
$"Unable to add loot to container: {openedItem.Template}, no rewards found"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -427,12 +350,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Edit marker request</param>
|
/// <param name="request">Edit marker request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void EditMapMarker(
|
public void EditMapMarker(PmcData pmcData, InventoryEditMarkerRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryEditMarkerRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var mapItem = mapMarkerService.EditMarkerOnMap(pmcData, request);
|
var mapItem = mapMarkerService.EditMarkerOnMap(pmcData, request);
|
||||||
|
|
||||||
@@ -480,26 +398,14 @@ public class InventoryController(
|
|||||||
/// <param name="request">Add marker request</param>
|
/// <param name="request">Add marker request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void SortInventory(
|
public void SortInventory(PmcData pmcData, InventorySortRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventorySortRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var change in request.ChangedItems)
|
foreach (var change in request.ChangedItems)
|
||||||
{
|
{
|
||||||
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item =>
|
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == change.Id);
|
||||||
item.Id == change.Id
|
|
||||||
);
|
|
||||||
if (inventoryItem is null)
|
if (inventoryItem is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("inventory-unable_to_sort_inventory_restart_game", change.Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"inventory-unable_to_sort_inventory_restart_game",
|
|
||||||
change.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -517,11 +423,7 @@ public class InventoryController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ReadEncyclopedia(
|
public ItemEventRouterResponse ReadEncyclopedia(PmcData pmcData, InventoryReadEncyclopediaRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryReadEncyclopediaRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var id in request.Ids)
|
foreach (var id in request.Ids)
|
||||||
{
|
{
|
||||||
@@ -538,12 +440,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Examine item request</param>
|
/// <param name="request">Examine item request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void ExamineItem(
|
public void ExamineItem(PmcData pmcData, InventoryExamineRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryExamineRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
MongoId? itemId = null;
|
MongoId? itemId = null;
|
||||||
if (request.FromOwner is not null)
|
if (request.FromOwner is not null)
|
||||||
@@ -554,12 +451,7 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("inventory-examine_item_does_not_exist", request.ItemId));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"inventory-examine_item_does_not_exist",
|
|
||||||
request.ItemId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -605,10 +497,7 @@ public class InventoryController(
|
|||||||
if (request.FromOwner.Id == Traders.FENCE)
|
if (request.FromOwner.Id == Traders.FENCE)
|
||||||
// Get tpl from fence assorts
|
// Get tpl from fence assorts
|
||||||
{
|
{
|
||||||
return fenceService
|
return fenceService.GetRawFenceAssorts().Items.FirstOrDefault(x => x.Id == request.ItemId)?.Template;
|
||||||
.GetRawFenceAssorts()
|
|
||||||
.Items.FirstOrDefault(x => x.Id == request.ItemId)
|
|
||||||
?.Template;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.FromOwner.Type == "Trader")
|
if (request.FromOwner.Type == "Trader")
|
||||||
@@ -632,22 +521,17 @@ public class InventoryController(
|
|||||||
|
|
||||||
// Try alternate way of getting offer if first approach fails
|
// Try alternate way of getting offer if first approach fails
|
||||||
var offer =
|
var offer =
|
||||||
ragfairOfferService.GetOfferByOfferId(request.ItemId)
|
ragfairOfferService.GetOfferByOfferId(request.ItemId) ?? ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id.Value);
|
||||||
?? ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id.Value);
|
|
||||||
|
|
||||||
// Try find examine item inside offer items array
|
// Try find examine item inside offer items array
|
||||||
var matchingItem = offer.Items.FirstOrDefault(offerItem =>
|
var matchingItem = offer.Items.FirstOrDefault(offerItem => offerItem.Id == request.ItemId);
|
||||||
offerItem.Id == request.ItemId
|
|
||||||
);
|
|
||||||
if (matchingItem is not null)
|
if (matchingItem is not null)
|
||||||
{
|
{
|
||||||
return matchingItem.Template;
|
return matchingItem.Template;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unable to find item in database or ragfair
|
// Unable to find item in database or ragfair
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("inventory-unable_to_find_item", request.ItemId));
|
||||||
serverLocalisationService.GetText("inventory-unable_to_find_item", request.ItemId)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get hideout item
|
// get hideout item
|
||||||
@@ -662,9 +546,7 @@ public class InventoryController(
|
|||||||
// all mail the player has
|
// all mail the player has
|
||||||
var mail = profileHelper.GetFullProfile(sessionId).DialogueRecords;
|
var mail = profileHelper.GetFullProfile(sessionId).DialogueRecords;
|
||||||
// per trader/person mail
|
// per trader/person mail
|
||||||
var dialogue = mail.FirstOrDefault(x =>
|
var dialogue = mail.FirstOrDefault(x => x.Value.Messages.Any(m => m.Id == request.FromOwner.Id));
|
||||||
x.Value.Messages.Any(m => m.Id == request.FromOwner.Id)
|
|
||||||
);
|
|
||||||
// check each message from that trader/person for messages that match the ID we got
|
// check each message from that trader/person for messages that match the ID we got
|
||||||
var message = dialogue.Value.Messages.FirstOrDefault(m => m.Id == request.FromOwner.Id);
|
var message = dialogue.Value.Messages.FirstOrDefault(m => m.Id == request.FromOwner.Id);
|
||||||
// get the Id given and get the Template ID from that
|
// get the Id given and get the Template ID from that
|
||||||
@@ -689,12 +571,7 @@ public class InventoryController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void UnBindItem(
|
public void UnBindItem(PmcData pmcData, InventoryBindRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryBindRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Remove kvp from requested fast panel index
|
// Remove kvp from requested fast panel index
|
||||||
|
|
||||||
@@ -710,12 +587,7 @@ public class InventoryController(
|
|||||||
/// <param name="bindRequest"></param>
|
/// <param name="bindRequest"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void BindItem(
|
public void BindItem(PmcData pmcData, InventoryBindRequestData bindRequest, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryBindRequestData bindRequest,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Remove link
|
// Remove link
|
||||||
pmcData.Inventory.FastPanel.Remove(bindRequest.Index);
|
pmcData.Inventory.FastPanel.Remove(bindRequest.Index);
|
||||||
@@ -731,18 +603,12 @@ public class InventoryController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse TagItem(
|
public ItemEventRouterResponse TagItem(PmcData pmcData, InventoryTagRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryTagRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var itemToTag = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
|
var itemToTag = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
|
||||||
if (itemToTag is null)
|
if (itemToTag is null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Unable to tag item: {request.Item} as it cannot be found in player {sessionId} inventory");
|
||||||
$"Unable to tag item: {request.Item} as it cannot be found in player {sessionId} inventory"
|
|
||||||
);
|
|
||||||
|
|
||||||
return new ItemEventRouterResponse { Warnings = [] };
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
}
|
}
|
||||||
@@ -762,11 +628,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Toggle request</param>
|
/// <param name="request">Toggle request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse ToggleItem(
|
public ItemEventRouterResponse ToggleItem(PmcData pmcData, InventoryToggleRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryToggleRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// May need to reassign to scav profile
|
// May need to reassign to scav profile
|
||||||
var playerData = pmcData;
|
var playerData = pmcData;
|
||||||
@@ -782,10 +644,7 @@ public class InventoryController(
|
|||||||
{
|
{
|
||||||
itemHelper.AddUpdObjectToItem(
|
itemHelper.AddUpdObjectToItem(
|
||||||
itemToToggle,
|
itemToToggle,
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText("inventory-item_to_toggle_missing_upd", itemToToggle.Id)
|
||||||
"inventory-item_to_toggle_missing_upd",
|
|
||||||
itemToToggle.Id
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
itemToToggle.Upd.Togglable = new UpdTogglable { On = request.Value };
|
itemToToggle.Upd.Togglable = new UpdTogglable { On = request.Value };
|
||||||
@@ -793,12 +652,7 @@ public class InventoryController(
|
|||||||
return eventOutputHolder.GetOutput(sessionId);
|
return eventOutputHolder.GetOutput(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("inventory-unable_to_toggle_item_not_found", request.Item));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"inventory-unable_to_toggle_item_not_found",
|
|
||||||
request.Item
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return new ItemEventRouterResponse { Warnings = [] };
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
}
|
}
|
||||||
@@ -810,11 +664,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Fold item request</param>
|
/// <param name="request">Fold item request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse FoldItem(
|
public ItemEventRouterResponse FoldItem(PmcData pmcData, InventoryFoldRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryFoldRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// May need to reassign to scav profile
|
// May need to reassign to scav profile
|
||||||
var playerData = pmcData;
|
var playerData = pmcData;
|
||||||
@@ -829,12 +679,7 @@ public class InventoryController(
|
|||||||
if (itemToFold is null)
|
if (itemToFold is null)
|
||||||
{
|
{
|
||||||
// Item not found
|
// Item not found
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("inventory-unable_to_fold_item_not_found_in_inventory", request.Item));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"inventory-unable_to_fold_item_not_found_in_inventory",
|
|
||||||
request.Item
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return new ItemEventRouterResponse { Warnings = [] };
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
}
|
}
|
||||||
@@ -856,11 +701,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Swap item request</param>
|
/// <param name="request">Swap item request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse SwapItem(
|
public ItemEventRouterResponse SwapItem(PmcData pmcData, InventorySwapRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
InventorySwapRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// During post-raid scav transfer, the swap may be in the scav inventory
|
// During post-raid scav transfer, the swap may be in the scav inventory
|
||||||
var playerData = pmcData;
|
var playerData = pmcData;
|
||||||
@@ -917,19 +758,10 @@ public class InventoryController(
|
|||||||
/// <param name="request">Transfer item request</param>
|
/// <param name="request">Transfer item request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void TransferItem(
|
public void TransferItem(PmcData pmcData, InventoryTransferRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryTransferRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// TODO - check GetOwnerInventoryItems() call still works
|
// TODO - check GetOwnerInventoryItems() call still works
|
||||||
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(
|
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionId);
|
||||||
request,
|
|
||||||
request.Item,
|
|
||||||
sessionId
|
|
||||||
);
|
|
||||||
var sourceItem = inventoryItems.From.FirstOrDefault(item => item.Id == request.Item);
|
var sourceItem = inventoryItems.From.FirstOrDefault(item => item.Id == request.Item);
|
||||||
var destinationItem = inventoryItems.To.FirstOrDefault(item => item.Id == request.With);
|
var destinationItem = inventoryItems.To.FirstOrDefault(item => item.Id == request.With);
|
||||||
|
|
||||||
@@ -981,26 +813,16 @@ public class InventoryController(
|
|||||||
/// <param name="request">Merge stacks request</param>
|
/// <param name="request">Merge stacks request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void MergeItem(
|
public void MergeItem(PmcData pmcData, InventoryMergeRequestData request, MongoId sessionID, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryMergeRequestData request,
|
|
||||||
MongoId sessionID,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(
|
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionID);
|
||||||
request,
|
|
||||||
request.Item,
|
|
||||||
sessionID
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get source item (can be from player or trader or mail)
|
// Get source item (can be from player or trader or mail)
|
||||||
var sourceItem = inventoryItems.From.FirstOrDefault(x => x.Id == request.Item);
|
var sourceItem = inventoryItems.From.FirstOrDefault(x => x.Id == request.Item);
|
||||||
if (sourceItem is null)
|
if (sourceItem is null)
|
||||||
{
|
{
|
||||||
var errorMessage =
|
var errorMessage = $"Unable to merge stacks as source item: {request.With} cannot be found";
|
||||||
$"Unable to merge stacks as source item: {request.With} cannot be found";
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -1012,8 +834,7 @@ public class InventoryController(
|
|||||||
var destinationItem = inventoryItems.To.FirstOrDefault(x => x.Id == request.With);
|
var destinationItem = inventoryItems.To.FirstOrDefault(x => x.Id == request.With);
|
||||||
if (destinationItem is null)
|
if (destinationItem is null)
|
||||||
{
|
{
|
||||||
var errorMessage =
|
var errorMessage = $"Unable to merge stacks as destination item: {request.With} cannot be found";
|
||||||
$"Unable to merge stacks as destination item: {request.With} cannot be found";
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -1038,24 +859,18 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove FiR status from destination stack when source stack has no FiR but destination does
|
// Remove FiR status from destination stack when source stack has no FiR but destination does
|
||||||
if (
|
if (!sourceItem.Upd.SpawnedInSession.GetValueOrDefault(false) && destinationItem.Upd.SpawnedInSession.GetValueOrDefault(false))
|
||||||
!sourceItem.Upd.SpawnedInSession.GetValueOrDefault(false)
|
|
||||||
&& destinationItem.Upd.SpawnedInSession.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
destinationItem.Upd.SpawnedInSession = false;
|
destinationItem.Upd.SpawnedInSession = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
destinationItem.Upd.StackObjectsCount += sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
|
destinationItem.Upd.StackObjectsCount += sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
|
||||||
output
|
output.ProfileChanges[sessionID].Items.DeletedItems.Add(new DeletedItem { Id = sourceItem.Id }); // Inform client source item being deleted
|
||||||
.ProfileChanges[sessionID]
|
|
||||||
.Items.DeletedItems.Add(new DeletedItem { Id = sourceItem.Id }); // Inform client source item being deleted
|
|
||||||
|
|
||||||
var indexOfItemToRemove = inventoryItems.From.FindIndex(x => x.Id == sourceItem.Id);
|
var indexOfItemToRemove = inventoryItems.From.FindIndex(x => x.Id == sourceItem.Id);
|
||||||
if (indexOfItemToRemove == -1)
|
if (indexOfItemToRemove == -1)
|
||||||
{
|
{
|
||||||
var errorMessage =
|
var errorMessage = $"Unable to find item: {sourceItem.Id} to remove from sender inventory";
|
||||||
$"Unable to find item: {sourceItem.Id} to remove from sender inventory";
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -1073,19 +888,10 @@ public class InventoryController(
|
|||||||
/// <param name="request">Split stack request</param>
|
/// <param name="request">Split stack request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void SplitItem(
|
public void SplitItem(PmcData pmcData, InventorySplitRequestData request, MongoId sessionID, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventorySplitRequestData request,
|
|
||||||
MongoId sessionID,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(
|
var inventoryItems = inventoryHelper.GetOwnerInventoryItems(request, request.NewItem.Value, sessionID);
|
||||||
request,
|
|
||||||
request.NewItem.Value,
|
|
||||||
sessionID
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle cartridge edge-case
|
// Handle cartridge edge-case
|
||||||
if (request.Container.Location is null && request.Container.ContainerName == "cartridges")
|
if (request.Container.Location is null && request.Container.ContainerName == "cartridges")
|
||||||
@@ -1098,8 +904,7 @@ public class InventoryController(
|
|||||||
var itemToSplit = inventoryItems.From.FirstOrDefault(x => x.Id == request.SplitItem);
|
var itemToSplit = inventoryItems.From.FirstOrDefault(x => x.Id == request.SplitItem);
|
||||||
if (itemToSplit is null)
|
if (itemToSplit is null)
|
||||||
{
|
{
|
||||||
var errorMessage =
|
var errorMessage = $"Unable to split stack as source item: {request.SplitItem} cannot be found";
|
||||||
$"Unable to split stack as source item: {request.SplitItem} cannot be found";
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -1148,12 +953,7 @@ public class InventoryController(
|
|||||||
/// <param name="request">Discard item request</param>
|
/// <param name="request">Discard item request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void DiscardItem(
|
public void DiscardItem(PmcData pmcData, InventoryRemoveRequestData request, MongoId sessionId, ItemEventRouterResponse output)
|
||||||
PmcData pmcData,
|
|
||||||
InventoryRemoveRequestData request,
|
|
||||||
MongoId sessionId,
|
|
||||||
ItemEventRouterResponse output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (request.FromOwner?.Type == "Mail")
|
if (request.FromOwner?.Type == "Mail")
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ public class LauncherController(
|
|||||||
// Get all possible profile types + filter out any that are blacklisted
|
// Get all possible profile types + filter out any that are blacklisted
|
||||||
var profileTemplates = databaseService
|
var profileTemplates = databaseService
|
||||||
.GetProfileTemplates()
|
.GetProfileTemplates()
|
||||||
.Where(profile =>
|
.Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key))
|
||||||
!_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key)
|
|
||||||
)
|
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
|
|
||||||
return new ConnectResponse
|
return new ConnectResponse
|
||||||
@@ -57,17 +55,12 @@ public class LauncherController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="profileTemplates">Profiles to get descriptions of</param>
|
/// <param name="profileTemplates">Profiles to get descriptions of</param>
|
||||||
/// <returns>Dictionary of profile types with related descriptive text</returns>
|
/// <returns>Dictionary of profile types with related descriptive text</returns>
|
||||||
protected Dictionary<string, string> GetProfileDescriptions(
|
protected Dictionary<string, string> GetProfileDescriptions(Dictionary<string, ProfileSides> profileTemplates)
|
||||||
Dictionary<string, ProfileSides> profileTemplates
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var result = new Dictionary<string, string>();
|
var result = new Dictionary<string, string>();
|
||||||
foreach (var (profileKey, profile) in profileTemplates)
|
foreach (var (profileKey, profile) in profileTemplates)
|
||||||
{
|
{
|
||||||
result.TryAdd(
|
result.TryAdd(profileKey, serverLocalisationService.GetText(profile.DescriptionLocaleKey));
|
||||||
profileKey,
|
|
||||||
serverLocalisationService.GetText(profile.DescriptionLocaleKey)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -79,9 +72,7 @@ public class LauncherController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Info? Find(MongoId sessionId)
|
public Info? Find(MongoId sessionId)
|
||||||
{
|
{
|
||||||
return saveServer.GetProfiles().TryGetValue(sessionId, out var profile)
|
return saveServer.GetProfiles().TryGetValue(sessionId, out var profile) ? profile.ProfileInfo : null;
|
||||||
? profile.ProfileInfo
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -215,10 +206,7 @@ public class LauncherController(
|
|||||||
/// <returns>Dictionary of mod name and mod details</returns>
|
/// <returns>Dictionary of mod name and mod details</returns>
|
||||||
public Dictionary<string, AbstractModMetadata> GetLoadedServerMods()
|
public Dictionary<string, AbstractModMetadata> GetLoadedServerMods()
|
||||||
{
|
{
|
||||||
return loadedMods.ToDictionary(
|
return loadedMods.ToDictionary(sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD", sptMod => sptMod.ModMetadata);
|
||||||
sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD",
|
|
||||||
sptMod => sptMod.ModMetadata
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -47,10 +47,7 @@ public class LauncherV2Controller(
|
|||||||
|
|
||||||
foreach (var (templateName, template) in dbProfiles)
|
foreach (var (templateName, template) in dbProfiles)
|
||||||
{
|
{
|
||||||
result.TryAdd(
|
result.TryAdd(templateName, serverLocalisationService.GetText(template.DescriptionLocaleKey));
|
||||||
templateName,
|
|
||||||
serverLocalisationService.GetText(template.DescriptionLocaleKey)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -149,10 +146,7 @@ public class LauncherV2Controller(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Dictionary<string, AbstractModMetadata> LoadedMods()
|
public Dictionary<string, AbstractModMetadata> LoadedMods()
|
||||||
{
|
{
|
||||||
return loadedMods.ToDictionary(
|
return loadedMods.ToDictionary(sptMod => sptMod.ModMetadata.Name, sptMod => sptMod.ModMetadata);
|
||||||
sptMod => sptMod.ModMetadata.Name,
|
|
||||||
sptMod => sptMod.ModMetadata
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -187,10 +181,7 @@ public class LauncherV2Controller(
|
|||||||
{
|
{
|
||||||
foreach (var (sessionId, profile) in saveServer.GetProfiles())
|
foreach (var (sessionId, profile) in saveServer.GetProfiles())
|
||||||
{
|
{
|
||||||
if (
|
if (info.Username == profile.ProfileInfo!.Username && info.Password == profile.ProfileInfo.Password)
|
||||||
info.Username == profile.ProfileInfo!.Username
|
|
||||||
&& info.Password == profile.ProfileInfo.Password
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return sessionId;
|
return sessionId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class LocationController(
|
public class LocationController(ISptLogger<LocationController> logger, DatabaseService databaseService, AirdropService airdropService)
|
||||||
ISptLogger<LocationController> logger,
|
|
||||||
DatabaseService databaseService,
|
|
||||||
AirdropService airdropService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/locations
|
/// Handle client/locations
|
||||||
@@ -49,11 +45,7 @@ public class LocationController(
|
|||||||
locationResult.Add(mapBase.IdField, mapBase);
|
locationResult.Add(mapBase.IdField, mapBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LocationsGenerateAllResponse
|
return new LocationsGenerateAllResponse { Locations = locationResult, Paths = locationsFromDb.Base!.Paths };
|
||||||
{
|
|
||||||
Locations = locationResult,
|
|
||||||
Paths = locationsFromDb.Base!.Paths,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -104,9 +104,7 @@ public class MatchController(
|
|||||||
// Set pmcs to difficulty set in pre-raid screen if override in bot config isnt enabled
|
// Set pmcs to difficulty set in pre-raid screen if override in bot config isnt enabled
|
||||||
if (!_pmcConfig.UseDifficultyOverride)
|
if (!_pmcConfig.UseDifficultyOverride)
|
||||||
{
|
{
|
||||||
_pmcConfig.Difficulty = ConvertDifficultyDropdownIntoBotDifficulty(
|
_pmcConfig.Difficulty = ConvertDifficultyDropdownIntoBotDifficulty(request.WavesSettings.BotDifficulty.ToString());
|
||||||
request.WavesSettings.BotDifficulty.ToString()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,10 +130,7 @@ public class MatchController(
|
|||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="request">Start raid request</param>
|
/// <param name="request">Start raid request</param>
|
||||||
/// <returns>StartLocalRaidResponseData</returns>
|
/// <returns>StartLocalRaidResponseData</returns>
|
||||||
public StartLocalRaidResponseData StartLocalRaid(
|
public StartLocalRaidResponseData StartLocalRaid(MongoId sessionId, StartLocalRaidRequestData request)
|
||||||
MongoId sessionId,
|
|
||||||
StartLocalRaidRequestData request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return locationLifecycleService.StartLocalRaid(sessionId, request);
|
return locationLifecycleService.StartLocalRaid(sessionId, request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,7 @@ public class NoteController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request">Add note request</param>
|
/// <param name="request">Add note request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse AddNote(
|
public ItemEventRouterResponse AddNote(PmcData pmcData, NoteActionRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var newNote = new Note { Time = request.Note.Time, Text = request.Note.Text };
|
var newNote = new Note { Time = request.Note.Time, Text = request.Note.Text };
|
||||||
pmcData.Notes.DataNotes.Add(newNote);
|
pmcData.Notes.DataNotes.Add(newNote);
|
||||||
@@ -34,11 +30,7 @@ public class NoteController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request">Edit note request</param>
|
/// <param name="request">Edit note request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse EditNote(
|
public ItemEventRouterResponse EditNote(PmcData pmcData, NoteActionRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var noteToEdit = pmcData.Notes.DataNotes[request.Index!.Value];
|
var noteToEdit = pmcData.Notes.DataNotes[request.Index!.Value];
|
||||||
noteToEdit.Time = request.Note.Time;
|
noteToEdit.Time = request.Note.Time;
|
||||||
@@ -53,11 +45,7 @@ public class NoteController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request">Delete note request</param>
|
/// <param name="request">Delete note request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse DeleteNote(
|
public ItemEventRouterResponse DeleteNote(PmcData pmcData, NoteActionRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
NoteActionRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
pmcData.Notes?.DataNotes?.RemoveAt(request.Index!.Value);
|
pmcData.Notes?.DataNotes?.RemoveAt(request.Index!.Value);
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class NotifierController(
|
public class NotifierController(HttpServerHelper httpServerHelper, NotifierHelper notifierHelper, NotificationService notificationService)
|
||||||
HttpServerHelper httpServerHelper,
|
|
||||||
NotifierHelper notifierHelper,
|
|
||||||
NotificationService notificationService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
protected const int PollInterval = 300;
|
protected const int PollInterval = 300;
|
||||||
protected const int Timeout = 15000;
|
protected const int Timeout = 15000;
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class PresetController(
|
public class PresetController(ISptLogger<PresetController> logger, PresetHelper presetHelper, DatabaseService databaseService)
|
||||||
ISptLogger<PresetController> logger,
|
|
||||||
PresetHelper presetHelper,
|
|
||||||
DatabaseService databaseService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Keyed by item tpl, value = collection of preset ids
|
/// Keyed by item tpl, value = collection of preset ids
|
||||||
|
|||||||
@@ -44,9 +44,7 @@ public class ProfileController(
|
|||||||
var profile = saveServer.GetProfile(sessionId);
|
var profile = saveServer.GetProfile(sessionId);
|
||||||
if (profile?.CharacterData == null)
|
if (profile?.CharacterData == null)
|
||||||
{
|
{
|
||||||
throw new Exception(
|
throw new Exception($"Unable to find character data for id: {sessionId}. Profile may be corrupt");
|
||||||
$"Unable to find character data for id: {sessionId}. Profile may be corrupt"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmc = profile.CharacterData.PmcData;
|
var pmc = profile.CharacterData.PmcData;
|
||||||
@@ -82,8 +80,7 @@ public class ProfileController(
|
|||||||
Side = pmc.Info.Side,
|
Side = pmc.Info.Side,
|
||||||
CurrentLevel = pmc.Info.Level,
|
CurrentLevel = pmc.Info.Level,
|
||||||
CurrentExperience = pmc.Info.Experience ?? 0,
|
CurrentExperience = pmc.Info.Experience ?? 0,
|
||||||
PreviousExperience =
|
PreviousExperience = currentLevel == 0 ? 0 : profileHelper.GetExperience(currentLevel.Value),
|
||||||
currentLevel == 0 ? 0 : profileHelper.GetExperience(currentLevel.Value),
|
|
||||||
NextLevel = xpToNextLevel,
|
NextLevel = xpToNextLevel,
|
||||||
MaxLevel = maxLvl,
|
MaxLevel = maxLvl,
|
||||||
Edition = profile.ProfileInfo?.Edition ?? "",
|
Edition = profile.ProfileInfo?.Edition ?? "",
|
||||||
@@ -127,10 +124,7 @@ public class ProfileController(
|
|||||||
/// <param name="request">Create profile request</param>
|
/// <param name="request">Create profile request</param>
|
||||||
/// <param name="sessionId">Player id</param>
|
/// <param name="sessionId">Player id</param>
|
||||||
/// <returns>Player id</returns>
|
/// <returns>Player id</returns>
|
||||||
public virtual async ValueTask<string> CreateProfile(
|
public virtual async ValueTask<string> CreateProfile(ProfileCreateRequestData request, MongoId sessionId)
|
||||||
ProfileCreateRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return await createProfileService.CreateProfile(sessionId, request);
|
return await createProfileService.CreateProfile(sessionId, request);
|
||||||
}
|
}
|
||||||
@@ -152,10 +146,7 @@ public class ProfileController(
|
|||||||
/// <param name="request">Validate nickname request</param>
|
/// <param name="request">Validate nickname request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual NicknameValidationResult ValidateNickname(
|
public virtual NicknameValidationResult ValidateNickname(ValidateNicknameRequestData request, MongoId sessionId)
|
||||||
ValidateNicknameRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (request.Nickname?.Length < 3)
|
if (request.Nickname?.Length < 3)
|
||||||
{
|
{
|
||||||
@@ -177,15 +168,9 @@ public class ProfileController(
|
|||||||
/// <param name="request">Change nickname request</param>
|
/// <param name="request">Change nickname request</param>
|
||||||
/// <param name="sessionId">Player id</param>
|
/// <param name="sessionId">Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual NicknameValidationResult ChangeNickname(
|
public virtual NicknameValidationResult ChangeNickname(ProfileChangeNicknameRequestData request, MongoId sessionId)
|
||||||
ProfileChangeNicknameRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = ValidateNickname(
|
var output = ValidateNickname(new ValidateNicknameRequestData { Nickname = request.Nickname }, sessionId);
|
||||||
new ValidateNicknameRequestData { Nickname = request.Nickname },
|
|
||||||
sessionId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (output == NicknameValidationResult.Valid)
|
if (output == NicknameValidationResult.Valid)
|
||||||
{
|
{
|
||||||
@@ -215,10 +200,7 @@ public class ProfileController(
|
|||||||
/// <param name="request">Search profiles request</param>
|
/// <param name="request">Search profiles request</param>
|
||||||
/// <param name="sessionID">Player id</param>
|
/// <param name="sessionID">Player id</param>
|
||||||
/// <returns>Found profiles</returns>
|
/// <returns>Found profiles</returns>
|
||||||
public virtual List<SearchFriendResponse> SearchProfiles(
|
public virtual List<SearchFriendResponse> SearchProfiles(SearchProfilesRequestData request, MongoId sessionID)
|
||||||
SearchProfilesRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var result = new List<SearchFriendResponse>();
|
var result = new List<SearchFriendResponse>();
|
||||||
|
|
||||||
@@ -228,10 +210,7 @@ public class ProfileController(
|
|||||||
foreach (var profile in allProfiles)
|
foreach (var profile in allProfiles)
|
||||||
{
|
{
|
||||||
var pmcProfile = profile?.CharacterData?.PmcData;
|
var pmcProfile = profile?.CharacterData?.PmcData;
|
||||||
if (
|
if (!pmcProfile?.Info?.LowerNickname?.Contains(request.Nickname.ToLowerInvariant()) ?? false)
|
||||||
!pmcProfile?.Info?.LowerNickname?.Contains(request.Nickname.ToLowerInvariant())
|
|
||||||
?? false
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -285,21 +264,13 @@ public class ProfileController(
|
|||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="request">Get other profile request</param>
|
/// <param name="request">Get other profile request</param>
|
||||||
/// <returns>GetOtherProfileResponse</returns>
|
/// <returns>GetOtherProfileResponse</returns>
|
||||||
public virtual GetOtherProfileResponse GetOtherProfile(
|
public virtual GetOtherProfileResponse GetOtherProfile(MongoId sessionId, GetOtherProfileRequest request)
|
||||||
MongoId sessionId,
|
|
||||||
GetOtherProfileRequest request
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Find the profile by the account ID, fall back to the current player if we can't find the account
|
// Find the profile by the account ID, fall back to the current player if we can't find the account
|
||||||
var profileToView = profileHelper.GetFullProfileByAccountId(request.AccountId);
|
var profileToView = profileHelper.GetFullProfileByAccountId(request.AccountId);
|
||||||
if (
|
if (profileToView?.CharacterData?.PmcData is null || profileToView.CharacterData.ScavData is null)
|
||||||
profileToView?.CharacterData?.PmcData is null
|
|
||||||
|| profileToView.CharacterData.ScavData is null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Unable to get profile: {request.AccountId} to show, falling back to own profile");
|
||||||
$"Unable to get profile: {request.AccountId} to show, falling back to own profile"
|
|
||||||
);
|
|
||||||
profileToView = profileHelper.GetFullProfile(sessionId);
|
profileToView = profileHelper.GetFullProfile(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,16 +283,12 @@ public class ProfileController(
|
|||||||
hideoutKeys.Add(profileToViewPmc.Inventory.HideoutCustomizationStashId);
|
hideoutKeys.Add(profileToViewPmc.Inventory.HideoutCustomizationStashId);
|
||||||
|
|
||||||
// Find hideout items e.g. posters
|
// Find hideout items e.g. posters
|
||||||
var hideoutRootItems = profileToViewPmc.Inventory.Items.Where(x =>
|
var hideoutRootItems = profileToViewPmc.Inventory.Items.Where(x => hideoutKeys.Contains(x.Id));
|
||||||
hideoutKeys.Contains(x.Id)
|
|
||||||
);
|
|
||||||
var itemsToReturn = new List<Item>();
|
var itemsToReturn = new List<Item>();
|
||||||
foreach (var rootItems in hideoutRootItems)
|
foreach (var rootItems in hideoutRootItems)
|
||||||
{
|
{
|
||||||
// Check each root items for children and add
|
// Check each root items for children and add
|
||||||
var itemWithChildren = profileToViewPmc.Inventory.Items.GetItemWithChildren(
|
var itemWithChildren = profileToViewPmc.Inventory.Items.GetItemWithChildren(rootItems.Id);
|
||||||
rootItems.Id
|
|
||||||
);
|
|
||||||
itemsToReturn.AddRange(itemWithChildren);
|
itemsToReturn.AddRange(itemWithChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,9 +301,7 @@ public class ProfileController(
|
|||||||
Nickname = profileToViewPmc.Info.Nickname,
|
Nickname = profileToViewPmc.Info.Nickname,
|
||||||
Side = profileToViewPmc.Info.Side,
|
Side = profileToViewPmc.Info.Side,
|
||||||
Experience = profileToViewPmc.Info.Experience,
|
Experience = profileToViewPmc.Info.Experience,
|
||||||
MemberCategory = (int)(
|
MemberCategory = (int)(profileToViewPmc.Info.MemberCategory ?? MemberCategory.Default),
|
||||||
profileToViewPmc.Info.MemberCategory ?? MemberCategory.Default
|
|
||||||
),
|
|
||||||
BannedState = profileToViewPmc.Info.BannedState,
|
BannedState = profileToViewPmc.Info.BannedState,
|
||||||
BannedUntil = profileToViewPmc.Info.BannedUntil,
|
BannedUntil = profileToViewPmc.Info.BannedUntil,
|
||||||
RegistrationDate = profileToViewPmc.Info.RegistrationDate,
|
RegistrationDate = profileToViewPmc.Info.RegistrationDate,
|
||||||
@@ -351,11 +316,7 @@ public class ProfileController(
|
|||||||
Voice = profileToViewPmc.Customization.Voice,
|
Voice = profileToViewPmc.Customization.Voice,
|
||||||
},
|
},
|
||||||
Skills = profileToViewPmc.Skills,
|
Skills = profileToViewPmc.Skills,
|
||||||
Equipment = new OtherProfileEquipment
|
Equipment = new OtherProfileEquipment { Id = profileToViewPmc.Inventory.Equipment, Items = profileToViewPmc.Inventory.Items },
|
||||||
{
|
|
||||||
Id = profileToViewPmc.Inventory.Equipment,
|
|
||||||
Items = profileToViewPmc.Inventory.Items,
|
|
||||||
},
|
|
||||||
Achievements = profileToViewPmc.Achievements,
|
Achievements = profileToViewPmc.Achievements,
|
||||||
FavoriteItems = profileHelper.GetOtherProfileFavorites(profileToViewPmc),
|
FavoriteItems = profileHelper.GetOtherProfileFavorites(profileToViewPmc),
|
||||||
PmcStats = new OtherProfileStats
|
PmcStats = new OtherProfileStats
|
||||||
|
|||||||
@@ -50,19 +50,13 @@ public class QuestController(
|
|||||||
/// <param name="acceptedQuest">Quest accepted</param>
|
/// <param name="acceptedQuest">Quest accepted</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse AcceptQuest(
|
public ItemEventRouterResponse AcceptQuest(PmcData pmcData, AcceptQuestRequestData acceptedQuest, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AcceptQuestRequestData acceptedQuest,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var acceptQuestResponse = eventOutputHolder.GetOutput(sessionID);
|
var acceptQuestResponse = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
// Does quest exist in profile
|
// Does quest exist in profile
|
||||||
// Restarting a failed quest can mean quest exists in profile
|
// Restarting a failed quest can mean quest exists in profile
|
||||||
var existingQuestStatus = pmcData.Quests.FirstOrDefault(x =>
|
var existingQuestStatus = pmcData.Quests.FirstOrDefault(x => x.QId == acceptedQuest.QuestId);
|
||||||
x.QId == acceptedQuest.QuestId
|
|
||||||
);
|
|
||||||
if (existingQuestStatus is not null)
|
if (existingQuestStatus is not null)
|
||||||
{
|
{
|
||||||
// Update existing
|
// Update existing
|
||||||
@@ -74,11 +68,7 @@ public class QuestController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add new quest to server profile
|
// Add new quest to server profile
|
||||||
var newQuest = questHelper.GetQuestReadyForProfile(
|
var newQuest = questHelper.GetQuestReadyForProfile(pmcData, QuestStatusEnum.Started, acceptedQuest);
|
||||||
pmcData,
|
|
||||||
QuestStatusEnum.Started,
|
|
||||||
acceptedQuest
|
|
||||||
);
|
|
||||||
pmcData.Quests.Add(newQuest);
|
pmcData.Quests.Add(newQuest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,18 +78,11 @@ public class QuestController(
|
|||||||
|
|
||||||
if (questFromDb.Conditions?.AvailableForFinish is not null)
|
if (questFromDb.Conditions?.AvailableForFinish is not null)
|
||||||
{
|
{
|
||||||
AddTaskConditionCountersToProfile(
|
AddTaskConditionCountersToProfile(questFromDb.Conditions.AvailableForFinish, pmcData, acceptedQuest.QuestId);
|
||||||
questFromDb.Conditions.AvailableForFinish,
|
|
||||||
pmcData,
|
|
||||||
acceptedQuest.QuestId
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get messageId of text to send to player as text message in game
|
// Get messageId of text to send to player as text message in game
|
||||||
var messageId = questHelper.GetMessageIdForQuestStart(
|
var messageId = questHelper.GetMessageIdForQuestStart(questFromDb.StartedMessageText, questFromDb.Description);
|
||||||
questFromDb.StartedMessageText,
|
|
||||||
questFromDb.Description
|
|
||||||
);
|
|
||||||
|
|
||||||
// Apply non-item rewards to profile + return item rewards
|
// Apply non-item rewards to profile + return item rewards
|
||||||
var startedQuestRewardItems = questRewardHelper.ApplyQuestReward(
|
var startedQuestRewardItems = questRewardHelper.ApplyQuestReward(
|
||||||
@@ -117,16 +100,11 @@ public class QuestController(
|
|||||||
MessageType.QuestStart,
|
MessageType.QuestStart,
|
||||||
messageId,
|
messageId,
|
||||||
startedQuestRewardItems.ToList(),
|
startedQuestRewardItems.ToList(),
|
||||||
timeUtil.GetHoursAsSeconds(
|
timeUtil.GetHoursAsSeconds((int)questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData))
|
||||||
(int)questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Having accepted new quest, look for newly unlocked quests and inform client of them
|
// Having accepted new quest, look for newly unlocked quests and inform client of them
|
||||||
var newlyAccessibleQuests = questHelper.GetNewlyAccessibleQuestsWhenStartingQuest(
|
var newlyAccessibleQuests = questHelper.GetNewlyAccessibleQuestsWhenStartingQuest(acceptedQuest.QuestId, sessionID);
|
||||||
acceptedQuest.QuestId,
|
|
||||||
sessionID
|
|
||||||
);
|
|
||||||
if (newlyAccessibleQuests.Count > 0)
|
if (newlyAccessibleQuests.Count > 0)
|
||||||
{
|
{
|
||||||
acceptQuestResponse.ProfileChanges[sessionID].Quests.AddRange(newlyAccessibleQuests);
|
acceptQuestResponse.ProfileChanges[sessionID].Quests.AddRange(newlyAccessibleQuests);
|
||||||
@@ -142,17 +120,9 @@ public class QuestController(
|
|||||||
/// <param name="questConditionsToAdd">Conditions to iterate over and possibly add to profile</param>
|
/// <param name="questConditionsToAdd">Conditions to iterate over and possibly add to profile</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="questId">Quest where conditions originated</param>
|
/// <param name="questId">Quest where conditions originated</param>
|
||||||
protected void AddTaskConditionCountersToProfile(
|
protected void AddTaskConditionCountersToProfile(IEnumerable<QuestCondition> questConditionsToAdd, PmcData pmcData, MongoId questId)
|
||||||
IEnumerable<QuestCondition> questConditionsToAdd,
|
|
||||||
PmcData pmcData,
|
|
||||||
MongoId questId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (
|
foreach (var condition in questConditionsToAdd.Where(condition => condition.ConditionType == "SellItemToTrader"))
|
||||||
var condition in questConditionsToAdd.Where(condition =>
|
|
||||||
condition.ConditionType == "SellItemToTrader"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (pmcData.TaskConditionCounters.TryGetValue(condition.Id, out _))
|
if (pmcData.TaskConditionCounters.TryGetValue(condition.Id, out _))
|
||||||
{
|
{
|
||||||
@@ -185,11 +155,7 @@ public class QuestController(
|
|||||||
/// <param name="request">Complete quest request</param>
|
/// <param name="request">Complete quest request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse CompleteQuest(
|
public ItemEventRouterResponse CompleteQuest(PmcData pmcData, CompleteQuestRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
CompleteQuestRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return questHelper.CompleteQuest(pmcData, request, sessionId);
|
return questHelper.CompleteQuest(pmcData, request, sessionId);
|
||||||
}
|
}
|
||||||
@@ -202,11 +168,7 @@ public class QuestController(
|
|||||||
/// <param name="request">Handover request</param>
|
/// <param name="request">Handover request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse HandoverQuest(
|
public ItemEventRouterResponse HandoverQuest(PmcData pmcData, HandoverQuestRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
HandoverQuestRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var quest = questHelper.GetQuestFromDb(request.QuestId, pmcData);
|
var quest = questHelper.GetQuestFromDb(request.QuestId, pmcData);
|
||||||
HashSet<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
|
HashSet<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
|
||||||
@@ -217,11 +179,7 @@ public class QuestController(
|
|||||||
|
|
||||||
// Decrement number of items handed in
|
// Decrement number of items handed in
|
||||||
QuestCondition? handoverRequirements = null;
|
QuestCondition? handoverRequirements = null;
|
||||||
foreach (
|
foreach (var condition in quest.Conditions.AvailableForFinish.Where(condition => condition.Id == request.ConditionId))
|
||||||
var condition in quest.Conditions.AvailableForFinish.Where(condition =>
|
|
||||||
condition.Id == request.ConditionId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Not a handover quest type, skip
|
// Not a handover quest type, skip
|
||||||
if (!handoverQuestTypes.Contains(condition.ConditionType))
|
if (!handoverQuestTypes.Contains(condition.ConditionType))
|
||||||
@@ -261,51 +219,26 @@ public class QuestController(
|
|||||||
|
|
||||||
if (isItemHandoverQuest && handedInCount == 0)
|
if (isItemHandoverQuest && handedInCount == 0)
|
||||||
{
|
{
|
||||||
return ShowRepeatableQuestInvalidConditionError(
|
return ShowRepeatableQuestInvalidConditionError(request.QuestId, request.ConditionId, output);
|
||||||
request.QuestId,
|
|
||||||
request.ConditionId,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalItemCountToRemove = 0d;
|
var totalItemCountToRemove = 0d;
|
||||||
foreach (var itemHandover in request.Items)
|
foreach (var itemHandover in request.Items)
|
||||||
{
|
{
|
||||||
var matchingItemInProfile = pmcData.Inventory.Items.FirstOrDefault(item =>
|
var matchingItemInProfile = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == itemHandover.Id);
|
||||||
item.Id == itemHandover.Id
|
if (!(matchingItemInProfile is not null && handoverRequirements.Target.List.Contains(matchingItemInProfile.Template)))
|
||||||
);
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
matchingItemInProfile is not null
|
|
||||||
&& handoverRequirements.Target.List.Contains(matchingItemInProfile.Template)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Item handed in by player doesn't match what was requested
|
// Item handed in by player doesn't match what was requested
|
||||||
{
|
{
|
||||||
return ShowQuestItemHandoverMatchError(
|
return ShowQuestItemHandoverMatchError(request, matchingItemInProfile, handoverRequirements, output);
|
||||||
request,
|
|
||||||
matchingItemInProfile,
|
|
||||||
handoverRequirements,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the right quantity of given items
|
// Remove the right quantity of given items
|
||||||
var itemCountToRemove = Math.Min(
|
var itemCountToRemove = Math.Min(itemHandover.Count ?? 0, handedInCount - totalItemCountToRemove);
|
||||||
itemHandover.Count ?? 0,
|
|
||||||
handedInCount - totalItemCountToRemove
|
|
||||||
);
|
|
||||||
totalItemCountToRemove += itemCountToRemove;
|
totalItemCountToRemove += itemCountToRemove;
|
||||||
if (itemHandover.Count - itemCountToRemove > 0)
|
if (itemHandover.Count - itemCountToRemove > 0)
|
||||||
{
|
{
|
||||||
// Remove single item with no children
|
// Remove single item with no children
|
||||||
questHelper.ChangeItemStack(
|
questHelper.ChangeItemStack(pmcData, itemHandover.Id, (int)(itemHandover.Count - itemCountToRemove), sessionID, output);
|
||||||
pmcData,
|
|
||||||
itemHandover.Id,
|
|
||||||
(int)(itemHandover.Count - itemCountToRemove),
|
|
||||||
sessionID,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
// Complete - handedInCount == totalItemCountToRemove
|
// Complete - handedInCount == totalItemCountToRemove
|
||||||
if (Math.Abs(totalItemCountToRemove - handedInCount) < 0.01)
|
if (Math.Abs(totalItemCountToRemove - handedInCount) < 0.01)
|
||||||
@@ -316,15 +249,11 @@ public class QuestController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remove item with children
|
// Remove item with children
|
||||||
var toRemove = pmcData
|
var toRemove = pmcData.Inventory.Items.GetItemWithChildrenTpls(itemHandover.Id).ToHashSet();
|
||||||
.Inventory.Items.GetItemWithChildrenTpls(itemHandover.Id)
|
|
||||||
.ToHashSet();
|
|
||||||
var index = pmcData.Inventory.Items.Count;
|
var index = pmcData.Inventory.Items.Count;
|
||||||
|
|
||||||
// Important: don't tell the client to remove the attachments, it will handle it
|
// Important: don't tell the client to remove the attachments, it will handle it
|
||||||
output
|
output.ProfileChanges[sessionID].Items.DeletedItems.Add(new DeletedItem { Id = itemHandover.Id });
|
||||||
.ProfileChanges[sessionID]
|
|
||||||
.Items.DeletedItems.Add(new DeletedItem { Id = itemHandover.Id });
|
|
||||||
|
|
||||||
// Important: loop backward when removing items from the array we're looping on
|
// Important: loop backward when removing items from the array we're looping on
|
||||||
while (index-- > 0)
|
while (index-- > 0)
|
||||||
@@ -339,9 +268,7 @@ public class QuestController(
|
|||||||
// element `location` properties of the parent so they are sequential, while retaining order
|
// element `location` properties of the parent so they are sequential, while retaining order
|
||||||
if (removedItem.Location?.GetType() == typeof(int))
|
if (removedItem.Location?.GetType() == typeof(int))
|
||||||
{
|
{
|
||||||
var childItems = pmcData.Inventory.Items.GetItemWithChildren(
|
var childItems = pmcData.Inventory.Items.GetItemWithChildren(removedItem.ParentId);
|
||||||
removedItem.ParentId
|
|
||||||
);
|
|
||||||
childItems.RemoveAt(0); // Remove the parent
|
childItems.RemoveAt(0); // Remove the parent
|
||||||
|
|
||||||
// Sort by the current `location` and update
|
// Sort by the current `location` and update
|
||||||
@@ -357,12 +284,7 @@ public class QuestController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateProfileTaskConditionCounterValue(
|
UpdateProfileTaskConditionCounterValue(pmcData, request.ConditionId, request.QuestId, totalItemCountToRemove);
|
||||||
pmcData,
|
|
||||||
request.ConditionId,
|
|
||||||
request.QuestId,
|
|
||||||
totalItemCountToRemove
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -426,12 +348,7 @@ public class QuestController(
|
|||||||
/// <param name="conditionId">Backend counter id to update</param>
|
/// <param name="conditionId">Backend counter id to update</param>
|
||||||
/// <param name="questId">Quest id counter is associated with</param>
|
/// <param name="questId">Quest id counter is associated with</param>
|
||||||
/// <param name="counterValue">Value to increment the backend counter with</param>
|
/// <param name="counterValue">Value to increment the backend counter with</param>
|
||||||
protected void UpdateProfileTaskConditionCounterValue(
|
protected void UpdateProfileTaskConditionCounterValue(PmcData pmcData, MongoId conditionId, MongoId questId, double counterValue)
|
||||||
PmcData pmcData,
|
|
||||||
MongoId conditionId,
|
|
||||||
MongoId questId,
|
|
||||||
double counterValue
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (pmcData.TaskConditionCounters.GetValueOrDefault(conditionId) != null)
|
if (pmcData.TaskConditionCounters.GetValueOrDefault(conditionId) != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -62,8 +62,7 @@ public class RagfairController(
|
|||||||
var pmcProfile = profile.CharacterData.PmcData;
|
var pmcProfile = profile.CharacterData.PmcData;
|
||||||
if (
|
if (
|
||||||
pmcProfile.RagfairInfo is not null
|
pmcProfile.RagfairInfo is not null
|
||||||
&& pmcProfile.Info.Level
|
&& pmcProfile.Info.Level >= databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
|
||||||
>= databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ragfairOfferHelper.ProcessOffersOnProfile(sessionId);
|
ragfairOfferHelper.ProcessOffersOnProfile(sessionId);
|
||||||
@@ -91,21 +90,12 @@ public class RagfairController(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Get all offers ready for sorting/filtering below
|
// Get all offers ready for sorting/filtering below
|
||||||
result.Offers = GetOffersForSearchType(
|
result.Offers = GetOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, profile.CharacterData.PmcData);
|
||||||
searchRequest,
|
|
||||||
itemsToAdd,
|
|
||||||
traderAssorts,
|
|
||||||
profile.CharacterData.PmcData
|
|
||||||
);
|
|
||||||
|
|
||||||
// Client requested a category refresh
|
// Client requested a category refresh
|
||||||
if (searchRequest.UpdateOfferCount.GetValueOrDefault(false))
|
if (searchRequest.UpdateOfferCount.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
result.Categories = GetSpecificCategories(
|
result.Categories = GetSpecificCategories(profile.CharacterData.PmcData, searchRequest, result.Offers);
|
||||||
profile.CharacterData.PmcData,
|
|
||||||
searchRequest,
|
|
||||||
result.Offers
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust index value of offers found to start at 0
|
// Adjust index value of offers found to start at 0
|
||||||
@@ -217,10 +207,7 @@ public class RagfairController(
|
|||||||
var assortId = offerRootItem.Id;
|
var assortId = offerRootItem.Id;
|
||||||
|
|
||||||
// No trader found in profile, create a blank record for them
|
// No trader found in profile, create a blank record for them
|
||||||
var existsInProfile = !fullProfile.TraderPurchases.TryAdd(
|
var existsInProfile = !fullProfile.TraderPurchases.TryAdd(offer.User.Id, new Dictionary<MongoId, TraderPurchaseData>());
|
||||||
offer.User.Id,
|
|
||||||
new Dictionary<MongoId, TraderPurchaseData>()
|
|
||||||
);
|
|
||||||
if (!existsInProfile)
|
if (!existsInProfile)
|
||||||
{
|
{
|
||||||
// Not purchased by player before, use value from assort data
|
// Not purchased by player before, use value from assort data
|
||||||
@@ -266,16 +253,10 @@ public class RagfairController(
|
|||||||
/// <param name="searchRequest">Client search request data</param>
|
/// <param name="searchRequest">Client search request data</param>
|
||||||
/// <param name="offers">Ragfair offers to get categories for</param>
|
/// <param name="offers">Ragfair offers to get categories for</param>
|
||||||
/// <returns>Record with templates + counts</returns>
|
/// <returns>Record with templates + counts</returns>
|
||||||
protected Dictionary<MongoId, int> GetSpecificCategories(
|
protected Dictionary<MongoId, int> GetSpecificCategories(PmcData pmcProfile, SearchRequestData searchRequest, List<RagfairOffer> offers)
|
||||||
PmcData pmcProfile,
|
|
||||||
SearchRequestData searchRequest,
|
|
||||||
List<RagfairOffer> offers
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Linked/required search categories
|
// Linked/required search categories
|
||||||
var playerHasFleaUnlocked =
|
var playerHasFleaUnlocked = pmcProfile.Info.Level >= databaseService.GetGlobals().Configuration.RagFair.MinUserLevel;
|
||||||
pmcProfile.Info.Level
|
|
||||||
>= databaseService.GetGlobals().Configuration.RagFair.MinUserLevel;
|
|
||||||
List<RagfairOffer> offerPool;
|
List<RagfairOffer> offerPool;
|
||||||
if (IsLinkedSearch(searchRequest) || IsRequiredSearch(searchRequest))
|
if (IsLinkedSearch(searchRequest) || IsRequiredSearch(searchRequest))
|
||||||
{
|
{
|
||||||
@@ -297,11 +278,7 @@ public class RagfairController(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return ragfairServer.GetAllActiveCategories(
|
return ragfairServer.GetAllActiveCategories(playerHasFleaUnlocked, searchRequest, offerPool);
|
||||||
playerHasFleaUnlocked,
|
|
||||||
searchRequest,
|
|
||||||
offerPool
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -342,12 +319,7 @@ public class RagfairController(
|
|||||||
// Searching for items in preset menu
|
// Searching for items in preset menu
|
||||||
if (searchRequest.BuildCount > 0)
|
if (searchRequest.BuildCount > 0)
|
||||||
{
|
{
|
||||||
return ragfairOfferHelper.GetOffersForBuild(
|
return ragfairOfferHelper.GetOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
||||||
searchRequest,
|
|
||||||
itemsToAdd,
|
|
||||||
traderAssorts,
|
|
||||||
pmcProfile
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchRequest.NeededSearchId != null && !searchRequest.NeededSearchId.Value.IsEmpty())
|
if (searchRequest.NeededSearchId != null && !searchRequest.NeededSearchId.Value.IsEmpty())
|
||||||
@@ -356,12 +328,7 @@ public class RagfairController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Searching for general items
|
// Searching for general items
|
||||||
return ragfairOfferHelper.GetValidOffers(
|
return ragfairOfferHelper.GetValidOffers(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
||||||
searchRequest,
|
|
||||||
itemsToAdd,
|
|
||||||
traderAssorts,
|
|
||||||
pmcProfile
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -370,10 +337,7 @@ public class RagfairController(
|
|||||||
/// <param name="getPriceRequest">Client request object</param>
|
/// <param name="getPriceRequest">Client request object</param>
|
||||||
/// <param name="ignoreTraderOffers">OPTIONAL - Should trader offers be ignored in the calculation</param>
|
/// <param name="ignoreTraderOffers">OPTIONAL - Should trader offers be ignored in the calculation</param>
|
||||||
/// <returns>min/avg/max values for an item based on flea offers available</returns>
|
/// <returns>min/avg/max values for an item based on flea offers available</returns>
|
||||||
public GetItemPriceResult GetItemMinAvgMaxFleaPriceValues(
|
public GetItemPriceResult GetItemMinAvgMaxFleaPriceValues(GetMarketPriceRequestData getPriceRequest, bool ignoreTraderOffers = true)
|
||||||
GetMarketPriceRequestData getPriceRequest,
|
|
||||||
bool ignoreTraderOffers = true
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get all items of tpl
|
// Get all items of tpl
|
||||||
var offers = ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId);
|
var offers = ragfairOfferService.GetOffersOfType(getPriceRequest.TemplateId);
|
||||||
@@ -411,11 +375,7 @@ public class RagfairController(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetAveragePriceFromOffers(
|
protected double GetAveragePriceFromOffers(IEnumerable<RagfairOffer> offers, MinMax<double> minMax, bool ignoreTraderOffers)
|
||||||
IEnumerable<RagfairOffer> offers,
|
|
||||||
MinMax<double> minMax,
|
|
||||||
bool ignoreTraderOffers
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var sum = 0d;
|
var sum = 0d;
|
||||||
var totalOfferCount = 0;
|
var totalOfferCount = 0;
|
||||||
@@ -434,9 +394,7 @@ public class RagfairController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out how many items the requirementsCost is applying to, and what the per-item price is
|
// Figure out how many items the requirementsCost is applying to, and what the per-item price is
|
||||||
var offerItemCount = offer.SellInOnePiece.GetValueOrDefault(false)
|
var offerItemCount = offer.SellInOnePiece.GetValueOrDefault(false) ? offer.Items.First().Upd?.StackObjectsCount ?? 1 : 1;
|
||||||
? offer.Items.First().Upd?.StackObjectsCount ?? 1
|
|
||||||
: 1;
|
|
||||||
var perItemPrice = offer.RequirementsCost / offerItemCount;
|
var perItemPrice = offer.RequirementsCost / offerItemCount;
|
||||||
|
|
||||||
// Handle min/max calculations based on the per-item price
|
// Handle min/max calculations based on the per-item price
|
||||||
@@ -468,30 +426,20 @@ public class RagfairController(
|
|||||||
/// <param name="offerRequest">Flea list creation offer</param>
|
/// <param name="offerRequest">Flea list creation offer</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse AddPlayerOffer(
|
public ItemEventRouterResponse AddPlayerOffer(PmcData pmcData, AddOfferRequestData offerRequest, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AddOfferRequestData offerRequest,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
var fullProfile = profileHelper.GetFullProfile(sessionID);
|
var fullProfile = profileHelper.GetFullProfile(sessionID);
|
||||||
|
|
||||||
if (!IsValidPlayerOfferRequest(offerRequest))
|
if (!IsValidPlayerOfferRequest(offerRequest))
|
||||||
{
|
{
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, "Unable to add offer, check server for error");
|
||||||
output,
|
|
||||||
"Unable to add offer, check server for error"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var typeOfOffer = GetOfferType(offerRequest);
|
var typeOfOffer = GetOfferType(offerRequest);
|
||||||
if (typeOfOffer == FleaOfferType.UNKNOWN)
|
if (typeOfOffer == FleaOfferType.UNKNOWN)
|
||||||
{
|
{
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, $"Unknown offer type: {typeOfOffer}, cannot list item on flea");
|
||||||
output,
|
|
||||||
$"Unknown offer type: {typeOfOffer}, cannot list item on flea"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (typeOfOffer)
|
switch (typeOfOffer)
|
||||||
@@ -504,10 +452,7 @@ public class RagfairController(
|
|||||||
return CreatePackOffer(sessionID, offerRequest, fullProfile, output);
|
return CreatePackOffer(sessionID, offerRequest, fullProfile, output);
|
||||||
case FleaOfferType.UNKNOWN:
|
case FleaOfferType.UNKNOWN:
|
||||||
default:
|
default:
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, $"Unknown offer type: {typeOfOffer}, cannot list item on flea");
|
||||||
output,
|
|
||||||
$"Unknown offer type: {typeOfOffer}, cannot list item on flea"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,9 +472,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
if (offerRequest.Requirements is null)
|
if (offerRequest.Requirements is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements"));
|
||||||
localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements")
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -613,9 +556,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
// Average offer price for single item (or whole weapon)
|
// Average offer price for single item (or whole weapon)
|
||||||
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
||||||
var averages = GetItemMinAvgMaxFleaPriceValues(
|
var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData { TemplateId = firstInventoryItem.Template });
|
||||||
new GetMarketPriceRequestData { TemplateId = firstInventoryItem.Template }
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create flea object
|
// Create flea object
|
||||||
var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, inventoryItems, false);
|
var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, inventoryItems, false);
|
||||||
@@ -625,12 +566,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
// Check for and apply item price modifer if it exists in config
|
// Check for and apply item price modifer if it exists in config
|
||||||
var averageOfferPrice = averages.Avg;
|
var averageOfferPrice = averages.Avg;
|
||||||
if (
|
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(rootOfferItem.Template, out var itemPriceModifer))
|
||||||
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
|
||||||
rootOfferItem.Template,
|
|
||||||
out var itemPriceModifer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
averageOfferPrice *= itemPriceModifer;
|
averageOfferPrice *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -645,11 +581,7 @@ public class RagfairController(
|
|||||||
var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements);
|
var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements);
|
||||||
|
|
||||||
// Roll sale chance
|
// Roll sale chance
|
||||||
var sellChancePercent = ragfairSellHelper.CalculateSellChance(
|
var sellChancePercent = ragfairSellHelper.CalculateSellChance(averageOfferPrice.Value, playerListedPriceInRub, qualityMultiplier);
|
||||||
averageOfferPrice.Value,
|
|
||||||
playerListedPriceInRub,
|
|
||||||
qualityMultiplier
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create array of sell times for items listed
|
// Create array of sell times for items listed
|
||||||
offer.SellResults = ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal);
|
offer.SellResults = ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal);
|
||||||
@@ -707,9 +639,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
// multi-offers are all the same item,
|
// multi-offers are all the same item,
|
||||||
// Get first item and its children and use as template
|
// Get first item and its children and use as template
|
||||||
var firstInventoryItemAndChildren = pmcData.Inventory.Items.GetItemWithChildren(
|
var firstInventoryItemAndChildren = pmcData.Inventory.Items.GetItemWithChildren(offerRequest.Items.FirstOrDefault());
|
||||||
offerRequest.Items.FirstOrDefault()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Find items to be listed on flea (+ children) from player inventory
|
// Find items to be listed on flea (+ children) from player inventory
|
||||||
var result = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items);
|
var result = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items);
|
||||||
@@ -729,29 +659,17 @@ public class RagfairController(
|
|||||||
|
|
||||||
// Single price for an item
|
// Single price for an item
|
||||||
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
||||||
var averages = GetItemMinAvgMaxFleaPriceValues(
|
var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData { TemplateId = firstInventoryItem.Template });
|
||||||
new GetMarketPriceRequestData { TemplateId = firstInventoryItem.Template }
|
|
||||||
);
|
|
||||||
var singleItemPrice = averages.Avg;
|
var singleItemPrice = averages.Avg;
|
||||||
|
|
||||||
// Create flea object
|
// Create flea object
|
||||||
var offer = CreatePlayerOffer(
|
var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstInventoryItemAndChildren, true);
|
||||||
sessionID,
|
|
||||||
offerRequest.Requirements,
|
|
||||||
firstInventoryItemAndChildren,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// This is the item that will be listed on flea, has merged stackObjectCount
|
// This is the item that will be listed on flea, has merged stackObjectCount
|
||||||
var newRootOfferItem = offer.Items[0]; // TODO: add logic like single/multi offers to find root item
|
var newRootOfferItem = offer.Items[0]; // TODO: add logic like single/multi offers to find root item
|
||||||
|
|
||||||
// Check for and apply item price modifer if it exists in config
|
// Check for and apply item price modifer if it exists in config
|
||||||
if (
|
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(newRootOfferItem.Template, out var itemPriceModifer))
|
||||||
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
|
||||||
newRootOfferItem.Template,
|
|
||||||
out var itemPriceModifer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
singleItemPrice *= itemPriceModifer;
|
singleItemPrice *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -773,11 +691,7 @@ public class RagfairController(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Create array of sell times for items listed + sell all at once as it's a pack
|
// Create array of sell times for items listed + sell all at once as it's a pack
|
||||||
offer.SellResults = ragfairSellHelper.RollForSale(
|
offer.SellResults = ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal, true);
|
||||||
sellChancePercent,
|
|
||||||
(int)stackCountTotal,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Subtract flea market fee from stash
|
// Subtract flea market fee from stash
|
||||||
if (_ragfairConfig.Sell.Fees)
|
if (_ragfairConfig.Sell.Fees)
|
||||||
@@ -831,10 +745,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
// Find items to be listed on flea from player inventory
|
// Find items to be listed on flea from player inventory
|
||||||
var inventoryItemsToSell = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items);
|
var inventoryItemsToSell = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items);
|
||||||
if (
|
if (inventoryItemsToSell.Items is null || !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage))
|
||||||
inventoryItemsToSell.Items is null
|
|
||||||
|| !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
httpResponseUtil.AppendErrorToOutput(output, inventoryItemsToSell.ErrorMessage);
|
httpResponseUtil.AppendErrorToOutput(output, inventoryItemsToSell.ErrorMessage);
|
||||||
}
|
}
|
||||||
@@ -846,9 +757,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
// Average offer price for single item (or whole weapon)
|
// Average offer price for single item (or whole weapon)
|
||||||
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
// MUST occur prior to CreatePlayerOffer(), otherwise offer ends up in averages calculation
|
||||||
var averages = GetItemMinAvgMaxFleaPriceValues(
|
var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData { TemplateId = firstItemToSell.Template });
|
||||||
new GetMarketPriceRequestData { TemplateId = firstItemToSell.Template }
|
|
||||||
);
|
|
||||||
var averageOfferPriceSingleItem = averages.Avg;
|
var averageOfferPriceSingleItem = averages.Avg;
|
||||||
|
|
||||||
// Checks are done, create offer
|
// Checks are done, create offer
|
||||||
@@ -866,12 +775,7 @@ public class RagfairController(
|
|||||||
var qualityMultiplier = itemHelper.GetItemQualityModifierForItems(offer.Items, true);
|
var qualityMultiplier = itemHelper.GetItemQualityModifierForItems(offer.Items, true);
|
||||||
|
|
||||||
// Check for and apply item price modifer if it exists in config
|
// Check for and apply item price modifer if it exists in config
|
||||||
if (
|
if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(offerRootItem.Template, out var itemPriceModifer))
|
||||||
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
|
||||||
offerRootItem.Template,
|
|
||||||
out var itemPriceModifer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
averageOfferPriceSingleItem *= itemPriceModifer;
|
averageOfferPriceSingleItem *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -941,9 +845,7 @@ public class RagfairController(
|
|||||||
{
|
{
|
||||||
// Get tax from cache hydrated earlier by client, if that's missing fall back to server calculation (inaccurate)
|
// Get tax from cache hydrated earlier by client, if that's missing fall back to server calculation (inaccurate)
|
||||||
var requestRootItemId = offerRequest.Items.FirstOrDefault();
|
var requestRootItemId = offerRequest.Items.FirstOrDefault();
|
||||||
var storedClientTaxValue = ragfairTaxService.GetStoredClientOfferTaxValueById(
|
var storedClientTaxValue = ragfairTaxService.GetStoredClientOfferTaxValueById(requestRootItemId);
|
||||||
requestRootItemId
|
|
||||||
);
|
|
||||||
var tax = storedClientTaxValue is not null
|
var tax = storedClientTaxValue is not null
|
||||||
? storedClientTaxValue.Fee
|
? storedClientTaxValue.Fee
|
||||||
: ragfairTaxService.CalculateTax(
|
: ragfairTaxService.CalculateTax(
|
||||||
@@ -956,9 +858,7 @@ public class RagfairController(
|
|||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}");
|
||||||
$"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup of cache now we've used the tax value from it
|
// Cleanup of cache now we've used the tax value from it
|
||||||
@@ -968,10 +868,7 @@ public class RagfairController(
|
|||||||
paymentService.PayMoney(pmcData, buyTradeRequest, sessionId, output);
|
paymentService.PayMoney(pmcData, buyTradeRequest, sessionId, output);
|
||||||
if (output.Warnings.Count > 0)
|
if (output.Warnings.Count > 0)
|
||||||
{
|
{
|
||||||
httpResponseUtil.AppendErrorToOutput(
|
httpResponseUtil.AppendErrorToOutput(output, localisationService.GetText("ragfair-unable_to_pay_commission_fee", tax));
|
||||||
output,
|
|
||||||
localisationService.GetText("ragfair-unable_to_pay_commission_fee", tax)
|
|
||||||
);
|
|
||||||
return true; // Fee failed
|
return true; // Fee failed
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -986,12 +883,7 @@ public class RagfairController(
|
|||||||
/// <param name="items">Item(s) to list on flea (with children)</param>
|
/// <param name="items">Item(s) to list on flea (with children)</param>
|
||||||
/// <param name="sellInOnePiece">Is this a pack offer</param>
|
/// <param name="sellInOnePiece">Is this a pack offer</param>
|
||||||
/// <returns>RagfairOffer</returns>
|
/// <returns>RagfairOffer</returns>
|
||||||
protected RagfairOffer CreatePlayerOffer(
|
protected RagfairOffer CreatePlayerOffer(MongoId sessionId, List<Requirement> requirements, List<Item> items, bool sellInOnePiece)
|
||||||
MongoId sessionId,
|
|
||||||
List<Requirement> requirements,
|
|
||||||
List<Item> items,
|
|
||||||
bool sellInOnePiece
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
const int loyalLevel = 1;
|
const int loyalLevel = 1;
|
||||||
var formattedItems = items.Select(item =>
|
var formattedItems = items.Select(item =>
|
||||||
@@ -1039,19 +931,14 @@ public class RagfairController(
|
|||||||
{
|
{
|
||||||
return requirements.Sum(requirement =>
|
return requirements.Sum(requirement =>
|
||||||
{
|
{
|
||||||
if (
|
if (requirement.Template.IsEmpty() || !requirement.Count.HasValue || requirement.Count == 0)
|
||||||
requirement.Template.IsEmpty()
|
|
||||||
|| !requirement.Count.HasValue
|
|
||||||
|| requirement.Count == 0
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return paymentHelper.IsMoneyTpl(requirement.Template)
|
return paymentHelper.IsMoneyTpl(requirement.Template)
|
||||||
? handbookHelper.InRUB(requirement.Count.Value, requirement.Template)
|
? handbookHelper.InRUB(requirement.Count.Value, requirement.Template)
|
||||||
: itemHelper.GetDynamicItemPrice(requirement.Template).Value
|
: itemHelper.GetDynamicItemPrice(requirement.Template).Value * requirement.Count.Value;
|
||||||
* requirement.Count.Value;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,17 +962,10 @@ public class RagfairController(
|
|||||||
var rootItem = pmcData.Inventory?.Items?.FirstOrDefault(i => i.Id == itemId);
|
var rootItem = pmcData.Inventory?.Items?.FirstOrDefault(i => i.Id == itemId);
|
||||||
if (rootItem is null)
|
if (rootItem is null)
|
||||||
{
|
{
|
||||||
errorMessage = localisationService.GetText(
|
errorMessage = localisationService.GetText("ragfair-unable_to_find_item_in_inventory", new { id = itemId.ToString() });
|
||||||
"ragfair-unable_to_find_item_in_inventory",
|
|
||||||
new { id = itemId.ToString() }
|
|
||||||
);
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult
|
return new GetItemsToListOnFleaFromInventoryResult { Items = itemsToReturn, ErrorMessage = errorMessage };
|
||||||
{
|
|
||||||
Items = itemsToReturn,
|
|
||||||
ErrorMessage = errorMessage,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rootItem.FixItemStackCount();
|
rootItem.FixItemStackCount();
|
||||||
@@ -1095,19 +975,13 @@ public class RagfairController(
|
|||||||
|
|
||||||
if (itemsToReturn.Count == 0)
|
if (itemsToReturn.Count == 0)
|
||||||
{
|
{
|
||||||
errorMessage = localisationService.GetText(
|
errorMessage = localisationService.GetText("ragfair-unable_to_find_requested_items_in_inventory");
|
||||||
"ragfair-unable_to_find_requested_items_in_inventory"
|
|
||||||
);
|
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult { ErrorMessage = errorMessage };
|
return new GetItemsToListOnFleaFromInventoryResult { ErrorMessage = errorMessage };
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult
|
return new GetItemsToListOnFleaFromInventoryResult { Items = itemsToReturn, ErrorMessage = errorMessage };
|
||||||
{
|
|
||||||
Items = itemsToReturn,
|
|
||||||
ErrorMessage = errorMessage,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1126,10 +1000,7 @@ public class RagfairController(
|
|||||||
if (playerProfileOffers is null)
|
if (playerProfileOffers is null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(
|
||||||
localisationService.GetText(
|
localisationService.GetText("ragfair-unable_to_remove_offer_not_found_in_profile", new { profileId = sessionId, offerId })
|
||||||
"ragfair-unable_to_remove_offer_not_found_in_profile",
|
|
||||||
new { profileId = sessionId, offerId }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
pmcData.RagfairInfo.Offers = [];
|
pmcData.RagfairInfo.Offers = [];
|
||||||
@@ -1138,14 +1009,9 @@ public class RagfairController(
|
|||||||
var playerOffer = playerProfileOffers?.FirstOrDefault(x => x.Id == offerId);
|
var playerOffer = playerProfileOffers?.FirstOrDefault(x => x.Id == offerId);
|
||||||
if (playerOffer is null)
|
if (playerOffer is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("ragfair-offer_not_found_in_profile", new { offerId }));
|
||||||
localisationService.GetText("ragfair-offer_not_found_in_profile", new { offerId })
|
|
||||||
);
|
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, localisationService.GetText("ragfair-offer_not_found_in_profile_short"));
|
||||||
output,
|
|
||||||
localisationService.GetText("ragfair-offer_not_found_in_profile_short")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only reduce time to end if time remaining is greater than what we would set it to
|
// Only reduce time to end if time remaining is greater than what we would set it to
|
||||||
@@ -1157,9 +1023,7 @@ public class RagfairController(
|
|||||||
playerOffer.EndTime = (long?)Math.Round((double)newEndTime);
|
playerOffer.EndTime = (long?)Math.Round((double)newEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug(
|
logger.Debug($"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}");
|
||||||
$"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}"
|
|
||||||
);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -1170,10 +1034,7 @@ public class RagfairController(
|
|||||||
/// <param name="extendRequest">Extend time request</param>
|
/// <param name="extendRequest">Extend time request</param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse ExtendOffer(
|
public ItemEventRouterResponse ExtendOffer(ExtendOfferRequestData extendRequest, MongoId sessionId)
|
||||||
ExtendOfferRequestData extendRequest,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -1184,16 +1045,8 @@ public class RagfairController(
|
|||||||
|
|
||||||
if (playerOfferIndex == -1)
|
if (playerOfferIndex == -1)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("ragfair-offer_not_found_in_profile", new { offerId = extendRequest.OfferId }));
|
||||||
localisationService.GetText(
|
return httpResponseUtil.AppendErrorToOutput(output, localisationService.GetText("ragfair-offer_not_found_in_profile_short"));
|
||||||
"ragfair-offer_not_found_in_profile",
|
|
||||||
new { offerId = extendRequest.OfferId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
|
||||||
output,
|
|
||||||
localisationService.GetText("ragfair-offer_not_found_in_profile_short")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var playerOffer = playerOffers[playerOfferIndex];
|
var playerOffer = playerOffers[playerOfferIndex];
|
||||||
@@ -1205,8 +1058,7 @@ public class RagfairController(
|
|||||||
var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false);
|
var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false);
|
||||||
if (!sellInOncePiece)
|
if (!sellInOncePiece)
|
||||||
{
|
{
|
||||||
count = (int)
|
count = (int)playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
|
||||||
playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tax = ragfairTaxService.CalculateTax(
|
var tax = ragfairTaxService.CalculateTax(
|
||||||
@@ -1221,10 +1073,7 @@ public class RagfairController(
|
|||||||
paymentService.PayMoney(pmcData, request, sessionId, output);
|
paymentService.PayMoney(pmcData, request, sessionId, output);
|
||||||
if (output.Warnings.Count > 0)
|
if (output.Warnings.Count > 0)
|
||||||
{
|
{
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, localisationService.GetText("ragfair-unable_to_pay_commission_fee"));
|
||||||
output,
|
|
||||||
localisationService.GetText("ragfair-unable_to_pay_commission_fee")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1240,19 +1089,13 @@ public class RagfairController(
|
|||||||
/// <param name="currency">What currency: RUB, EURO, USD</param>
|
/// <param name="currency">What currency: RUB, EURO, USD</param>
|
||||||
/// <param name="value">Amount of currency</param>
|
/// <param name="value">Amount of currency</param>
|
||||||
/// <returns>ProcessBuyTradeRequestData</returns>
|
/// <returns>ProcessBuyTradeRequestData</returns>
|
||||||
protected ProcessBuyTradeRequestData CreateBuyTradeRequestObject(
|
protected ProcessBuyTradeRequestData CreateBuyTradeRequestObject(CurrencyType currency, double value)
|
||||||
CurrencyType currency,
|
|
||||||
double value
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new ProcessBuyTradeRequestData
|
return new ProcessBuyTradeRequestData
|
||||||
{
|
{
|
||||||
TransactionId = "ragfair",
|
TransactionId = "ragfair",
|
||||||
Action = "TradingConfirm",
|
Action = "TradingConfirm",
|
||||||
SchemeItems =
|
SchemeItems = [new IdWithCount { Id = currency.GetCurrencyTpl(), Count = Math.Round(value) }],
|
||||||
[
|
|
||||||
new IdWithCount { Id = currency.GetCurrencyTpl(), Count = Math.Round(value) },
|
|
||||||
],
|
|
||||||
Type = "",
|
Type = "",
|
||||||
ItemId = MongoId.Empty(),
|
ItemId = MongoId.Empty(),
|
||||||
Count = 0,
|
Count = 0,
|
||||||
|
|||||||
@@ -19,32 +19,16 @@ public class RepairController(EventOutputHolder eventOutputHolder, RepairService
|
|||||||
/// <param name="request">endpoint request data</param>
|
/// <param name="request">endpoint request data</param>
|
||||||
/// <param name="pmcData">player profile</param>
|
/// <param name="pmcData">player profile</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse TraderRepair(
|
public ItemEventRouterResponse TraderRepair(MongoId sessionID, TraderRepairActionDataRequest request, PmcData pmcData)
|
||||||
MongoId sessionID,
|
|
||||||
TraderRepairActionDataRequest request,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
// find the item to repair
|
// find the item to repair
|
||||||
foreach (var repairItem in request.RepairItems)
|
foreach (var repairItem in request.RepairItems)
|
||||||
{
|
{
|
||||||
var repairDetails = repairService.RepairItemByTrader(
|
var repairDetails = repairService.RepairItemByTrader(sessionID, pmcData, repairItem, request.TraderId);
|
||||||
sessionID,
|
|
||||||
pmcData,
|
|
||||||
repairItem,
|
|
||||||
request.TraderId
|
|
||||||
);
|
|
||||||
|
|
||||||
repairService.PayForRepair(
|
repairService.PayForRepair(sessionID, pmcData, repairItem.Id, repairDetails.RepairCost.Value, request.TraderId, output);
|
||||||
sessionID,
|
|
||||||
pmcData,
|
|
||||||
repairItem.Id,
|
|
||||||
repairDetails.RepairCost.Value,
|
|
||||||
request.TraderId,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -69,22 +53,12 @@ public class RepairController(EventOutputHolder eventOutputHolder, RepairService
|
|||||||
/// <param name="body">endpoint request data</param>
|
/// <param name="body">endpoint request data</param>
|
||||||
/// <param name="pmcData">player profile</param>
|
/// <param name="pmcData">player profile</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse RepairWithKit(
|
public ItemEventRouterResponse RepairWithKit(MongoId sessionId, RepairActionDataRequest body, PmcData pmcData)
|
||||||
MongoId sessionId,
|
|
||||||
RepairActionDataRequest body,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
// repair item
|
// repair item
|
||||||
var repairDetails = repairService.RepairItemByKit(
|
var repairDetails = repairService.RepairItemByKit(sessionId, pmcData, body.RepairKitsInfo, body.Target.Value, output);
|
||||||
sessionId,
|
|
||||||
pmcData,
|
|
||||||
body.RepairKitsInfo,
|
|
||||||
body.Target.Value,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
repairService.AddBuffToItem(repairDetails, pmcData);
|
repairService.AddBuffToItem(repairDetails, pmcData);
|
||||||
|
|
||||||
|
|||||||
@@ -46,12 +46,7 @@ public class RepeatableQuestController(
|
|||||||
ICloner cloner
|
ICloner cloner
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected static readonly FrozenSet<string> _questTypes =
|
protected static readonly FrozenSet<string> _questTypes = ["PickUp", "Exploration", "Elimination"];
|
||||||
[
|
|
||||||
"PickUp",
|
|
||||||
"Exploration",
|
|
||||||
"Elimination",
|
|
||||||
];
|
|
||||||
protected readonly QuestConfig QuestConfig = configServer.GetConfig<QuestConfig>();
|
protected readonly QuestConfig QuestConfig = configServer.GetConfig<QuestConfig>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -63,18 +58,10 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="acceptedQuest">Repeatable quest accepted</param>
|
/// <param name="acceptedQuest">Repeatable quest accepted</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse AcceptRepeatableQuest(
|
public ItemEventRouterResponse AcceptRepeatableQuest(PmcData pmcData, AcceptQuestRequestData acceptedQuest, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
AcceptQuestRequestData acceptedQuest,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Create and store quest status object inside player profile
|
// Create and store quest status object inside player profile
|
||||||
var newRepeatableQuest = questHelper.GetQuestReadyForProfile(
|
var newRepeatableQuest = questHelper.GetQuestReadyForProfile(pmcData, QuestStatusEnum.Started, acceptedQuest);
|
||||||
pmcData,
|
|
||||||
QuestStatusEnum.Started,
|
|
||||||
acceptedQuest
|
|
||||||
);
|
|
||||||
pmcData.Quests.Add(newRepeatableQuest);
|
pmcData.Quests.Add(newRepeatableQuest);
|
||||||
|
|
||||||
// Look for the generated quest cache in profile.RepeatableQuests
|
// Look for the generated quest cache in profile.RepeatableQuests
|
||||||
@@ -82,22 +69,14 @@ public class RepeatableQuestController(
|
|||||||
if (repeatableQuestProfile is null)
|
if (repeatableQuestProfile is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText("repeatable-accepted_repeatable_quest_not_found_in_active_quests", acceptedQuest.QuestId)
|
||||||
"repeatable-accepted_repeatable_quest_not_found_in_active_quests",
|
|
||||||
acceptedQuest.QuestId
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new Exception(
|
throw new Exception(serverLocalisationService.GetText("repeatable-unable_to_accept_quest_see_log"));
|
||||||
serverLocalisationService.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
|
// Some scav quests need to be added to scav profile for them to show up in-raid
|
||||||
if (
|
if (repeatableQuestProfile.Side == "Scav" && _questTypes.Contains(repeatableQuestProfile.Type.ToString()))
|
||||||
repeatableQuestProfile.Side == "Scav"
|
|
||||||
&& _questTypes.Contains(repeatableQuestProfile.Type.ToString())
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var fullProfile = profileHelper.GetFullProfile(sessionID);
|
var fullProfile = profileHelper.GetFullProfile(sessionID);
|
||||||
|
|
||||||
@@ -117,11 +96,7 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="changeRequest">Change quest request</param>
|
/// <param name="changeRequest">Change quest request</param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ChangeRepeatableQuest(
|
public ItemEventRouterResponse ChangeRepeatableQuest(PmcData pmcData, RepeatableQuestChangeRequest changeRequest, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
RepeatableQuestChangeRequest changeRequest,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -134,9 +109,7 @@ public class RepeatableQuestController(
|
|||||||
if (repeatables.RepeatableType is null || repeatables.Quest is null)
|
if (repeatables.RepeatableType is null || repeatables.Quest is null)
|
||||||
{
|
{
|
||||||
// Unable to find quest being replaced
|
// Unable to find quest being replaced
|
||||||
var message = serverLocalisationService.GetText(
|
var message = serverLocalisationService.GetText("quest-unable_to_find_repeatable_to_replace");
|
||||||
"quest-unable_to_find_repeatable_to_replace"
|
|
||||||
);
|
|
||||||
logger.Error(message);
|
logger.Error(message);
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(output, message);
|
return httpResponseUtil.AppendErrorToOutput(output, message);
|
||||||
@@ -154,17 +127,13 @@ public class RepeatableQuestController(
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Save for later cost calculations
|
// Save for later cost calculations
|
||||||
var previousChangeRequirement = cloner.Clone(
|
var previousChangeRequirement = cloner.Clone(repeatablesOfTypeInProfile.ChangeRequirement[changeRequest.QuestId]);
|
||||||
repeatablesOfTypeInProfile.ChangeRequirement[changeRequest.QuestId]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Delete the replaced quest change requirement data as we're going to add new data below
|
// Delete the replaced quest change requirement data as we're going to add new data below
|
||||||
repeatablesOfTypeInProfile.ChangeRequirement.Remove(changeRequest.QuestId);
|
repeatablesOfTypeInProfile.ChangeRequirement.Remove(changeRequest.QuestId);
|
||||||
|
|
||||||
// Get config for this repeatable subtype (daily/weekly/scav)
|
// Get config for this repeatable subtype (daily/weekly/scav)
|
||||||
var repeatableConfig = QuestConfig.RepeatableQuests.FirstOrDefault(config =>
|
var repeatableConfig = QuestConfig.RepeatableQuests.FirstOrDefault(config => config.Name == repeatablesOfTypeInProfile.Name);
|
||||||
config.Name == repeatablesOfTypeInProfile.Name
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the configuration dictates to replace with the same quest type, adjust the available quest types
|
// If the configuration dictates to replace with the same quest type, adjust the available quest types
|
||||||
if (repeatableConfig?.KeepDailyQuestTypeOnReplacement is not null)
|
if (repeatableConfig?.KeepDailyQuestTypeOnReplacement is not null)
|
||||||
@@ -173,16 +142,8 @@ public class RepeatableQuestController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate meta-data for what type/level range of quests can be generated for player
|
// Generate meta-data for what type/level range of quests can be generated for player
|
||||||
var allowedQuestTypes = GenerateQuestPool(
|
var allowedQuestTypes = GenerateQuestPool(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
|
||||||
repeatableConfig,
|
var newRepeatableQuest = AttemptToGenerateRepeatableQuest(sessionID, pmcData, allowedQuestTypes, repeatableConfig);
|
||||||
pmcData.Info.Level.GetValueOrDefault(1)
|
|
||||||
);
|
|
||||||
var newRepeatableQuest = AttemptToGenerateRepeatableQuest(
|
|
||||||
sessionID,
|
|
||||||
pmcData,
|
|
||||||
allowedQuestTypes,
|
|
||||||
repeatableConfig
|
|
||||||
);
|
|
||||||
if (newRepeatableQuest is null)
|
if (newRepeatableQuest is null)
|
||||||
{
|
{
|
||||||
// Unable to find quest being replaced
|
// Unable to find quest being replaced
|
||||||
@@ -218,11 +179,7 @@ public class RepeatableQuestController(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Check if we should charge player for replacing quest
|
// Check if we should charge player for replacing quest
|
||||||
var isFreeToReplace = UseFreeRefreshIfAvailable(
|
var isFreeToReplace = UseFreeRefreshIfAvailable(fullProfile, repeatablesOfTypeInProfile, repeatableTypeLower);
|
||||||
fullProfile,
|
|
||||||
repeatablesOfTypeInProfile,
|
|
||||||
repeatableTypeLower
|
|
||||||
);
|
|
||||||
if (!isFreeToReplace)
|
if (!isFreeToReplace)
|
||||||
{
|
{
|
||||||
// Reduce standing with trader for not doing their quest
|
// Reduce standing with trader for not doing their quest
|
||||||
@@ -233,17 +190,8 @@ public class RepeatableQuestController(
|
|||||||
foreach (var cost in previousChangeRequirement.ChangeCost)
|
foreach (var cost in previousChangeRequirement.ChangeCost)
|
||||||
{
|
{
|
||||||
// Not free, Charge player + apply charisma bonus to cost of replacement
|
// Not free, Charge player + apply charisma bonus to cost of replacement
|
||||||
cost.Count = (int)
|
cost.Count = (int)Math.Truncate(cost.Count.Value * (1 - (Math.Truncate(charismaBonus / 100) * 0.001)));
|
||||||
Math.Truncate(
|
paymentService.AddPaymentToOutput(pmcData, cost.TemplateId, cost.Count.Value, sessionID, output);
|
||||||
cost.Count.Value * (1 - (Math.Truncate(charismaBonus / 100) * 0.001))
|
|
||||||
);
|
|
||||||
paymentService.AddPaymentToOutput(
|
|
||||||
pmcData,
|
|
||||||
cost.TemplateId,
|
|
||||||
cost.Count.Value,
|
|
||||||
sessionID,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
if (output.Warnings.Count > 0)
|
if (output.Warnings.Count > 0)
|
||||||
{
|
{
|
||||||
return output;
|
return output;
|
||||||
@@ -302,11 +250,7 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="repeatableSubType">Can be daily / weekly / scav repeatable</param>
|
/// <param name="repeatableSubType">Can be daily / weekly / scav repeatable</param>
|
||||||
/// <param name="repeatableTypeName">Subtype of repeatable quest: daily / weekly / scav</param>
|
/// <param name="repeatableTypeName">Subtype of repeatable quest: daily / weekly / scav</param>
|
||||||
/// <returns>Is the repeatable being replaced for free</returns>
|
/// <returns>Is the repeatable being replaced for free</returns>
|
||||||
protected bool UseFreeRefreshIfAvailable(
|
protected bool UseFreeRefreshIfAvailable(SptProfile? fullProfile, PmcDataRepeatableQuest repeatableSubType, string repeatableTypeName)
|
||||||
SptProfile? fullProfile,
|
|
||||||
PmcDataRepeatableQuest repeatableSubType,
|
|
||||||
string repeatableTypeName
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// No free refreshes, exit early
|
// No free refreshes, exit early
|
||||||
if (repeatableSubType.FreeChangesAvailable <= 0)
|
if (repeatableSubType.FreeChangesAvailable <= 0)
|
||||||
@@ -318,9 +262,7 @@ public class RepeatableQuestController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only certain game versions have access to free refreshes
|
// Only certain game versions have access to free refreshes
|
||||||
var hasAccessToFreeRefreshSystem = profileHelper.HasAccessToRepeatableFreeRefreshSystem(
|
var hasAccessToFreeRefreshSystem = profileHelper.HasAccessToRepeatableFreeRefreshSystem(fullProfile.CharacterData.PmcData);
|
||||||
fullProfile.CharacterData.PmcData
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the player has access and available refreshes:
|
// If the player has access and available refreshes:
|
||||||
if (hasAccessToFreeRefreshSystem)
|
if (hasAccessToFreeRefreshSystem)
|
||||||
@@ -345,10 +287,7 @@ public class RepeatableQuestController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="repeatablesOfTypeInProfile">repeatables that have the replaced and new quest</param>
|
/// <param name="repeatablesOfTypeInProfile">repeatables that have the replaced and new quest</param>
|
||||||
/// <param name="replacedQuestId">Id of the replaced quest</param>
|
/// <param name="replacedQuestId">Id of the replaced quest</param>
|
||||||
protected void CleanUpRepeatableChangeRequirements(
|
protected void CleanUpRepeatableChangeRequirements(PmcDataRepeatableQuest repeatablesOfTypeInProfile, string replacedQuestId)
|
||||||
PmcDataRepeatableQuest repeatablesOfTypeInProfile,
|
|
||||||
string replacedQuestId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (repeatablesOfTypeInProfile.ActiveQuests.Count == 1)
|
if (repeatablesOfTypeInProfile.ActiveQuests.Count == 1)
|
||||||
// Only one repeatable quest being replaced (e.g. scav_daily), remove everything ready for new quest requirement to be added
|
// Only one repeatable quest being replaced (e.g. scav_daily), remove everything ready for new quest requirement to be added
|
||||||
@@ -402,12 +341,7 @@ public class RepeatableQuestController(
|
|||||||
|
|
||||||
if (attempts > maxAttempts)
|
if (attempts > maxAttempts)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("quest-repeatable_generation_failed_please_report", attempts));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"quest-repeatable_generation_failed_please_report",
|
|
||||||
attempts
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRepeatableQuest;
|
return newRepeatableQuest;
|
||||||
@@ -446,9 +380,7 @@ public class RepeatableQuestController(
|
|||||||
var traderId = randomUtil.DrawRandomFromList(traders).FirstOrDefault();
|
var traderId = randomUtil.DrawRandomFromList(traders).FirstOrDefault();
|
||||||
if (traderId.IsEmpty())
|
if (traderId.IsEmpty())
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("repeatable-unable_to_find_trader_in_pool"));
|
||||||
serverLocalisationService.GetText("repeatable-unable_to_find_trader_in_pool")
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -460,34 +392,10 @@ public class RepeatableQuestController(
|
|||||||
|
|
||||||
return questType switch
|
return questType switch
|
||||||
{
|
{
|
||||||
"Elimination" => eliminationQuestGenerator.Generate(
|
"Elimination" => eliminationQuestGenerator.Generate(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
||||||
sessionId,
|
"Completion" => completionQuestGenerator.Generate(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
||||||
pmcLevel,
|
"Exploration" => explorationQuestGenerator.Generate(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
||||||
traderId,
|
"Pickup" => pickupQuestGenerator.Generate(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
||||||
questTypePool,
|
|
||||||
repeatableConfig
|
|
||||||
),
|
|
||||||
"Completion" => completionQuestGenerator.Generate(
|
|
||||||
sessionId,
|
|
||||||
pmcLevel,
|
|
||||||
traderId,
|
|
||||||
questTypePool,
|
|
||||||
repeatableConfig
|
|
||||||
),
|
|
||||||
"Exploration" => explorationQuestGenerator.Generate(
|
|
||||||
sessionId,
|
|
||||||
pmcLevel,
|
|
||||||
traderId,
|
|
||||||
questTypePool,
|
|
||||||
repeatableConfig
|
|
||||||
),
|
|
||||||
"Pickup" => pickupQuestGenerator.Generate(
|
|
||||||
sessionId,
|
|
||||||
pmcLevel,
|
|
||||||
traderId,
|
|
||||||
questTypePool,
|
|
||||||
repeatableConfig
|
|
||||||
),
|
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -500,18 +408,12 @@ public class RepeatableQuestController(
|
|||||||
protected void RemoveQuestFromProfile(SptProfile fullProfile, MongoId questToReplaceId)
|
protected void RemoveQuestFromProfile(SptProfile fullProfile, MongoId questToReplaceId)
|
||||||
{
|
{
|
||||||
// Find quest we're replacing in pmc profile quests array and remove it
|
// Find quest we're replacing in pmc profile quests array and remove it
|
||||||
questHelper.FindAndRemoveQuestFromArrayIfExists(
|
questHelper.FindAndRemoveQuestFromArrayIfExists(questToReplaceId, fullProfile.CharacterData.PmcData.Quests);
|
||||||
questToReplaceId,
|
|
||||||
fullProfile.CharacterData.PmcData.Quests
|
|
||||||
);
|
|
||||||
|
|
||||||
// Look for and remove quest we're replacing in scav profile too
|
// Look for and remove quest we're replacing in scav profile too
|
||||||
if (fullProfile.CharacterData.ScavData is not null)
|
if (fullProfile.CharacterData.ScavData is not null)
|
||||||
{
|
{
|
||||||
questHelper.FindAndRemoveQuestFromArrayIfExists(
|
questHelper.FindAndRemoveQuestFromArrayIfExists(questToReplaceId, fullProfile.CharacterData.ScavData.Quests);
|
||||||
questToReplaceId,
|
|
||||||
fullProfile.CharacterData.ScavData.Quests
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,20 +428,14 @@ public class RepeatableQuestController(
|
|||||||
foreach (var repeatablesInProfile in pmcData.RepeatableQuests)
|
foreach (var repeatablesInProfile in pmcData.RepeatableQuests)
|
||||||
{
|
{
|
||||||
// Check for existing quest in (daily/weekly/scav arrays)
|
// Check for existing quest in (daily/weekly/scav arrays)
|
||||||
var questToReplace = repeatablesInProfile.ActiveQuests?.FirstOrDefault(repeatable =>
|
var questToReplace = repeatablesInProfile.ActiveQuests?.FirstOrDefault(repeatable => repeatable.Id == questId);
|
||||||
repeatable.Id == questId
|
|
||||||
);
|
|
||||||
if (questToReplace is null)
|
if (questToReplace is null)
|
||||||
// Not found, skip to next repeatable subtype
|
// Not found, skip to next repeatable subtype
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GetRepeatableByIdResult
|
return new GetRepeatableByIdResult { Quest = questToReplace, RepeatableType = repeatablesInProfile };
|
||||||
{
|
|
||||||
Quest = questToReplace,
|
|
||||||
RepeatableType = repeatablesInProfile,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -577,10 +473,7 @@ public class RepeatableQuestController(
|
|||||||
foreach (var repeatableConfig in QuestConfig.RepeatableQuests)
|
foreach (var repeatableConfig in QuestConfig.RepeatableQuests)
|
||||||
{
|
{
|
||||||
// Get daily/weekly data from profile, add empty object if missing
|
// Get daily/weekly data from profile, add empty object if missing
|
||||||
var generatedRepeatables = GetRepeatableQuestSubTypeFromProfile(
|
var generatedRepeatables = GetRepeatableQuestSubTypeFromProfile(repeatableConfig, pmcData);
|
||||||
repeatableConfig,
|
|
||||||
pmcData
|
|
||||||
);
|
|
||||||
var repeatableTypeLower = repeatableConfig.Name.ToLowerInvariant();
|
var repeatableTypeLower = repeatableConfig.Name.ToLowerInvariant();
|
||||||
|
|
||||||
var canAccessRepeatables = CanProfileAccessRepeatableQuests(repeatableConfig, pmcData);
|
var canAccessRepeatables = CanProfileAccessRepeatableQuests(repeatableConfig, pmcData);
|
||||||
@@ -620,10 +513,7 @@ public class RepeatableQuestController(
|
|||||||
ProcessExpiredQuests(generatedRepeatables, pmcData);
|
ProcessExpiredQuests(generatedRepeatables, pmcData);
|
||||||
|
|
||||||
// Create dynamic quest pool to avoid generating duplicates
|
// Create dynamic quest pool to avoid generating duplicates
|
||||||
var questTypePool = GenerateQuestPool(
|
var questTypePool = GenerateQuestPool(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
|
||||||
repeatableConfig,
|
|
||||||
pmcData.Info.Level.GetValueOrDefault(1)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add repeatable quests of this loops sub-type (daily/weekly)
|
// Add repeatable quests of this loops sub-type (daily/weekly)
|
||||||
for (var i = 0; i < GetQuestCount(repeatableConfig, fullProfile); i++)
|
for (var i = 0; i < GetQuestCount(repeatableConfig, fullProfile); i++)
|
||||||
@@ -642,9 +532,7 @@ public class RepeatableQuestController(
|
|||||||
lifeline++;
|
lifeline++;
|
||||||
if (lifeline > 10)
|
if (lifeline > 10)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error("We were stuck in repeatable quest generation. This should never happen. Please report");
|
||||||
"We were stuck in repeatable quest generation. This should never happen. Please report"
|
|
||||||
);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -675,9 +563,7 @@ public class RepeatableQuestController(
|
|||||||
new ChangeRequirement
|
new ChangeRequirement
|
||||||
{
|
{
|
||||||
ChangeCost = quest.ChangeCost,
|
ChangeCost = quest.ChangeCost,
|
||||||
ChangeStandingCost = randomUtil.GetArrayValue(
|
ChangeStandingCost = randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost), // Randomise standing loss to replace
|
||||||
repeatableConfig.StandingChangeCost
|
|
||||||
), // Randomise standing loss to replace
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -709,15 +595,10 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="repeatableConfig">daily/weekly config</param>
|
/// <param name="repeatableConfig">daily/weekly config</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <returns>PmcDataRepeatableQuest</returns>
|
/// <returns>PmcDataRepeatableQuest</returns>
|
||||||
protected PmcDataRepeatableQuest GetRepeatableQuestSubTypeFromProfile(
|
protected PmcDataRepeatableQuest GetRepeatableQuestSubTypeFromProfile(RepeatableQuestConfig repeatableConfig, PmcData pmcData)
|
||||||
RepeatableQuestConfig repeatableConfig,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get from profile, add if missing
|
// Get from profile, add if missing
|
||||||
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable =>
|
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable => repeatable.Name == repeatableConfig.Name);
|
||||||
repeatable.Name == repeatableConfig.Name
|
|
||||||
);
|
|
||||||
var hasAccess = profileHelper.HasAccessToRepeatableFreeRefreshSystem(pmcData);
|
var hasAccess = profileHelper.HasAccessToRepeatableFreeRefreshSystem(pmcData);
|
||||||
|
|
||||||
if (repeatableQuestDetails is null)
|
if (repeatableQuestDetails is null)
|
||||||
@@ -755,16 +636,10 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="repeatableConfig">Repeatable quest config</param>
|
/// <param name="repeatableConfig">Repeatable quest config</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <returns>True if profile has access to repeatables</returns>
|
/// <returns>True if profile has access to repeatables</returns>
|
||||||
protected bool CanProfileAccessRepeatableQuests(
|
protected bool CanProfileAccessRepeatableQuests(RepeatableQuestConfig repeatableConfig, PmcData pmcData)
|
||||||
RepeatableQuestConfig repeatableConfig,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// PMC and daily quests not unlocked yet
|
// PMC and daily quests not unlocked yet
|
||||||
if (
|
if (repeatableConfig.Side == PlayerGroup.Pmc && !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig))
|
||||||
repeatableConfig.Side == PlayerGroup.Pmc
|
|
||||||
&& !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -789,10 +664,7 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="repeatableConfig">Config of daily type to check</param>
|
/// <param name="repeatableConfig">Config of daily type to check</param>
|
||||||
/// <returns>True if unlocked</returns>
|
/// <returns>True if unlocked</returns>
|
||||||
protected static bool PlayerHasDailyPmcQuestsUnlocked(
|
protected static bool PlayerHasDailyPmcQuestsUnlocked(PmcData pmcData, RepeatableQuestConfig repeatableConfig)
|
||||||
PmcData pmcData,
|
|
||||||
RepeatableQuestConfig repeatableConfig
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return pmcData.Info.Level >= repeatableConfig.MinPlayerLevel;
|
return pmcData.Info.Level >= repeatableConfig.MinPlayerLevel;
|
||||||
}
|
}
|
||||||
@@ -804,11 +676,7 @@ public class RepeatableQuestController(
|
|||||||
/// <returns>True if unlocked</returns>
|
/// <returns>True if unlocked</returns>
|
||||||
protected bool PlayerHasDailyScavQuestsUnlocked(PmcData pmcData)
|
protected bool PlayerHasDailyScavQuestsUnlocked(PmcData pmcData)
|
||||||
{
|
{
|
||||||
return pmcData
|
return pmcData.Hideout?.Areas?.FirstOrDefault(hideoutArea => hideoutArea.Type == HideoutAreas.IntelligenceCenter)?.Level >= 1;
|
||||||
.Hideout?.Areas?.FirstOrDefault(hideoutArea =>
|
|
||||||
hideoutArea.Type == HideoutAreas.IntelligenceCenter
|
|
||||||
)
|
|
||||||
?.Level >= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -816,17 +684,12 @@ public class RepeatableQuestController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="generatedRepeatables">Repeatables to process (daily/weekly)</param>
|
/// <param name="generatedRepeatables">Repeatables to process (daily/weekly)</param>
|
||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
protected void ProcessExpiredQuests(
|
protected void ProcessExpiredQuests(PmcDataRepeatableQuest generatedRepeatables, PmcData pmcData)
|
||||||
PmcDataRepeatableQuest generatedRepeatables,
|
|
||||||
PmcData pmcData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var questsToKeep = new List<RepeatableQuest>();
|
var questsToKeep = new List<RepeatableQuest>();
|
||||||
foreach (var activeQuest in generatedRepeatables.ActiveQuests)
|
foreach (var activeQuest in generatedRepeatables.ActiveQuests)
|
||||||
{
|
{
|
||||||
var questStatusInProfile = pmcData.Quests.FirstOrDefault(quest =>
|
var questStatusInProfile = pmcData.Quests.FirstOrDefault(quest => quest.QId == activeQuest.Id);
|
||||||
quest.QId == activeQuest.Id
|
|
||||||
);
|
|
||||||
if (questStatusInProfile is null)
|
if (questStatusInProfile is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -884,14 +747,8 @@ public class RepeatableQuestController(
|
|||||||
// Add "any" to pickup quest pool
|
// Add "any" to pickup quest pool
|
||||||
questPool.Pool.Pickup.Locations[ELocationName.any] = ["any"];
|
questPool.Pool.Pickup.Locations[ELocationName.any] = ["any"];
|
||||||
|
|
||||||
var eliminationConfig = repeatableQuestHelper.GetEliminationConfigByPmcLevel(
|
var eliminationConfig = repeatableQuestHelper.GetEliminationConfigByPmcLevel(pmcLevel, repeatableConfig);
|
||||||
pmcLevel,
|
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(cloner, eliminationConfig.Targets);
|
||||||
repeatableConfig
|
|
||||||
);
|
|
||||||
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(
|
|
||||||
cloner,
|
|
||||||
eliminationConfig.Targets
|
|
||||||
);
|
|
||||||
|
|
||||||
// Populate Elimination quest targets and their locations
|
// Populate Elimination quest targets and their locations
|
||||||
foreach (var target in targetsConfig)
|
foreach (var target in targetsConfig)
|
||||||
@@ -899,10 +756,7 @@ public class RepeatableQuestController(
|
|||||||
// Target is boss
|
// Target is boss
|
||||||
if (target.Data?.IsBoss ?? false)
|
if (target.Data?.IsBoss ?? false)
|
||||||
{
|
{
|
||||||
questPool.Pool.Elimination.Targets.Add(
|
questPool.Pool.Elimination.Targets.Add(target.Key, new TargetLocation { Locations = ["any"] });
|
||||||
target.Key,
|
|
||||||
new TargetLocation { Locations = ["any"] }
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -916,10 +770,7 @@ public class RepeatableQuestController(
|
|||||||
|
|
||||||
questPool.Pool.Elimination.Targets.Add(
|
questPool.Pool.Elimination.Targets.Add(
|
||||||
target.Key,
|
target.Key,
|
||||||
new TargetLocation
|
new TargetLocation { Locations = allowedLocations.Select(x => x.ToString()).ToList() }
|
||||||
{
|
|
||||||
Locations = allowedLocations.Select(x => x.ToString()).ToList(),
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -938,18 +789,9 @@ public class RepeatableQuestController(
|
|||||||
Types = cloner.Clone(repeatableConfig.Types)!,
|
Types = cloner.Clone(repeatableConfig.Types)!,
|
||||||
Pool = new QuestPool
|
Pool = new QuestPool
|
||||||
{
|
{
|
||||||
Exploration = new ExplorationPool
|
Exploration = new ExplorationPool { Locations = new Dictionary<ELocationName, List<string>>() },
|
||||||
{
|
Elimination = new EliminationPool { Targets = new Dictionary<string, TargetLocation>() },
|
||||||
Locations = new Dictionary<ELocationName, List<string>>(),
|
Pickup = new ExplorationPool { Locations = new Dictionary<ELocationName, List<string>>() },
|
||||||
},
|
|
||||||
Elimination = new EliminationPool
|
|
||||||
{
|
|
||||||
Targets = new Dictionary<string, TargetLocation>(),
|
|
||||||
},
|
|
||||||
Pickup = new ExplorationPool
|
|
||||||
{
|
|
||||||
Locations = new Dictionary<ELocationName, List<string>>(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -971,10 +813,7 @@ public class RepeatableQuestController(
|
|||||||
// Add elite bonus to daily quests
|
// Add elite bonus to daily quests
|
||||||
if (
|
if (
|
||||||
string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase)
|
string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase)
|
||||||
&& profileHelper.HasEliteSkillLevel(
|
&& profileHelper.HasEliteSkillLevel(SkillTypes.Charisma, fullProfile.CharacterData.PmcData)
|
||||||
SkillTypes.Charisma,
|
|
||||||
fullProfile.CharacterData.PmcData
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
// Elite charisma skill gives extra daily quest(s)
|
// Elite charisma skill gives extra daily quest(s)
|
||||||
{
|
{
|
||||||
@@ -984,8 +823,7 @@ public class RepeatableQuestController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add any extra repeatable quests the profile has unlocked
|
// Add any extra repeatable quests the profile has unlocked
|
||||||
questCount += (int)
|
questCount += (int)fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
|
||||||
fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
|
|
||||||
|
|
||||||
return questCount;
|
return questCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,7 @@ public class TradeController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ConfirmTrading(
|
public ItemEventRouterResponse ConfirmTrading(PmcData pmcData, ProcessBaseTradeRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ProcessBaseTradeRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -76,11 +72,7 @@ public class TradeController(
|
|||||||
var errorMessage = $"Unhandled trade event: {request.Type}";
|
var errorMessage = $"Unhandled trade event: {request.Type}";
|
||||||
logger.Error(errorMessage);
|
logger.Error(errorMessage);
|
||||||
|
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
|
||||||
output,
|
|
||||||
errorMessage,
|
|
||||||
BackendErrorCodes.RagfairUnavailable
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -90,11 +82,7 @@ public class TradeController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ConfirmRagfairTrading(
|
public ItemEventRouterResponse ConfirmRagfairTrading(PmcData pmcData, ProcessRagfairTradeRequestData request, MongoId sessionID)
|
||||||
PmcData pmcData,
|
|
||||||
ProcessRagfairTradeRequestData request,
|
|
||||||
MongoId sessionID
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionID);
|
var output = eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -103,11 +91,7 @@ public class TradeController(
|
|||||||
var fleaOffer = ragfairServer.GetOffer(offer.Id);
|
var fleaOffer = ragfairServer.GetOffer(offer.Id);
|
||||||
if (fleaOffer is null)
|
if (fleaOffer is null)
|
||||||
{
|
{
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, $"Offer with ID {offer.Id} not found", BackendErrorCodes.OfferNotFound);
|
||||||
output,
|
|
||||||
$"Offer with ID {offer.Id} not found",
|
|
||||||
BackendErrorCodes.OfferNotFound
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offer.Count == 0)
|
if (offer.Count == 0)
|
||||||
@@ -116,11 +100,7 @@ public class TradeController(
|
|||||||
"ragfair-unable_to_purchase_0_count_item",
|
"ragfair-unable_to_purchase_0_count_item",
|
||||||
itemHelper.GetItem(fleaOffer.Items[0].Template).Value.Name
|
itemHelper.GetItem(fleaOffer.Items[0].Template).Value.Name
|
||||||
);
|
);
|
||||||
return httpResponseUtil.AppendErrorToOutput(
|
return httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.OfferOutOfStock);
|
||||||
output,
|
|
||||||
errorMessage,
|
|
||||||
BackendErrorCodes.OfferOutOfStock
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fleaOffer.IsTraderOffer())
|
if (fleaOffer.IsTraderOffer())
|
||||||
@@ -168,11 +148,7 @@ public class TradeController(
|
|||||||
logger.Debug(errorMessage);
|
logger.Debug(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
httpResponseUtil.AppendErrorToOutput(
|
httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
|
||||||
output,
|
|
||||||
errorMessage,
|
|
||||||
BackendErrorCodes.RagfairUnavailable
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -188,13 +164,7 @@ public class TradeController(
|
|||||||
SchemeId = 0,
|
SchemeId = 0,
|
||||||
SchemeItems = requestOffer.Items,
|
SchemeItems = requestOffer.Items,
|
||||||
};
|
};
|
||||||
tradeHelper.BuyItem(
|
tradeHelper.BuyItem(pmcData, buyData, sessionId, _traderConfig.PurchasesAreFoundInRaid, output);
|
||||||
pmcData,
|
|
||||||
buyData,
|
|
||||||
sessionId,
|
|
||||||
_traderConfig.PurchasesAreFoundInRaid,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove/lower offer quantity of item purchased from trader flea offer
|
// Remove/lower offer quantity of item purchased from trader flea offer
|
||||||
ragfairServer.ReduceOfferQuantity(fleaOffer.Id, requestOffer.Count ?? 0);
|
ragfairServer.ReduceOfferQuantity(fleaOffer.Id, requestOffer.Count ?? 0);
|
||||||
@@ -228,13 +198,7 @@ public class TradeController(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// buyItem() must occur prior to removing the offer stack, otherwise item inside offer doesn't exist for confirmTrading() to use
|
// buyItem() must occur prior to removing the offer stack, otherwise item inside offer doesn't exist for confirmTrading() to use
|
||||||
tradeHelper.BuyItem(
|
tradeHelper.BuyItem(pmcData, buyData, sessionId, _ragfairConfig.Dynamic.PurchasesAreFoundInRaid, output);
|
||||||
pmcData,
|
|
||||||
buyData,
|
|
||||||
sessionId,
|
|
||||||
_ragfairConfig.Dynamic.PurchasesAreFoundInRaid,
|
|
||||||
output
|
|
||||||
);
|
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -274,11 +238,7 @@ public class TradeController(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SellScavItemsToFence(
|
public ItemEventRouterResponse SellScavItemsToFence(PmcData pmcData, SellScavItemsToFenceRequestData request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
SellScavItemsToFenceRequestData request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var output = eventOutputHolder.GetOutput(sessionId);
|
var output = eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -316,11 +276,7 @@ public class TradeController(
|
|||||||
sessionId,
|
sessionId,
|
||||||
trader,
|
trader,
|
||||||
MessageType.MessageWithItems,
|
MessageType.MessageWithItems,
|
||||||
randomUtil.GetArrayValue(
|
randomUtil.GetArrayValue(databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items) ? items : []),
|
||||||
databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items)
|
|
||||||
? items
|
|
||||||
: []
|
|
||||||
),
|
|
||||||
currencyReward.SelectMany(x => x).ToList(),
|
currencyReward.SelectMany(x => x).ToList(),
|
||||||
timeUtil.GetHoursAsSeconds(72)
|
timeUtil.GetHoursAsSeconds(72)
|
||||||
);
|
);
|
||||||
@@ -347,25 +303,14 @@ public class TradeController(
|
|||||||
foreach (var itemToSell in itemWithChildren)
|
foreach (var itemToSell in itemWithChildren)
|
||||||
{
|
{
|
||||||
var itemDetails = itemHelper.GetItem(itemToSell.Template);
|
var itemDetails = itemHelper.GetItem(itemToSell.Template);
|
||||||
if (
|
if (!(itemDetails.Key && itemHelper.IsOfBaseclasses(itemDetails.Value.Id, traderDetails.ItemsBuy.Category)))
|
||||||
!(
|
|
||||||
itemDetails.Key
|
|
||||||
&& itemHelper.IsOfBaseclasses(
|
|
||||||
itemDetails.Value.Id,
|
|
||||||
traderDetails.ItemsBuy.Category
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
|
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get price of item multiplied by how many are in stack
|
// Get price of item multiplied by how many are in stack
|
||||||
totalPrice += (int)(
|
totalPrice += (int)((handbookPrices[itemToSell.Template] ?? 0) * (itemToSell.Upd?.StackObjectsCount ?? 1));
|
||||||
(handbookPrices[itemToSell.Template] ?? 0)
|
|
||||||
* (itemToSell.Upd?.StackObjectsCount ?? 1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalPrice;
|
return totalPrice;
|
||||||
|
|||||||
@@ -83,10 +83,7 @@ public class TraderController(
|
|||||||
foreach (var kvp in trader.Assort?.BarterScheme)
|
foreach (var kvp in trader.Assort?.BarterScheme)
|
||||||
{
|
{
|
||||||
var barterSchemeItem = kvp.Value.FirstOrDefault()?.FirstOrDefault();
|
var barterSchemeItem = kvp.Value.FirstOrDefault()?.FirstOrDefault();
|
||||||
if (
|
if (barterSchemeItem?.Template != null && paymentHelper.IsMoneyTpl(barterSchemeItem.Template))
|
||||||
barterSchemeItem?.Template != null
|
|
||||||
&& paymentHelper.IsMoneyTpl(barterSchemeItem.Template)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
barterSchemeItem.Count += Math.Round(barterSchemeItem?.Count * multiplier ?? 0D, 2);
|
barterSchemeItem.Count += Math.Round(barterSchemeItem?.Count * multiplier ?? 0D, 2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,7 @@ public class WeatherController(
|
|||||||
/// <returns>GetLocalWeatherResponseData</returns>
|
/// <returns>GetLocalWeatherResponseData</returns>
|
||||||
public GetLocalWeatherResponseData GenerateLocal(MongoId sessionId)
|
public GetLocalWeatherResponseData GenerateLocal(MongoId sessionId)
|
||||||
{
|
{
|
||||||
var result = new GetLocalWeatherResponseData
|
var result = new GetLocalWeatherResponseData { Season = seasonalEventService.GetActiveWeatherSeason(), Weather = [] };
|
||||||
{
|
|
||||||
Season = seasonalEventService.GetActiveWeatherSeason(),
|
|
||||||
Weather = [],
|
|
||||||
};
|
|
||||||
|
|
||||||
result.Weather.AddRange(raidWeatherService.GetUpcomingWeather());
|
result.Weather.AddRange(raidWeatherService.GetUpcomingWeather());
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ public class WishlistController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse AddToWishList(
|
public ItemEventRouterResponse AddToWishList(PmcData pmcData, AddToWishlistRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
AddToWishlistRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
pmcData.WishList ??= new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
pmcData.WishList ??= new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
||||||
foreach (var item in request.Items)
|
foreach (var item in request.Items)
|
||||||
@@ -40,11 +36,7 @@ public class WishlistController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse RemoveFromWishList(
|
public ItemEventRouterResponse RemoveFromWishList(PmcData pmcData, RemoveFromWishlistRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
RemoveFromWishlistRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var itemId in request.Items)
|
foreach (var itemId in request.Items)
|
||||||
{
|
{
|
||||||
@@ -61,11 +53,7 @@ public class WishlistController(EventOutputHolder eventOutputHolder)
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse ChangeWishListItemCategory(
|
public ItemEventRouterResponse ChangeWishListItemCategory(PmcData pmcData, ChangeWishlistItemCategoryRequest request, MongoId sessionId)
|
||||||
PmcData pmcData,
|
|
||||||
ChangeWishlistItemCategoryRequest request,
|
|
||||||
MongoId sessionId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
pmcData.WishList.Dictionary[request.Item] = request.Category.Value;
|
pmcData.WishList.Dictionary[request.Item] = request.Category.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -42,12 +42,7 @@ public abstract class Router
|
|||||||
|
|
||||||
public abstract class StaticRouter(JsonUtil jsonUtil, IEnumerable<RouteAction> routes) : Router
|
public abstract class StaticRouter(JsonUtil jsonUtil, IEnumerable<RouteAction> routes) : Router
|
||||||
{
|
{
|
||||||
public async ValueTask<object> HandleStatic(
|
public async ValueTask<object> HandleStatic(string url, string? body, MongoId sessionId, string output)
|
||||||
string url,
|
|
||||||
string? body,
|
|
||||||
MongoId sessionId,
|
|
||||||
string output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var action = routes.Single(route => route.url == url);
|
var action = routes.Single(route => route.url == url);
|
||||||
var type = action.bodyType;
|
var type = action.bodyType;
|
||||||
@@ -68,12 +63,7 @@ public abstract class StaticRouter(JsonUtil jsonUtil, IEnumerable<RouteAction> r
|
|||||||
|
|
||||||
public abstract class DynamicRouter(JsonUtil jsonUtil, IEnumerable<RouteAction> routes) : Router
|
public abstract class DynamicRouter(JsonUtil jsonUtil, IEnumerable<RouteAction> routes) : Router
|
||||||
{
|
{
|
||||||
public async ValueTask<object> HandleDynamic(
|
public async ValueTask<object> HandleDynamic(string url, string? body, MongoId sessionID, string output)
|
||||||
string url,
|
|
||||||
string? body,
|
|
||||||
MongoId sessionID,
|
|
||||||
string output
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var action = routes.First(r => url.Contains(r.url));
|
var action = routes.First(r => url.Contains(r.url));
|
||||||
var type = action.bodyType;
|
var type = action.bodyType;
|
||||||
@@ -112,9 +102,5 @@ public abstract class SaveLoadRouter : Router
|
|||||||
|
|
||||||
public record HandledRoute(string route, bool dynamic);
|
public record HandledRoute(string route, bool dynamic);
|
||||||
|
|
||||||
public record RouteAction(
|
public record RouteAction(string url, Func<string, IRequestData?, MongoId, string?, ValueTask<object>> action, Type? bodyType = null);
|
||||||
string url,
|
|
||||||
Func<string, IRequestData?, MongoId, string?, ValueTask<object>> action,
|
|
||||||
Type? bodyType = null
|
|
||||||
);
|
|
||||||
//public action: (url: string, info: any, sessionID: string, output: string) => Promise<any>,
|
//public action: (url: string, info: any, sessionID: string, output: string) => Promise<any>,
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="itemWidthX">Width of item</param>
|
/// <param name="itemWidthX">Width of item</param>
|
||||||
/// <param name="itemHeightY">Height of item</param>
|
/// <param name="itemHeightY">Height of item</param>
|
||||||
/// <returns>Location to place item in container</returns>
|
/// <returns>Location to place item in container</returns>
|
||||||
public static FindSlotResult FindSlotForItem(
|
public static FindSlotResult FindSlotForItem(this int[,] container2D, int? itemWidthX, int? itemHeightY)
|
||||||
this int[,] container2D,
|
|
||||||
int? itemWidthX,
|
|
||||||
int? itemHeightY
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Assume not rotated
|
// Assume not rotated
|
||||||
var rotation = false;
|
var rotation = false;
|
||||||
@@ -45,15 +41,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
for (var column = 0; column < limitX; column++)
|
for (var column = 0; column < limitX; column++)
|
||||||
{
|
{
|
||||||
// Does item fit
|
// Does item fit
|
||||||
if (
|
if (CanItemBePlacedInContainerAtPosition(container2D, row, column, itemWidthX.Value, itemHeightY.Value))
|
||||||
CanItemBePlacedInContainerAtPosition(
|
|
||||||
container2D,
|
|
||||||
row,
|
|
||||||
column,
|
|
||||||
itemWidthX.Value,
|
|
||||||
itemHeightY.Value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Success, found a spot it fits
|
// Success, found a spot it fits
|
||||||
return new FindSlotResult(true, column, row, rotation);
|
return new FindSlotResult(true, column, row, rotation);
|
||||||
|
|||||||
@@ -93,13 +93,7 @@
|
|||||||
/// <param name="endMonth">Upper bound for month</param>
|
/// <param name="endMonth">Upper bound for month</param>
|
||||||
/// <param name="endDay">Upper bound for day</param>
|
/// <param name="endDay">Upper bound for day</param>
|
||||||
/// <returns>True when inside date range</returns>
|
/// <returns>True when inside date range</returns>
|
||||||
public static bool DateIsBetweenTwoDates(
|
public static bool DateIsBetweenTwoDates(this DateTime dateToCheck, int startMonth, int startDay, int endMonth, int endDay)
|
||||||
this DateTime dateToCheck,
|
|
||||||
int startMonth,
|
|
||||||
int startDay,
|
|
||||||
int endMonth,
|
|
||||||
int endDay
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var eventStartDate = new DateTime(dateToCheck.Year, startMonth, startDay);
|
var eventStartDate = new DateTime(dateToCheck.Year, startMonth, startDay);
|
||||||
var eventEndDate = new DateTime(dateToCheck.Year, endMonth, endDay, 23, 59, 0);
|
var eventEndDate = new DateTime(dateToCheck.Year, endMonth, endDay, 23, 59, 0);
|
||||||
@@ -113,10 +107,7 @@
|
|||||||
/// <param name="dateTime">Date to get closest monday of</param>
|
/// <param name="dateTime">Date to get closest monday of</param>
|
||||||
/// <param name="startDay">Starting day of week - Default = Monday</param>
|
/// <param name="startDay">Starting day of week - Default = Monday</param>
|
||||||
/// <returns>Monday as DateTime</returns>
|
/// <returns>Monday as DateTime</returns>
|
||||||
public static DateTime GetClosestDate(
|
public static DateTime GetClosestDate(this DateTime dateTime, DayOfWeek startDay = DayOfWeek.Monday)
|
||||||
this DateTime dateTime,
|
|
||||||
DayOfWeek startDay = DayOfWeek.Monday
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Calculate difference from current day to Monday
|
// Calculate difference from current day to Monday
|
||||||
var diff = (7 + (dateTime.DayOfWeek - startDay)) % 7;
|
var diff = (7 + (dateTime.DayOfWeek - startDay)) % 7;
|
||||||
@@ -132,11 +123,7 @@
|
|||||||
/// <param name="desiredDay">Desired day to find</param>
|
/// <param name="desiredDay">Desired day to find</param>
|
||||||
/// <param name="inclusiveOfToday">Should today be included in check, default = true</param>
|
/// <param name="inclusiveOfToday">Should today be included in check, default = true</param>
|
||||||
/// <returns>Datetime of desired day</returns>
|
/// <returns>Datetime of desired day</returns>
|
||||||
public static DateTime GetMostRecentPreviousDay(
|
public static DateTime GetMostRecentPreviousDay(this DateTime dateTime, DayOfWeek desiredDay, bool inclusiveOfToday = true)
|
||||||
this DateTime dateTime,
|
|
||||||
DayOfWeek desiredDay,
|
|
||||||
bool inclusiveOfToday = true
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get difference in day count from today to what day we want
|
// Get difference in day count from today to what day we want
|
||||||
var dayDifferenceCount = (dateTime.DayOfWeek - desiredDay + 7) % 7;
|
var dayDifferenceCount = (dateTime.DayOfWeek - desiredDay + 7) % 7;
|
||||||
|
|||||||
@@ -12,20 +12,13 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fullProfile">Profile to add clothing to</param>
|
/// <param name="fullProfile">Profile to add clothing to</param>
|
||||||
/// <param name="clothingIds">Clothing Ids to add to profile</param>
|
/// <param name="clothingIds">Clothing Ids to add to profile</param>
|
||||||
public static void AddSuitsToProfile(
|
public static void AddSuitsToProfile(this SptProfile fullProfile, IEnumerable<MongoId> clothingIds)
|
||||||
this SptProfile fullProfile,
|
|
||||||
IEnumerable<MongoId> clothingIds
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
fullProfile.CustomisationUnlocks ??= [];
|
fullProfile.CustomisationUnlocks ??= [];
|
||||||
|
|
||||||
foreach (var suitId in clothingIds)
|
foreach (var suitId in clothingIds)
|
||||||
{
|
{
|
||||||
if (
|
if (!fullProfile.CustomisationUnlocks.Exists(customisation => customisation.Id == suitId))
|
||||||
!fullProfile.CustomisationUnlocks.Exists(customisation =>
|
|
||||||
customisation.Id == suitId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Clothing item doesn't exist in profile, add it
|
// Clothing item doesn't exist in profile, add it
|
||||||
fullProfile.CustomisationUnlocks.Add(
|
fullProfile.CustomisationUnlocks.Add(
|
||||||
@@ -207,11 +200,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="fullProfile">Profile to add the extra repeatable to</param>
|
/// <param name="fullProfile">Profile to add the extra repeatable to</param>
|
||||||
/// <param name="repeatableId">The ID of the type of repeatable to increase</param>
|
/// <param name="repeatableId">The ID of the type of repeatable to increase</param>
|
||||||
/// <param name="rewardValue">The number of extra repeatables to add</param>
|
/// <param name="rewardValue">The number of extra repeatables to add</param>
|
||||||
public static void AddExtraRepeatableQuest(
|
public static void AddExtraRepeatableQuest(this SptProfile fullProfile, MongoId repeatableId, double rewardValue)
|
||||||
this SptProfile fullProfile,
|
|
||||||
MongoId repeatableId,
|
|
||||||
double rewardValue
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
fullProfile.SptData.ExtraRepeatableQuests ??= new Dictionary<MongoId, double>();
|
fullProfile.SptData.ExtraRepeatableQuests ??= new Dictionary<MongoId, double>();
|
||||||
|
|
||||||
@@ -228,8 +217,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <returns>True if account is developer</returns>
|
/// <returns>True if account is developer</returns>
|
||||||
public static bool IsDeveloperAccount(this SptProfile fullProfile)
|
public static bool IsDeveloperAccount(this SptProfile fullProfile)
|
||||||
{
|
{
|
||||||
return fullProfile?.ProfileInfo?.Edition?.ToLowerInvariant().StartsWith("spt developer")
|
return fullProfile?.ProfileInfo?.Edition?.ToLowerInvariant().StartsWith("spt developer") ?? false;
|
||||||
?? false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="output">Response to add item change event into</param>
|
/// <param name="output">Response to add item change event into</param>
|
||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <param name="item">Item that was adjusted</param>
|
/// <param name="item">Item that was adjusted</param>
|
||||||
public static void AddItemStackSizeChangeIntoEventResponse(
|
public static void AddItemStackSizeChangeIntoEventResponse(this ItemEventRouterResponse output, MongoId sessionId, Item item)
|
||||||
this ItemEventRouterResponse output,
|
|
||||||
MongoId sessionId,
|
|
||||||
Item item
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// TODO: replace with something safer like TryGet
|
// TODO: replace with something safer like TryGet
|
||||||
output
|
output
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="item2">second item to compare</param>
|
/// <param name="item2">second item to compare</param>
|
||||||
/// <param name="compareUpdProperties">Upd properties to compare between the items</param>
|
/// <param name="compareUpdProperties">Upd properties to compare between the items</param>
|
||||||
/// <returns>true if they are the same</returns>
|
/// <returns>true if they are the same</returns>
|
||||||
public static bool IsSameItem(
|
public static bool IsSameItem(this Item item1, Item item2, ISet<string>? compareUpdProperties = null)
|
||||||
this Item item1,
|
|
||||||
Item item2,
|
|
||||||
ISet<string>? compareUpdProperties = null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Different tpl == different item
|
// Different tpl == different item
|
||||||
if (item1.Template != item2.Template)
|
if (item1.Template != item2.Template)
|
||||||
@@ -51,48 +47,23 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
var comparers = new Dictionary<string, Func<Upd, Upd, bool>>
|
var comparers = new Dictionary<string, Func<Upd, Upd, bool>>
|
||||||
{
|
{
|
||||||
{ "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages },
|
{ "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages },
|
||||||
{
|
{ "Buff", (upd1, upd2) => upd1.Buff?.Value == upd2.Buff?.Value && upd1.Buff?.BuffType == upd2.Buff?.BuffType },
|
||||||
"Buff",
|
{ "CultistAmulet", (upd1, upd2) => upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages },
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.Buff?.Value == upd2.Buff?.Value
|
|
||||||
&& upd1.Buff?.BuffType == upd2.Buff?.BuffType
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CultistAmulet",
|
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages
|
|
||||||
},
|
|
||||||
{ "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId },
|
{ "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId },
|
||||||
{ "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits },
|
{ "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits },
|
||||||
{
|
{
|
||||||
"Foldable",
|
"Foldable",
|
||||||
(upd1, upd2) =>
|
(upd1, upd2) => upd1.Foldable?.Folded.GetValueOrDefault(false) == upd2.Foldable?.Folded.GetValueOrDefault(false)
|
||||||
upd1.Foldable?.Folded.GetValueOrDefault(false)
|
|
||||||
== upd2.Foldable?.Folded.GetValueOrDefault(false)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"FoodDrink",
|
|
||||||
(upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent
|
|
||||||
},
|
},
|
||||||
|
{ "FoodDrink", (upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent },
|
||||||
{ "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource },
|
{ "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource },
|
||||||
{
|
{ "RecodableComponent", (upd1, upd2) => upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded },
|
||||||
"RecodableComponent",
|
{ "RepairKit", (upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource },
|
||||||
(upd1, upd2) =>
|
{ "Resource", (upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed },
|
||||||
upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"RepairKit",
|
|
||||||
(upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Resource",
|
|
||||||
(upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Choose above keys or passed in keys to compare items with
|
// Choose above keys or passed in keys to compare items with
|
||||||
var valuesToCompare =
|
var valuesToCompare = compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet();
|
||||||
compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet();
|
|
||||||
foreach (var propertyName in valuesToCompare)
|
foreach (var propertyName in valuesToCompare)
|
||||||
{
|
{
|
||||||
if (!comparers.TryGetValue(propertyName, out var comparer))
|
if (!comparers.TryGetValue(propertyName, out var comparer))
|
||||||
@@ -117,11 +88,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="desiredContainerSlotId">Name of slot to check item is in e.g. SecuredContainer/Backpack</param>
|
/// <param name="desiredContainerSlotId">Name of slot to check item is in e.g. SecuredContainer/Backpack</param>
|
||||||
/// <param name="items">Inventory with child parent items to check</param>
|
/// <param name="items">Inventory with child parent items to check</param>
|
||||||
/// <returns>True when item is in container</returns>
|
/// <returns>True when item is in container</returns>
|
||||||
public static bool ItemIsInsideContainer(
|
public static bool ItemIsInsideContainer(this Item itemToCheck, string desiredContainerSlotId, IEnumerable<Item> items)
|
||||||
this Item itemToCheck,
|
|
||||||
string desiredContainerSlotId,
|
|
||||||
IEnumerable<Item> items
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get items parent
|
// Get items parent
|
||||||
var parent = items.FirstOrDefault(item => item.Id.Equals(itemToCheck.ParentId));
|
var parent = items.FirstOrDefault(item => item.Id.Equals(itemToCheck.ParentId));
|
||||||
@@ -199,10 +166,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="items">List of items (item + possible children)</param>
|
/// <param name="items">List of items (item + possible children)</param>
|
||||||
/// <param name="baseItemId">Parent item's id</param>
|
/// <param name="baseItemId">Parent item's id</param>
|
||||||
/// <returns>list of child item ids</returns>
|
/// <returns>list of child item ids</returns>
|
||||||
public static List<MongoId> GetItemWithChildrenTpls(
|
public static List<MongoId> GetItemWithChildrenTpls(this IEnumerable<Item> items, MongoId baseItemId)
|
||||||
this IEnumerable<Item> items,
|
|
||||||
MongoId baseItemId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
List<MongoId> list = [];
|
List<MongoId> list = [];
|
||||||
|
|
||||||
@@ -226,8 +190,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <returns>true if it has buy restrictions</returns>
|
/// <returns>true if it has buy restrictions</returns>
|
||||||
public static bool HasBuyRestrictions(this Item itemToCheck)
|
public static bool HasBuyRestrictions(this Item itemToCheck)
|
||||||
{
|
{
|
||||||
return itemToCheck.Upd?.BuyRestrictionCurrent is not null
|
return itemToCheck.Upd?.BuyRestrictionCurrent is not null && itemToCheck.Upd?.BuyRestrictionMax is not null;
|
||||||
&& itemToCheck.Upd?.BuyRestrictionMax is not null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -273,11 +236,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="baseItemId">Parent item's id</param>
|
/// <param name="baseItemId">Parent item's id</param>
|
||||||
/// <param name="excludeStoredItems">OPTIONAL - Include only mod items, exclude items stored inside root item</param>
|
/// <param name="excludeStoredItems">OPTIONAL - Include only mod items, exclude items stored inside root item</param>
|
||||||
/// <returns>list of Item objects</returns>
|
/// <returns>list of Item objects</returns>
|
||||||
public static List<Item> GetItemWithChildren(
|
public static List<Item> GetItemWithChildren(this IEnumerable<Item> items, MongoId baseItemId, bool excludeStoredItems = false)
|
||||||
this IEnumerable<Item> items,
|
|
||||||
MongoId baseItemId,
|
|
||||||
bool excludeStoredItems = false
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Use dictionary to make key lookup faster, convert to list before being returned
|
// Use dictionary to make key lookup faster, convert to list before being returned
|
||||||
var itemList = items.ToList();
|
var itemList = items.ToList();
|
||||||
@@ -416,10 +375,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="itemWithChildren">Item to update root items _id property</param>
|
/// <param name="itemWithChildren">Item to update root items _id property</param>
|
||||||
/// <param name="newId">Optional: new id to use</param>
|
/// <param name="newId">Optional: new id to use</param>
|
||||||
/// <returns>New root id</returns>
|
/// <returns>New root id</returns>
|
||||||
public static MongoId RemapRootItemId(
|
public static MongoId RemapRootItemId(this IEnumerable<Item> itemWithChildren, MongoId? newId = null)
|
||||||
this IEnumerable<Item> itemWithChildren,
|
|
||||||
MongoId? newId = null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
newId ??= new MongoId();
|
newId ??= new MongoId();
|
||||||
|
|
||||||
@@ -458,11 +414,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
.GroupBy(item => new MongoId(item.ParentId))
|
.GroupBy(item => new MongoId(item.ParentId))
|
||||||
.ToDictionary(kvp => kvp.Key, group => group.ToHashSet());
|
.ToDictionary(kvp => kvp.Key, group => group.ToHashSet());
|
||||||
|
|
||||||
return new InventoryItemHash
|
return new InventoryItemHash { ByItemId = inventoryItems.ToDictionary(item => item.Id), ByParentId = byParentId };
|
||||||
{
|
|
||||||
ByItemId = inventoryItems.ToDictionary(item => item.Id),
|
|
||||||
ByParentId = byParentId,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,9 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LootContainerSettingsExtensions
|
public static class LootContainerSettingsExtensions
|
||||||
{
|
{
|
||||||
public static double GetRoubleValue(
|
public static double GetRoubleValue(this LootContainerSettings settings, int botLevel, string? locationId)
|
||||||
this LootContainerSettings settings,
|
|
||||||
int botLevel,
|
|
||||||
string? locationId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var roubleTotalByLevel = GetContainerRoubleTotalByLevel(
|
var roubleTotalByLevel = GetContainerRoubleTotalByLevel(botLevel, settings.TotalRubByLevel);
|
||||||
botLevel,
|
|
||||||
settings.TotalRubByLevel
|
|
||||||
);
|
|
||||||
|
|
||||||
if (locationId is null)
|
if (locationId is null)
|
||||||
{
|
{
|
||||||
@@ -42,10 +35,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="botLevel">level of the bot</param>
|
/// <param name="botLevel">level of the bot</param>
|
||||||
/// <param name="containerLootValuesPool">Pocket/vest/backpack</param>
|
/// <param name="containerLootValuesPool">Pocket/vest/backpack</param>
|
||||||
/// <returns>rouble amount</returns>
|
/// <returns>rouble amount</returns>
|
||||||
private static double GetContainerRoubleTotalByLevel(
|
private static double GetContainerRoubleTotalByLevel(int botLevel, IEnumerable<MinMaxLootValue> containerLootValuesPool)
|
||||||
int botLevel,
|
|
||||||
IEnumerable<MinMaxLootValue> containerLootValuesPool
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var matchingValue = containerLootValuesPool.FirstOrDefault(minMaxValue =>
|
var matchingValue = containerLootValuesPool.FirstOrDefault(minMaxValue =>
|
||||||
botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
for (var i = 0; i < 24; i++)
|
for (var i = 0; i < 24; i++)
|
||||||
{
|
{
|
||||||
var c = span[i];
|
var c = span[i];
|
||||||
var isHex =
|
var isHex = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
(c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
|
||||||
|
|
||||||
if (!isHex)
|
if (!isHex)
|
||||||
{
|
{
|
||||||
@@ -58,8 +57,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
for (var i = 0; i < 24; i++)
|
for (var i = 0; i < 24; i++)
|
||||||
{
|
{
|
||||||
var c = span[i];
|
var c = span[i];
|
||||||
var isHex =
|
var isHex = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
(c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
|
||||||
|
|
||||||
if (!isHex)
|
if (!isHex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,9 +14,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <returns>List of item objects</returns>
|
/// <returns>List of item objects</returns>
|
||||||
public static IEnumerable<Item> GetQuestItemsInProfile(this PmcData profile)
|
public static IEnumerable<Item> GetQuestItemsInProfile(this PmcData profile)
|
||||||
{
|
{
|
||||||
return profile
|
return profile?.Inventory?.Items.Where(i => i.ParentId == profile.Inventory.QuestRaidItems).ToList();
|
||||||
?.Inventory?.Items.Where(i => i.ParentId == profile.Inventory.QuestRaidItems)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,15 +24,9 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
public static void UnlockHideoutWallInProfile(this PmcData profile)
|
public static void UnlockHideoutWallInProfile(this PmcData profile)
|
||||||
{
|
{
|
||||||
var profileHideoutAreas = profile.Hideout.Areas;
|
var profileHideoutAreas = profile.Hideout.Areas;
|
||||||
var waterCollector = profileHideoutAreas.FirstOrDefault(x =>
|
var waterCollector = profileHideoutAreas.FirstOrDefault(x => x.Type == HideoutAreas.WaterCollector);
|
||||||
x.Type == HideoutAreas.WaterCollector
|
var medStation = profileHideoutAreas.FirstOrDefault(x => x.Type == HideoutAreas.MedStation);
|
||||||
);
|
var wall = profileHideoutAreas.FirstOrDefault(x => x.Type == HideoutAreas.EmergencyWall);
|
||||||
var medStation = profileHideoutAreas.FirstOrDefault(x =>
|
|
||||||
x.Type == HideoutAreas.MedStation
|
|
||||||
);
|
|
||||||
var wall = profileHideoutAreas.FirstOrDefault(x =>
|
|
||||||
x.Type == HideoutAreas.EmergencyWall
|
|
||||||
);
|
|
||||||
|
|
||||||
// No collector or med station, skip
|
// No collector or med station, skip
|
||||||
if (waterCollector is null && medStation is null)
|
if (waterCollector is null && medStation is null)
|
||||||
@@ -151,10 +143,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="pmcProfile">Player profile</param>
|
/// <param name="pmcProfile">Player profile</param>
|
||||||
/// <param name="desiredBonus">Bonus to sum up</param>
|
/// <param name="desiredBonus">Bonus to sum up</param>
|
||||||
/// <returns>Summed bonus value or 0 if no bonus found</returns>
|
/// <returns>Summed bonus value or 0 if no bonus found</returns>
|
||||||
public static double GetBonusValueFromProfile(
|
public static double GetBonusValueFromProfile(this PmcData pmcProfile, BonusType desiredBonus)
|
||||||
this PmcData pmcProfile,
|
|
||||||
BonusType desiredBonus
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var bonuses = pmcProfile?.Bonuses?.Where(b => b.Type == desiredBonus);
|
var bonuses = pmcProfile?.Bonuses?.Where(b => b.Type == desiredBonus);
|
||||||
if (!bonuses.Any())
|
if (!bonuses.Any())
|
||||||
@@ -168,9 +157,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
|
|
||||||
public static bool PlayerIsFleaBanned(this PmcData pmcProfile, long currentTimestamp)
|
public static bool PlayerIsFleaBanned(this PmcData pmcProfile, long currentTimestamp)
|
||||||
{
|
{
|
||||||
return pmcProfile?.Info?.Bans?.Any(b =>
|
return pmcProfile?.Info?.Bans?.Any(b => b.BanType == BanType.RagFair && currentTimestamp < b.DateTime) ?? false;
|
||||||
b.BanType == BanType.RagFair && currentTimestamp < b.DateTime
|
|
||||||
) ?? false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -221,9 +208,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise get the parent item
|
// Otherwise get the parent item
|
||||||
currentItem = pmcData.Inventory.Items.FirstOrDefault(item =>
|
currentItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == currentItem.ParentId);
|
||||||
item.Id == currentItem.ParentId
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -251,12 +236,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
{
|
{
|
||||||
foreach (var (partKey, bodyPart) in profile.Health.BodyParts)
|
foreach (var (partKey, bodyPart) in profile.Health.BodyParts)
|
||||||
{
|
{
|
||||||
bodyPart.Health.Maximum = profileTemplate
|
bodyPart.Health.Maximum = profileTemplate.Character.Health.BodyParts[partKey].Health.Maximum;
|
||||||
.Character
|
|
||||||
.Health
|
|
||||||
.BodyParts[partKey]
|
|
||||||
.Health
|
|
||||||
.Maximum;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
{
|
{
|
||||||
public static string GetModPath(this SptMod sptMod)
|
public static string GetModPath(this SptMod sptMod)
|
||||||
{
|
{
|
||||||
var relativeModPath = Path.GetRelativePath(
|
var relativeModPath = Path.GetRelativePath(Directory.GetCurrentDirectory(), sptMod.Directory).Replace('\\', '/');
|
||||||
Directory.GetCurrentDirectory(),
|
|
||||||
sptMod.Directory
|
|
||||||
)
|
|
||||||
.Replace('\\', '/');
|
|
||||||
|
|
||||||
return relativeModPath;
|
return relativeModPath;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
{
|
{
|
||||||
public static class TemplateItemExtensions
|
public static class TemplateItemExtensions
|
||||||
{
|
{
|
||||||
public static IEnumerable<TemplateItem> OfClass(
|
public static IEnumerable<TemplateItem> OfClass(this Dictionary<MongoId, TemplateItem> templates, params MongoId[] baseClasses)
|
||||||
this Dictionary<MongoId, TemplateItem> templates,
|
|
||||||
params MongoId[] baseClasses
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return templates.Where(x => baseClasses.Contains(x.Value.Parent)).Select(x => x.Value);
|
return templates.Where(x => baseClasses.Contains(x.Value.Parent)).Select(x => x.Value);
|
||||||
}
|
}
|
||||||
@@ -19,9 +16,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
params MongoId[] baseClasses
|
params MongoId[] baseClasses
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return templates
|
return templates.Where(x => baseClasses.Contains(x.Value.Parent) && pred(x.Value)).Select(x => x.Value);
|
||||||
.Where(x => baseClasses.Contains(x.Value.Parent) && pred(x.Value))
|
|
||||||
.Select(x => x.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -13,11 +13,7 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// <param name="itemId">Id of item to remove from assort</param>
|
/// <param name="itemId">Id of item to remove from assort</param>
|
||||||
/// <param name="isFlea">Is the assort being modified the flea market assort</param>
|
/// <param name="isFlea">Is the assort being modified the flea market assort</param>
|
||||||
/// <returns>Modified assort</returns>
|
/// <returns>Modified assort</returns>
|
||||||
public static TraderAssort RemoveItemFromAssort(
|
public static TraderAssort RemoveItemFromAssort(this TraderAssort assort, MongoId itemId, bool isFlea = false)
|
||||||
this TraderAssort assort,
|
|
||||||
MongoId itemId,
|
|
||||||
bool isFlea = false
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Flea assort needs special handling, item must remain in assort but be flagged as locked
|
// Flea assort needs special handling, item must remain in assort but be flagged as locked
|
||||||
if (isFlea && assort.BarterScheme.TryGetValue(itemId, out var listToUse))
|
if (isFlea && assort.BarterScheme.TryGetValue(itemId, out var listToUse))
|
||||||
@@ -45,15 +41,10 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assortToFilter">Trader assort to modify</param>
|
/// <param name="assortToFilter">Trader assort to modify</param>
|
||||||
/// <param name="itemsTplsToRemove">Item TPLs the assort should not have</param>
|
/// <param name="itemsTplsToRemove">Item TPLs the assort should not have</param>
|
||||||
public static void RemoveItemsFromAssort(
|
public static void RemoveItemsFromAssort(this TraderAssort assortToFilter, HashSet<MongoId> itemsTplsToRemove)
|
||||||
this TraderAssort assortToFilter,
|
|
||||||
HashSet<MongoId> itemsTplsToRemove
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
assortToFilter.Items = assortToFilter
|
assortToFilter.Items = assortToFilter
|
||||||
.Items.Where(item =>
|
.Items.Where(item => item.ParentId == "hideout" && itemsTplsToRemove.Contains(item.Template))
|
||||||
item.ParentId == "hideout" && itemsTplsToRemove.Contains(item.Template)
|
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
{
|
{
|
||||||
public static class UtilityExtensions
|
public static class UtilityExtensions
|
||||||
{
|
{
|
||||||
public static IEnumerable<T> IntersectWith<T>(
|
public static IEnumerable<T> IntersectWith<T>(this IEnumerable<T> first, IEnumerable<T> second)
|
||||||
this IEnumerable<T> first,
|
|
||||||
IEnumerable<T> second
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
//a.Intersect(x => b.Contains(x)).ToList();
|
//a.Intersect(x => b.Contains(x)).ToList();
|
||||||
// gives error Delegate type could not be inferred
|
// gives error Delegate type could not be inferred
|
||||||
|
|||||||
@@ -39,11 +39,7 @@ public class BotEquipmentModGenerator(
|
|||||||
ICloner cloner
|
ICloner cloner
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected static readonly FrozenSet<string> _modSightIds =
|
protected static readonly FrozenSet<string> _modSightIds = ["mod_sight_front", "mod_sight_rear"];
|
||||||
[
|
|
||||||
"mod_sight_front",
|
|
||||||
"mod_sight_rear",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Slots that hold scopes
|
// Slots that hold scopes
|
||||||
protected static readonly FrozenSet<string> _scopeIds =
|
protected static readonly FrozenSet<string> _scopeIds =
|
||||||
@@ -58,21 +54,10 @@ public class BotEquipmentModGenerator(
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Slots that hold muzzles
|
// Slots that hold muzzles
|
||||||
protected static readonly FrozenSet<string> _muzzleIds =
|
protected static readonly FrozenSet<string> _muzzleIds = ["mod_muzzle", "mod_muzzle_000", "mod_muzzle_001"];
|
||||||
[
|
|
||||||
"mod_muzzle",
|
|
||||||
"mod_muzzle_000",
|
|
||||||
"mod_muzzle_001",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Slots a weapon can store its stock in
|
// Slots a weapon can store its stock in
|
||||||
protected static readonly FrozenSet<string> _stockSlots =
|
protected static readonly FrozenSet<string> _stockSlots = ["mod_stock", "mod_stock_000", "mod_stock_001", "mod_stock_akms"];
|
||||||
[
|
|
||||||
"mod_stock",
|
|
||||||
"mod_stock_000",
|
|
||||||
"mod_stock_001",
|
|
||||||
"mod_stock_akms",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Slots that hold cartridges
|
// Slots that hold cartridges
|
||||||
protected static readonly FrozenSet<string> _cartridgeHolderSlots =
|
protected static readonly FrozenSet<string> _cartridgeHolderSlots =
|
||||||
@@ -121,9 +106,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Get mod pool for the desired item
|
// Get mod pool for the desired item
|
||||||
if (!settings.ModPool.TryGetValue(parentTemplate.Id, out var compatibleModsPool))
|
if (!settings.ModPool.TryGetValue(parentTemplate.Id, out var compatibleModsPool))
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"bot: {settings.BotData.Role} lacks a mod slot pool for item: {parentTemplate.Id} {parentTemplate.Name}");
|
||||||
$"bot: {settings.BotData.Role} lacks a mod slot pool for item: {parentTemplate.Id} {parentTemplate.Name}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over mod pool and choose mods to add to item
|
// Iterate over mod pool and choose mods to add to item
|
||||||
@@ -172,11 +155,7 @@ public class BotEquipmentModGenerator(
|
|||||||
var modPoolToChooseFrom = modPool;
|
var modPoolToChooseFrom = modPool;
|
||||||
|
|
||||||
// Filter the pool of items in blacklist
|
// Filter the pool of items in blacklist
|
||||||
var filteredModPool = FilterModsByBlacklist(
|
var filteredModPool = FilterModsByBlacklist(modPoolToChooseFrom, specificBlacklist, modSlotName);
|
||||||
modPoolToChooseFrom,
|
|
||||||
specificBlacklist,
|
|
||||||
modSlotName
|
|
||||||
);
|
|
||||||
if (filteredModPool.Count > 0)
|
if (filteredModPool.Count > 0)
|
||||||
// use filtered pool as it has items in it
|
// use filtered pool as it has items in it
|
||||||
{
|
{
|
||||||
@@ -239,12 +218,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Compatible item not found but slot REQUIRES item, get random item from db
|
// Compatible item not found but slot REQUIRES item, get random item from db
|
||||||
if (!found && itemSlotTemplate.Required.GetValueOrDefault(false))
|
if (!found && itemSlotTemplate.Required.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
modTpl = GetRandomModTplFromItemDb(
|
modTpl = GetRandomModTplFromItemDb(modTpl.Value, itemSlotTemplate, modSlotName, equipment);
|
||||||
modTpl.Value,
|
|
||||||
itemSlotTemplate,
|
|
||||||
modSlotName,
|
|
||||||
equipment
|
|
||||||
);
|
|
||||||
found = modTpl is not null;
|
found = modTpl is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,44 +230,20 @@ public class BotEquipmentModGenerator(
|
|||||||
|
|
||||||
// Get chosen mods db template and check it fits into slot
|
// Get chosen mods db template and check it fits into slot
|
||||||
var modTemplate = itemHelper.GetItem(modTpl.Value);
|
var modTemplate = itemHelper.GetItem(modTpl.Value);
|
||||||
if (
|
if (!IsModValidForSlot(modTemplate, itemSlotTemplate, modSlotName, parentTemplate, settings.BotData.Role))
|
||||||
!IsModValidForSlot(
|
|
||||||
modTemplate,
|
|
||||||
itemSlotTemplate,
|
|
||||||
modSlotName,
|
|
||||||
parentTemplate,
|
|
||||||
settings.BotData.Role
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate new id to ensure all items are unique on bot
|
// Generate new id to ensure all items are unique on bot
|
||||||
var modId = new MongoId();
|
var modId = new MongoId();
|
||||||
equipment.Add(
|
equipment.Add(CreateModItem(modId, modTpl.Value, parentId, modSlotName, modTemplate.Value, settings.BotData.Role));
|
||||||
CreateModItem(
|
|
||||||
modId,
|
|
||||||
modTpl.Value,
|
|
||||||
parentId,
|
|
||||||
modSlotName,
|
|
||||||
modTemplate.Value,
|
|
||||||
settings.BotData.Role
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Does item being added exist in mod pool - has its own mod pool
|
// Does item being added exist in mod pool - has its own mod pool
|
||||||
if (settings.ModPool.ContainsKey(modTpl.Value))
|
if (settings.ModPool.ContainsKey(modTpl.Value))
|
||||||
// Call self again with mod being added as item to add child mods to
|
// Call self again with mod being added as item to add child mods to
|
||||||
{
|
{
|
||||||
GenerateModsForEquipment(
|
GenerateModsForEquipment(equipment, modId, modTemplate.Value, settings, specificBlacklist, forceSpawn);
|
||||||
equipment,
|
|
||||||
modId,
|
|
||||||
modTemplate.Value,
|
|
||||||
settings,
|
|
||||||
specificBlacklist,
|
|
||||||
forceSpawn
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,11 +265,7 @@ public class BotEquipmentModGenerator(
|
|||||||
TemplateItem armorItem
|
TemplateItem armorItem
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var result = new FilterPlateModsForSlotByLevelResult
|
var result = new FilterPlateModsForSlotByLevelResult { Result = Result.UNKNOWN_FAILURE, PlateModTemplates = null };
|
||||||
{
|
|
||||||
Result = Result.UNKNOWN_FAILURE,
|
|
||||||
PlateModTemplates = null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Not pmc or not a plate slot, return original mod pool array
|
// Not pmc or not a plate slot, return original mod pool array
|
||||||
if (!itemHelper.IsRemovablePlateSlot(modSlot))
|
if (!itemHelper.IsRemovablePlateSlot(modSlot))
|
||||||
@@ -331,10 +277,8 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the front/back/side weights based on bots level
|
// Get the front/back/side weights based on bots level
|
||||||
var plateSlotWeights = settings.BotEquipmentConfig?.ArmorPlateWeighting.FirstOrDefault(
|
var plateSlotWeights = settings.BotEquipmentConfig?.ArmorPlateWeighting.FirstOrDefault(armorWeight =>
|
||||||
armorWeight =>
|
settings.BotData.Level >= armorWeight.LevelRange.Min && settings.BotData.Level <= armorWeight.LevelRange.Max
|
||||||
settings.BotData.Level >= armorWeight.LevelRange.Min
|
|
||||||
&& settings.BotData.Level <= armorWeight.LevelRange.Max
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (plateSlotWeights is null)
|
if (plateSlotWeights is null)
|
||||||
@@ -360,14 +304,11 @@ public class BotEquipmentModGenerator(
|
|||||||
var chosenArmorPlateLevelString = weightedRandomHelper.GetWeightedValue(plateWeights);
|
var chosenArmorPlateLevelString = weightedRandomHelper.GetWeightedValue(plateWeights);
|
||||||
|
|
||||||
// Convert the array of ids into database items
|
// Convert the array of ids into database items
|
||||||
var platesFromDb = existingPlateTplPool.Select(plateTpl =>
|
var platesFromDb = existingPlateTplPool.Select(plateTpl => itemHelper.GetItem(plateTpl).Value);
|
||||||
itemHelper.GetItem(plateTpl).Value
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter plates to the chosen level based on its armorClass property
|
// Filter plates to the chosen level based on its armorClass property
|
||||||
var platesOfDesiredLevel = platesFromDb.Where(item =>
|
var platesOfDesiredLevel = platesFromDb.Where(item =>
|
||||||
item.Properties.ArmorClass.Value
|
item.Properties.ArmorClass.Value == double.Parse(chosenArmorPlateLevelString, CultureInfo.InvariantCulture)
|
||||||
== double.Parse(chosenArmorPlateLevelString, CultureInfo.InvariantCulture)
|
|
||||||
);
|
);
|
||||||
if (platesOfDesiredLevel.Any())
|
if (platesOfDesiredLevel.Any())
|
||||||
{
|
{
|
||||||
@@ -399,9 +340,7 @@ public class BotEquipmentModGenerator(
|
|||||||
|
|
||||||
findCompatiblePlateAttempts++;
|
findCompatiblePlateAttempts++;
|
||||||
|
|
||||||
platesOfDesiredLevel = platesFromDb.Where(item =>
|
platesOfDesiredLevel = platesFromDb.Where(item => item.Properties.ArmorClass == chosenArmorPlateLevelDouble);
|
||||||
item.Properties.ArmorClass == chosenArmorPlateLevelDouble
|
|
||||||
);
|
|
||||||
// Valid plates found, exit
|
// Valid plates found, exit
|
||||||
if (platesOfDesiredLevel.Any())
|
if (platesOfDesiredLevel.Any())
|
||||||
{
|
{
|
||||||
@@ -496,9 +435,7 @@ public class BotEquipmentModGenerator(
|
|||||||
{
|
{
|
||||||
var defaultPreset = presetHelper.GetDefaultPreset(armorItemTpl);
|
var defaultPreset = presetHelper.GetDefaultPreset(armorItemTpl);
|
||||||
|
|
||||||
return defaultPreset?.Items?.FirstOrDefault(item =>
|
return defaultPreset?.Items?.FirstOrDefault(item => string.Equals(item.SlotId, modSlot, StringComparison.OrdinalIgnoreCase));
|
||||||
string.Equals(item.SlotId, modSlot, StringComparison.OrdinalIgnoreCase)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -536,19 +473,11 @@ public class BotEquipmentModGenerator(
|
|||||||
request.BotData.EquipmentRole,
|
request.BotData.EquipmentRole,
|
||||||
pmcProfile?.Info?.Level ?? 0
|
pmcProfile?.Info?.Level ?? 0
|
||||||
);
|
);
|
||||||
var botWeaponSightWhitelist = botEquipmentFilterService.GetBotWeaponSightWhitelist(
|
var botWeaponSightWhitelist = botEquipmentFilterService.GetBotWeaponSightWhitelist(request.BotData.EquipmentRole);
|
||||||
request.BotData.EquipmentRole
|
var randomisationSettings = botHelper.GetBotRandomizationDetails(request.BotData.Level ?? 0, botEquipConfig);
|
||||||
);
|
|
||||||
var randomisationSettings = botHelper.GetBotRandomizationDetails(
|
|
||||||
request.BotData.Level ?? 0,
|
|
||||||
botEquipConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
// Iterate over mod pool and choose mods to attach
|
// Iterate over mod pool and choose mods to attach
|
||||||
var sortedModKeys = SortModKeys(
|
var sortedModKeys = SortModKeys(compatibleModsPool.Keys.ToHashSet(), request.ParentTemplate.Id);
|
||||||
compatibleModsPool.Keys.ToHashSet(),
|
|
||||||
request.ParentTemplate.Id
|
|
||||||
);
|
|
||||||
foreach (var modSlot in sortedModKeys)
|
foreach (var modSlot in sortedModKeys)
|
||||||
{
|
{
|
||||||
// Check weapon has slot for mod to fit in
|
// Check weapon has slot for mod to fit in
|
||||||
@@ -572,28 +501,19 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the parent is a UBGL, the patron_in_weapon will be generated later - so skip it for now
|
// If the parent is a UBGL, the patron_in_weapon will be generated later - so skip it for now
|
||||||
if (
|
if (modSlot == "patron_in_weapon" && itemHelper.IsOfBaseclass(request.ParentTemplate.Id, BaseClasses.LAUNCHER))
|
||||||
modSlot == "patron_in_weapon"
|
|
||||||
&& itemHelper.IsOfBaseclass(request.ParentTemplate.Id, BaseClasses.LAUNCHER)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check spawn chance of mod
|
// Check spawn chance of mod
|
||||||
var modSpawnResult = ShouldModBeSpawned(
|
var modSpawnResult = ShouldModBeSpawned(modsParentSlot, modSlot, request.ModSpawnChances, botEquipConfig);
|
||||||
modsParentSlot,
|
|
||||||
modSlot,
|
|
||||||
request.ModSpawnChances,
|
|
||||||
botEquipConfig
|
|
||||||
);
|
|
||||||
if (modSpawnResult == ModSpawn.SKIP)
|
if (modSpawnResult == ModSpawn.SKIP)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isRandomisableSlot =
|
var isRandomisableSlot = randomisationSettings?.RandomisedWeaponModSlots?.Contains(modSlot) ?? false;
|
||||||
randomisationSettings?.RandomisedWeaponModSlots?.Contains(modSlot) ?? false;
|
|
||||||
ModToSpawnRequest modToSpawnRequest = new()
|
ModToSpawnRequest modToSpawnRequest = new()
|
||||||
{
|
{
|
||||||
ModSlot = modSlot,
|
ModSlot = modSlot,
|
||||||
@@ -618,15 +538,7 @@ public class BotEquipmentModGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (!IsModValidForSlot(modToAdd, modsParentSlot, modSlot, request.ParentTemplate, request.BotData.Role))
|
||||||
!IsModValidForSlot(
|
|
||||||
modToAdd,
|
|
||||||
modsParentSlot,
|
|
||||||
modSlot,
|
|
||||||
request.ParentTemplate,
|
|
||||||
request.BotData.Role
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -650,26 +562,14 @@ public class BotEquipmentModGenerator(
|
|||||||
if (ModSlotCanHoldScope(modSlot, modToAddTemplate.Parent))
|
if (ModSlotCanHoldScope(modSlot, modToAddTemplate.Parent))
|
||||||
{
|
{
|
||||||
// mod_mount was picked to be added to weapon, force scope chance to ensure its filled
|
// mod_mount was picked to be added to weapon, force scope chance to ensure its filled
|
||||||
List<string> scopeSlots =
|
List<string> scopeSlots = ["mod_scope", "mod_scope_000", "mod_scope_001", "mod_scope_002", "mod_scope_003"];
|
||||||
[
|
|
||||||
"mod_scope",
|
|
||||||
"mod_scope_000",
|
|
||||||
"mod_scope_001",
|
|
||||||
"mod_scope_002",
|
|
||||||
"mod_scope_003",
|
|
||||||
];
|
|
||||||
AdjustSlotSpawnChances(request.ModSpawnChances, scopeSlots, 100);
|
AdjustSlotSpawnChances(request.ModSpawnChances, scopeSlots, 100);
|
||||||
|
|
||||||
// Hydrate pool of mods that fit into mount as its a randomisable slot
|
// Hydrate pool of mods that fit into mount as its a randomisable slot
|
||||||
if (isRandomisableSlot)
|
if (isRandomisableSlot)
|
||||||
// Add scope mods to modPool dictionary to ensure the mount has a scope in the pool to pick
|
// Add scope mods to modPool dictionary to ensure the mount has a scope in the pool to pick
|
||||||
{
|
{
|
||||||
AddCompatibleModsForProvidedMod(
|
AddCompatibleModsForProvidedMod("mod_scope", modToAddTemplate, request.ModPool, botEquipBlacklist);
|
||||||
"mod_scope",
|
|
||||||
modToAddTemplate,
|
|
||||||
request.ModPool,
|
|
||||||
botEquipBlacklist
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,13 +606,7 @@ public class BotEquipmentModGenerator(
|
|||||||
if (ShouldForceSubStockSlots(modSlot, botEquipConfig, modToAddTemplate))
|
if (ShouldForceSubStockSlots(modSlot, botEquipConfig, modToAddTemplate))
|
||||||
{
|
{
|
||||||
// Stock mod can take additional stocks, could be a locking device, force 100% chance
|
// Stock mod can take additional stocks, could be a locking device, force 100% chance
|
||||||
List<string> subStockSlots =
|
List<string> subStockSlots = ["mod_stock", "mod_stock_000", "mod_stock_001", "mod_stock_akms"];
|
||||||
[
|
|
||||||
"mod_stock",
|
|
||||||
"mod_stock_000",
|
|
||||||
"mod_stock_001",
|
|
||||||
"mod_stock_akms",
|
|
||||||
];
|
|
||||||
AdjustSlotSpawnChances(request.ModSpawnChances, subStockSlots, 100);
|
AdjustSlotSpawnChances(request.ModSpawnChances, subStockSlots, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,24 +622,14 @@ public class BotEquipmentModGenerator(
|
|||||||
request.WeaponStats.HasRearIronSight = true;
|
request.WeaponStats.HasRearIronSight = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (
|
else if (!(request.WeaponStats.HasOptic ?? false) && itemHelper.IsOfBaseclass(modToAddTemplate.Id, BaseClasses.SIGHTS))
|
||||||
!(request.WeaponStats.HasOptic ?? false)
|
|
||||||
&& itemHelper.IsOfBaseclass(modToAddTemplate.Id, BaseClasses.SIGHTS)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
request.WeaponStats.HasOptic = true;
|
request.WeaponStats.HasOptic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var modId = new MongoId();
|
var modId = new MongoId();
|
||||||
request.Weapon.Add(
|
request.Weapon.Add(
|
||||||
CreateModItem(
|
CreateModItem(modId, modToAddTemplate.Id, request.WeaponId, modSlot, modToAddTemplate, request.BotData.Role)
|
||||||
modId,
|
|
||||||
modToAddTemplate.Id,
|
|
||||||
request.WeaponId,
|
|
||||||
modSlot,
|
|
||||||
modToAddTemplate,
|
|
||||||
request.BotData.Role
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update conflicting item list now item has been chosen
|
// Update conflicting item list now item has been chosen
|
||||||
@@ -777,9 +661,7 @@ public class BotEquipmentModGenerator(
|
|||||||
&& modToAddTemplate.Properties.Slots.Any()
|
&& modToAddTemplate.Properties.Slots.Any()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var modFromService = botEquipmentModPoolService.GetModsForWeaponSlot(
|
var modFromService = botEquipmentModPoolService.GetModsForWeaponSlot(modToAddTemplate.Id);
|
||||||
modToAddTemplate.Id
|
|
||||||
);
|
|
||||||
if (modFromService?.Count > 0)
|
if (modFromService?.Count > 0)
|
||||||
{
|
{
|
||||||
request.ModPool[modToAddTemplate.Id] = modFromService.ToDictionary();
|
request.ModPool[modToAddTemplate.Id] = modFromService.ToDictionary();
|
||||||
@@ -791,9 +673,7 @@ public class BotEquipmentModGenerator(
|
|||||||
if (!containsModInPool && !isRandomisableSlot)
|
if (!containsModInPool && !isRandomisableSlot)
|
||||||
{
|
{
|
||||||
// Check for required mods the item we've added needs to be classified as 'valid'
|
// Check for required mods the item we've added needs to be classified as 'valid'
|
||||||
var modFromService = botEquipmentModPoolService.GetRequiredModsForWeaponSlot(
|
var modFromService = botEquipmentModPoolService.GetRequiredModsForWeaponSlot(modToAddTemplate.Id);
|
||||||
modToAddTemplate.Id
|
|
||||||
);
|
|
||||||
if (modFromService?.Count > 0)
|
if (modFromService?.Count > 0)
|
||||||
{
|
{
|
||||||
request.ModPool[modToAddTemplate.Id] = modFromService;
|
request.ModPool[modToAddTemplate.Id] = modFromService;
|
||||||
@@ -837,19 +717,12 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="botEquipConfig">Bots equipment config/chance values</param>
|
/// <param name="botEquipConfig">Bots equipment config/chance values</param>
|
||||||
/// <param name="modToAddTemplate">Mod being added to bots weapon</param>
|
/// <param name="modToAddTemplate">Mod being added to bots weapon</param>
|
||||||
/// <returns>True if it should</returns>
|
/// <returns>True if it should</returns>
|
||||||
public bool ShouldForceSubStockSlots(
|
public bool ShouldForceSubStockSlots(string modSlot, EquipmentFilters botEquipConfig, TemplateItem modToAddTemplate)
|
||||||
string modSlot,
|
|
||||||
EquipmentFilters botEquipConfig,
|
|
||||||
TemplateItem modToAddTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Can the stock hold child items
|
// Can the stock hold child items
|
||||||
var hasSubSlots =
|
var hasSubSlots = modToAddTemplate.Properties?.Slots is not null && modToAddTemplate.Properties.Slots.Any();
|
||||||
modToAddTemplate.Properties?.Slots is not null
|
|
||||||
&& modToAddTemplate.Properties.Slots.Any();
|
|
||||||
|
|
||||||
return (_stockSlots.Contains(modSlot) && hasSubSlots)
|
return (_stockSlots.Contains(modSlot) && hasSubSlots) || botEquipConfig.ForceStock.GetValueOrDefault(false);
|
||||||
|| botEquipConfig.ForceStock.GetValueOrDefault(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -887,11 +760,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modSpawnChances">Chance dictionary to update</param>
|
/// <param name="modSpawnChances">Chance dictionary to update</param>
|
||||||
/// <param name="modSlotsToAdjust"></param>
|
/// <param name="modSlotsToAdjust"></param>
|
||||||
/// <param name="newChancePercent"></param>
|
/// <param name="newChancePercent"></param>
|
||||||
public void AdjustSlotSpawnChances(
|
public void AdjustSlotSpawnChances(Dictionary<string, double>? modSpawnChances, List<string>? modSlotsToAdjust, double newChancePercent)
|
||||||
Dictionary<string, double>? modSpawnChances,
|
|
||||||
List<string>? modSlotsToAdjust,
|
|
||||||
double newChancePercent
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (modSpawnChances is null)
|
if (modSpawnChances is null)
|
||||||
{
|
{
|
||||||
@@ -930,10 +799,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="unsortedSlotKeys">Array of mod slot strings to sort</param>
|
/// <param name="unsortedSlotKeys">Array of mod slot strings to sort</param>
|
||||||
/// <param name="itemTplWithKeysToSort">The Tpl of the item with mod keys being sorted</param>
|
/// <param name="itemTplWithKeysToSort">The Tpl of the item with mod keys being sorted</param>
|
||||||
/// <returns>Sorted array</returns>
|
/// <returns>Sorted array</returns>
|
||||||
public HashSet<string> SortModKeys(
|
public HashSet<string> SortModKeys(HashSet<string> unsortedSlotKeys, MongoId itemTplWithKeysToSort)
|
||||||
HashSet<string> unsortedSlotKeys,
|
|
||||||
MongoId itemTplWithKeysToSort
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// No need to sort with only 1 item in array
|
// No need to sort with only 1 item in array
|
||||||
if (unsortedSlotKeys.Count <= 1)
|
if (unsortedSlotKeys.Count <= 1)
|
||||||
@@ -1078,15 +944,10 @@ public class BotEquipmentModGenerator(
|
|||||||
return ModSpawn.SPAWN;
|
return ModSpawn.SPAWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
var spawnMod = randomUtil.RollChance(
|
var spawnMod = randomUtil.RollChance(modSpawnChances.GetValueOrDefault(modSlotName.ToLowerInvariant()));
|
||||||
modSpawnChances.GetValueOrDefault(modSlotName.ToLowerInvariant())
|
|
||||||
);
|
|
||||||
if (
|
if (
|
||||||
!spawnMod
|
!spawnMod
|
||||||
&& (
|
&& (slotRequired.GetValueOrDefault(false) || (botEquipConfig.WeaponSlotIdsToMakeRequired?.Contains(modSlotName) ?? false))
|
||||||
slotRequired.GetValueOrDefault(false)
|
|
||||||
|| (botEquipConfig.WeaponSlotIdsToMakeRequired?.Contains(modSlotName) ?? false)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
// Edge case: Mod is required but spawn chance roll failed, choose default mod spawn for slot
|
// Edge case: Mod is required but spawn chance roll failed, choose default mod spawn for slot
|
||||||
{
|
{
|
||||||
@@ -1104,9 +965,7 @@ public class BotEquipmentModGenerator(
|
|||||||
public KeyValuePair<bool, TemplateItem>? ChooseModToPutIntoSlot(ModToSpawnRequest request)
|
public KeyValuePair<bool, TemplateItem>? ChooseModToPutIntoSlot(ModToSpawnRequest request)
|
||||||
{
|
{
|
||||||
// Slot mod will fill
|
// Slot mod will fill
|
||||||
var parentSlot = request.ParentTemplate.Properties.Slots?.FirstOrDefault(i =>
|
var parentSlot = request.ParentTemplate.Properties.Slots?.FirstOrDefault(i => i.Name == request.ModSlot);
|
||||||
i.Name == request.ModSlot
|
|
||||||
);
|
|
||||||
var weaponTemplate = itemHelper.GetItem(request.Weapon.First().Template).Value;
|
var weaponTemplate = itemHelper.GetItem(request.Weapon.First().Template).Value;
|
||||||
|
|
||||||
// It's ammo, use predefined ammo parameter
|
// It's ammo, use predefined ammo parameter
|
||||||
@@ -1136,11 +995,7 @@ public class BotEquipmentModGenerator(
|
|||||||
{
|
{
|
||||||
if (modPool.Count > 1)
|
if (modPool.Count > 1)
|
||||||
{
|
{
|
||||||
modPool = FilterSightsByWeaponType(
|
modPool = FilterSightsByWeaponType(request.Weapon.First(), modPool, request.BotWeaponSightWhitelist);
|
||||||
request.Weapon.First(),
|
|
||||||
modPool,
|
|
||||||
request.BotWeaponSightWhitelist
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1149,9 +1004,7 @@ public class BotEquipmentModGenerator(
|
|||||||
if ((request.WeaponStats?.HasOptic ?? false) && modPool.Count > 1)
|
if ((request.WeaponStats?.HasOptic ?? false) && modPool.Count > 1)
|
||||||
{
|
{
|
||||||
// Attempt to limit modpool to low profile gas blocks when weapon has an optic
|
// Attempt to limit modpool to low profile gas blocks when weapon has an optic
|
||||||
var onlyLowProfileGasBlocks = modPool.Where(tpl =>
|
var onlyLowProfileGasBlocks = modPool.Where(tpl => _botConfig.LowProfileGasBlockTpls.Contains(tpl));
|
||||||
_botConfig.LowProfileGasBlockTpls.Contains(tpl)
|
|
||||||
);
|
|
||||||
if (onlyLowProfileGasBlocks.Any())
|
if (onlyLowProfileGasBlocks.Any())
|
||||||
{
|
{
|
||||||
modPool = onlyLowProfileGasBlocks.ToHashSet();
|
modPool = onlyLowProfileGasBlocks.ToHashSet();
|
||||||
@@ -1160,9 +1013,7 @@ public class BotEquipmentModGenerator(
|
|||||||
else if ((request.WeaponStats?.HasRearIronSight ?? false) && modPool.Count > 1)
|
else if ((request.WeaponStats?.HasRearIronSight ?? false) && modPool.Count > 1)
|
||||||
{
|
{
|
||||||
// Attempt to limit modpool to high profile gas blocks when weapon has rear iron sight + no front iron sight
|
// Attempt to limit modpool to high profile gas blocks when weapon has rear iron sight + no front iron sight
|
||||||
var onlyHighProfileGasBlocks = modPool.Where(tpl =>
|
var onlyHighProfileGasBlocks = modPool.Where(tpl => !_botConfig.LowProfileGasBlockTpls.Contains(tpl));
|
||||||
!_botConfig.LowProfileGasBlockTpls.Contains(tpl)
|
|
||||||
);
|
|
||||||
if (onlyHighProfileGasBlocks.Any())
|
if (onlyHighProfileGasBlocks.Any())
|
||||||
{
|
{
|
||||||
modPool = onlyHighProfileGasBlocks.ToHashSet();
|
modPool = onlyHighProfileGasBlocks.ToHashSet();
|
||||||
@@ -1189,20 +1040,14 @@ public class BotEquipmentModGenerator(
|
|||||||
request.Weapon,
|
request.Weapon,
|
||||||
request.ModSlot
|
request.ModSlot
|
||||||
);
|
);
|
||||||
if (
|
if (chosenModResult.SlotBlocked.GetValueOrDefault(false) && !parentSlot.Required.GetValueOrDefault(false))
|
||||||
chosenModResult.SlotBlocked.GetValueOrDefault(false)
|
|
||||||
&& !parentSlot.Required.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
// Don't bother trying to fit mod, slot is completely blocked
|
// Don't bother trying to fit mod, slot is completely blocked
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log if mod chosen was incompatible
|
// Log if mod chosen was incompatible
|
||||||
if (
|
if (chosenModResult.Incompatible.GetValueOrDefault(false) && !parentSlot.Required.GetValueOrDefault(false))
|
||||||
chosenModResult.Incompatible.GetValueOrDefault(false)
|
|
||||||
&& !parentSlot.Required.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
@@ -1213,27 +1058,14 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get random mod to attach from items db for required slots if none found above
|
// Get random mod to attach from items db for required slots if none found above
|
||||||
if (
|
if (!(chosenModResult.Found ?? false) && parentSlot != null && (parentSlot.Required ?? false))
|
||||||
!(chosenModResult.Found ?? false)
|
|
||||||
&& parentSlot != null
|
|
||||||
&& (parentSlot.Required ?? false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
chosenModResult.ChosenTemplate = GetRandomModTplFromItemDb(
|
chosenModResult.ChosenTemplate = GetRandomModTplFromItemDb("", parentSlot, request.ModSlot, request.Weapon);
|
||||||
"",
|
|
||||||
parentSlot,
|
|
||||||
request.ModSlot,
|
|
||||||
request.Weapon
|
|
||||||
);
|
|
||||||
chosenModResult.Found = true;
|
chosenModResult.Found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compatible item not found + not required
|
// Compatible item not found + not required
|
||||||
if (
|
if (!chosenModResult.Found.GetValueOrDefault(false) && parentSlot is not null && !parentSlot.Required.GetValueOrDefault(false))
|
||||||
!chosenModResult.Found.GetValueOrDefault(false)
|
|
||||||
&& parentSlot is not null
|
|
||||||
&& !parentSlot.Required.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1259,29 +1091,20 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modSpawnRequest">Request data</param>
|
/// <param name="modSpawnRequest">Request data</param>
|
||||||
/// <param name="modPool">Pool of magazine tpls to filter</param>
|
/// <param name="modPool">Pool of magazine tpls to filter</param>
|
||||||
/// <returns>Filtered pool of magazine tpls</returns>
|
/// <returns>Filtered pool of magazine tpls</returns>
|
||||||
public IEnumerable<MongoId> GetFilteredMagazinePoolByCapacity(
|
public IEnumerable<MongoId> GetFilteredMagazinePoolByCapacity(ModToSpawnRequest modSpawnRequest, HashSet<MongoId> modPool)
|
||||||
ModToSpawnRequest modSpawnRequest,
|
|
||||||
HashSet<MongoId> modPool
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var weaponTpl = modSpawnRequest.Weapon.FirstOrDefault().Template;
|
var weaponTpl = modSpawnRequest.Weapon.FirstOrDefault().Template;
|
||||||
modSpawnRequest.RandomisationSettings.MinimumMagazineSize.TryGetValue(
|
modSpawnRequest.RandomisationSettings.MinimumMagazineSize.TryGetValue(weaponTpl, out var minMagSizeFromSettings);
|
||||||
weaponTpl,
|
|
||||||
out var minMagSizeFromSettings
|
|
||||||
);
|
|
||||||
var desiredMagazineTpls = modPool.Where(magTpl =>
|
var desiredMagazineTpls = modPool.Where(magTpl =>
|
||||||
{
|
{
|
||||||
var magazineDb = itemHelper.GetItem(magTpl).Value;
|
var magazineDb = itemHelper.GetItem(magTpl).Value;
|
||||||
return magazineDb.Properties?.Cartridges is not null
|
return magazineDb.Properties?.Cartridges is not null
|
||||||
&& magazineDb.Properties.Cartridges.FirstOrDefault()?.MaxCount
|
&& magazineDb.Properties.Cartridges.FirstOrDefault()?.MaxCount >= minMagSizeFromSettings;
|
||||||
>= minMagSizeFromSettings;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!desiredMagazineTpls.Any())
|
if (!desiredMagazineTpls.Any())
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Magazine size filter for: {weaponTpl} was too strict, ignoring filter");
|
||||||
$"Magazine size filter for: {weaponTpl} was too strict, ignoring filter"
|
|
||||||
);
|
|
||||||
|
|
||||||
return modPool;
|
return modPool;
|
||||||
}
|
}
|
||||||
@@ -1317,15 +1140,12 @@ public class BotEquipmentModGenerator(
|
|||||||
{
|
{
|
||||||
Incompatible = true,
|
Incompatible = true,
|
||||||
Found = false,
|
Found = false,
|
||||||
Reason =
|
Reason = $"Unable to add mod to {choiceTypeEnum.ToString()} slot: {modSlotName}. All: {modPool.Count} had conflicts",
|
||||||
$"Unable to add mod to {choiceTypeEnum.ToString()} slot: {modSlotName}. All: {modPool.Count} had conflicts",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter modpool to only items that appear in parents allowed list
|
// Filter modpool to only items that appear in parents allowed list
|
||||||
preFilteredModPool = preFilteredModPool
|
preFilteredModPool = preFilteredModPool.Where(tpl => parentSlot.Props.Filters.First().Filter.Contains(tpl)).ToHashSet();
|
||||||
.Where(tpl => parentSlot.Props.Filters.First().Filter.Contains(tpl))
|
|
||||||
.ToHashSet();
|
|
||||||
if (preFilteredModPool.Count == 0)
|
if (preFilteredModPool.Count == 0)
|
||||||
{
|
{
|
||||||
return new ChooseRandomCompatibleModResult
|
return new ChooseRandomCompatibleModResult
|
||||||
@@ -1393,8 +1213,7 @@ public class BotEquipmentModGenerator(
|
|||||||
|
|
||||||
// Check if existing weapon mods are incompatible with chosen item
|
// Check if existing weapon mods are incompatible with chosen item
|
||||||
var existingItemBlockingChoice = weapon.FirstOrDefault(item =>
|
var existingItemBlockingChoice = weapon.FirstOrDefault(item =>
|
||||||
pickedItemDetails.Value.Properties.ConflictingItems?.Contains(item.Template)
|
pickedItemDetails.Value.Properties.ConflictingItems?.Contains(item.Template) ?? false
|
||||||
?? false
|
|
||||||
);
|
);
|
||||||
if (existingItemBlockingChoice is not null)
|
if (existingItemBlockingChoice is not null)
|
||||||
{
|
{
|
||||||
@@ -1417,8 +1236,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Edge case - Some mod combos will never work, make sure this isn't the case
|
// Edge case - Some mod combos will never work, make sure this isn't the case
|
||||||
if (WeaponModComboIsIncompatible(weapon, chosenTpl))
|
if (WeaponModComboIsIncompatible(weapon, chosenTpl))
|
||||||
{
|
{
|
||||||
chosenModResult.Reason =
|
chosenModResult.Reason = $"Chosen weapon mod: {chosenTpl} can never be compatible with existing weapon mods";
|
||||||
$"Chosen weapon mod: {chosenTpl} can never be compatible with existing weapon mods";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1444,10 +1262,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modPool"></param>
|
/// <param name="modPool"></param>
|
||||||
/// <param name="tplBlacklist">Tpls that are incompatible and should not be used</param>
|
/// <param name="tplBlacklist">Tpls that are incompatible and should not be used</param>
|
||||||
/// <returns>string array of compatible mod tpls with weapon</returns>
|
/// <returns>string array of compatible mod tpls with weapon</returns>
|
||||||
public HashSet<MongoId> GetFilteredModPool(
|
public HashSet<MongoId> GetFilteredModPool(HashSet<MongoId> modPool, HashSet<MongoId> tplBlacklist)
|
||||||
HashSet<MongoId> modPool,
|
|
||||||
HashSet<MongoId> tplBlacklist
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return modPool.Where(tpl => !tplBlacklist.Contains(tpl)).ToHashSet();
|
return modPool.Where(tpl => !tplBlacklist.Contains(tpl)).ToHashSet();
|
||||||
}
|
}
|
||||||
@@ -1461,10 +1276,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="weaponTemplate">Mods root parent (weapon/equipment)</param>
|
/// <param name="weaponTemplate">Mods root parent (weapon/equipment)</param>
|
||||||
/// <returns>Array of mod tpls</returns>
|
/// <returns>Array of mod tpls</returns>
|
||||||
public HashSet<MongoId>? GetModPoolForSlot(
|
public HashSet<MongoId>? GetModPoolForSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||||
ModToSpawnRequest request,
|
|
||||||
TemplateItem weaponTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Mod is flagged as being default only, try and find it in globals
|
// Mod is flagged as being default only, try and find it in globals
|
||||||
if (request.ModSpawnResult == ModSpawn.DEFAULT_MOD)
|
if (request.ModSpawnResult == ModSpawn.DEFAULT_MOD)
|
||||||
@@ -1474,11 +1286,7 @@ public class BotEquipmentModGenerator(
|
|||||||
|
|
||||||
if (request.IsRandomisableSlot.GetValueOrDefault(false))
|
if (request.IsRandomisableSlot.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
return GetDynamicModPool(
|
return GetDynamicModPool(request.ParentTemplate.Id, request.ModSlot, request.BotEquipBlacklist);
|
||||||
request.ParentTemplate.Id,
|
|
||||||
request.ModSlot,
|
|
||||||
request.BotEquipBlacklist
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required mod is not default or randomisable, use existing pool
|
// Required mod is not default or randomisable, use existing pool
|
||||||
@@ -1491,10 +1299,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
/// <param name="weaponTemplate"></param>
|
/// <param name="weaponTemplate"></param>
|
||||||
/// <returns>Hashset of mods keyed by slot</returns>
|
/// <returns>Hashset of mods keyed by slot</returns>
|
||||||
public HashSet<MongoId> GetModPoolForDefaultSlot(
|
public HashSet<MongoId> GetModPoolForDefaultSlot(ModToSpawnRequest request, TemplateItem weaponTemplate)
|
||||||
ModToSpawnRequest request,
|
|
||||||
TemplateItem weaponTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var matchingModFromPreset = GetMatchingModFromPreset(request, weaponTemplate);
|
var matchingModFromPreset = GetMatchingModFromPreset(request, weaponTemplate);
|
||||||
if (matchingModFromPreset is null)
|
if (matchingModFromPreset is null)
|
||||||
@@ -1517,10 +1322,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Filtering mod pool to item that wasn't already there can have problems;
|
// Filtering mod pool to item that wasn't already there can have problems;
|
||||||
// You'd have a mod being picked without any sub-mods in its chain, possibly resulting in missing required mods not being added
|
// You'd have a mod being picked without any sub-mods in its chain, possibly resulting in missing required mods not being added
|
||||||
// Mod is in existing mod pool
|
// Mod is in existing mod pool
|
||||||
if (
|
if (request.ItemModPool.TryGetValue(request.ModSlot, out var ids) && ids.Contains(matchingModFromPreset.Template))
|
||||||
request.ItemModPool.TryGetValue(request.ModSlot, out var ids)
|
|
||||||
&& ids.Contains(matchingModFromPreset.Template)
|
|
||||||
)
|
|
||||||
// Found mod on preset + it already exists in mod pool
|
// Found mod on preset + it already exists in mod pool
|
||||||
{
|
{
|
||||||
return [matchingModFromPreset.Template];
|
return [matchingModFromPreset.Template];
|
||||||
@@ -1530,11 +1332,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Check the filter of the slot to ensure a chosen mod fits
|
// Check the filter of the slot to ensure a chosen mod fits
|
||||||
var parentSlotCompatibleItems = request
|
var parentSlotCompatibleItems = request
|
||||||
.ParentTemplate.Properties.Slots?.FirstOrDefault(slot =>
|
.ParentTemplate.Properties.Slots?.FirstOrDefault(slot =>
|
||||||
string.Equals(
|
string.Equals(slot.Name.ToLowerInvariant(), request.ModSlot.ToLowerInvariant(), StringComparison.Ordinal)
|
||||||
slot.Name.ToLowerInvariant(),
|
|
||||||
request.ModSlot.ToLowerInvariant(),
|
|
||||||
StringComparison.Ordinal
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
?.Props.Filters?.First()
|
?.Props.Filters?.First()
|
||||||
.Filter;
|
.Filter;
|
||||||
@@ -1571,9 +1369,7 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Last ditch, use full pool of items minus conflicts
|
// Last ditch, use full pool of items minus conflicts
|
||||||
var newListOfModsForSlot = parentSlotCompatibleItems.Where(tpl =>
|
var newListOfModsForSlot = parentSlotCompatibleItems.Where(tpl => !request.ConflictingItemTpls.Contains(tpl));
|
||||||
!request.ConflictingItemTpls.Contains(tpl)
|
|
||||||
);
|
|
||||||
if (newListOfModsForSlot.Any())
|
if (newListOfModsForSlot.Any())
|
||||||
{
|
{
|
||||||
return newListOfModsForSlot.ToHashSet();
|
return newListOfModsForSlot.ToHashSet();
|
||||||
@@ -1618,8 +1414,7 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Edge case - dvl 500mm is the silenced barrel and has specific muzzle mods
|
// Edge case - dvl 500mm is the silenced barrel and has specific muzzle mods
|
||||||
var isDvl500mmSilencedBarrel =
|
var isDvl500mmSilencedBarrel = parentItemTpl == ItemTpl.BARREL_DVL10_762X51_500MM_SUPPRESSED;
|
||||||
parentItemTpl == ItemTpl.BARREL_DVL10_762X51_500MM_SUPPRESSED;
|
|
||||||
|
|
||||||
if (isDvl500mmSilencedBarrel)
|
if (isDvl500mmSilencedBarrel)
|
||||||
{
|
{
|
||||||
@@ -1638,10 +1433,7 @@ public class BotEquipmentModGenerator(
|
|||||||
public bool WeaponModComboIsIncompatible(IEnumerable<Item> weapon, MongoId modTpl)
|
public bool WeaponModComboIsIncompatible(IEnumerable<Item> weapon, MongoId modTpl)
|
||||||
{
|
{
|
||||||
// STM-9 + AR-15 Lone Star Ion Lite handguard
|
// STM-9 + AR-15 Lone Star Ion Lite handguard
|
||||||
if (
|
if (weapon.First().Template == ItemTpl.SMG_SOYUZTM_STM9_GEN2_9X19_CARBINE && modTpl == ItemTpl.HANDGUARD_AR15_LONE_STAR_ION_LITE)
|
||||||
weapon.First().Template == ItemTpl.SMG_SOYUZTM_STM9_GEN2_9X19_CARBINE
|
|
||||||
&& modTpl == ItemTpl.HANDGUARD_AR15_LONE_STAR_ION_LITE
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1659,14 +1451,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modTemplate">Used to add additional properties in the upd object</param>
|
/// <param name="modTemplate">Used to add additional properties in the upd object</param>
|
||||||
/// <param name="botRole">The bots role mod is being created for</param>
|
/// <param name="botRole">The bots role mod is being created for</param>
|
||||||
/// <returns>Item object</returns>
|
/// <returns>Item object</returns>
|
||||||
public Item CreateModItem(
|
public Item CreateModItem(MongoId modId, MongoId modTpl, string parentId, string modSlot, TemplateItem modTemplate, string botRole)
|
||||||
MongoId modId,
|
|
||||||
MongoId modTpl,
|
|
||||||
string parentId,
|
|
||||||
string modSlot,
|
|
||||||
TemplateItem modTemplate,
|
|
||||||
string botRole
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return new Item
|
return new Item
|
||||||
{
|
{
|
||||||
@@ -1696,12 +1481,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modSlot">Slot to get mod to fill</param>
|
/// <param name="modSlot">Slot to get mod to fill</param>
|
||||||
/// <param name="items">Items to ensure picked mod is compatible with</param>
|
/// <param name="items">Items to ensure picked mod is compatible with</param>
|
||||||
/// <returns>Item tpl</returns>
|
/// <returns>Item tpl</returns>
|
||||||
public MongoId? GetRandomModTplFromItemDb(
|
public MongoId? GetRandomModTplFromItemDb(MongoId fallbackModTpl, Slot parentSlot, string modSlot, IEnumerable<Item> items)
|
||||||
MongoId fallbackModTpl,
|
|
||||||
Slot parentSlot,
|
|
||||||
string modSlot,
|
|
||||||
IEnumerable<Item> items
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Find compatible mods and make an array of them
|
// Find compatible mods and make an array of them
|
||||||
var allowedItems = parentSlot.Props.Filters.First().Filter;
|
var allowedItems = parentSlot.Props.Filters.First().Filter;
|
||||||
@@ -1712,11 +1492,7 @@ public class BotEquipmentModGenerator(
|
|||||||
while (exhaustableModPool.HasValues())
|
while (exhaustableModPool.HasValues())
|
||||||
{
|
{
|
||||||
tmpModTpl = exhaustableModPool.GetRandomValue();
|
tmpModTpl = exhaustableModPool.GetRandomValue();
|
||||||
if (
|
if (!botGeneratorHelper.IsItemIncompatibleWithCurrentItems(items, tmpModTpl, modSlot).Incompatible.GetValueOrDefault(false))
|
||||||
!botGeneratorHelper
|
|
||||||
.IsItemIncompatibleWithCurrentItems(items, tmpModTpl, modSlot)
|
|
||||||
.Incompatible.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return tmpModTpl;
|
return tmpModTpl;
|
||||||
}
|
}
|
||||||
@@ -1803,9 +1579,7 @@ public class BotEquipmentModGenerator(
|
|||||||
EquipmentFilterDetails botEquipBlacklist
|
EquipmentFilterDetails botEquipBlacklist
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var desiredSlotObject = modTemplate.Properties?.Slots?.FirstOrDefault(slot =>
|
var desiredSlotObject = modTemplate.Properties?.Slots?.FirstOrDefault(slot => slot.Name.Contains(desiredSlotName));
|
||||||
slot.Name.Contains(desiredSlotName)
|
|
||||||
);
|
|
||||||
|
|
||||||
var supportedSubMods = desiredSlotObject?.Props?.Filters?.FirstOrDefault()?.Filter;
|
var supportedSubMods = desiredSlotObject?.Props?.Filters?.FirstOrDefault()?.Filter;
|
||||||
if (supportedSubMods is null)
|
if (supportedSubMods is null)
|
||||||
@@ -1816,11 +1590,7 @@ public class BotEquipmentModGenerator(
|
|||||||
var supportedSubModsSet = supportedSubMods.ToHashSet();
|
var supportedSubModsSet = supportedSubMods.ToHashSet();
|
||||||
|
|
||||||
// Filter mods
|
// Filter mods
|
||||||
var filteredMods = FilterModsByBlacklist(
|
var filteredMods = FilterModsByBlacklist(supportedSubModsSet, botEquipBlacklist, desiredSlotName);
|
||||||
supportedSubModsSet,
|
|
||||||
botEquipBlacklist,
|
|
||||||
desiredSlotName
|
|
||||||
);
|
|
||||||
if (!filteredMods.Any())
|
if (!filteredMods.Any())
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(
|
||||||
@@ -1843,15 +1613,9 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="modSlot">Slot item should fit in</param>
|
/// <param name="modSlot">Slot item should fit in</param>
|
||||||
/// <param name="botEquipBlacklist">Equipment that should not be picked</param>
|
/// <param name="botEquipBlacklist">Equipment that should not be picked</param>
|
||||||
/// <returns>Array of compatible items for that slot</returns>
|
/// <returns>Array of compatible items for that slot</returns>
|
||||||
public HashSet<MongoId> GetDynamicModPool(
|
public HashSet<MongoId> GetDynamicModPool(string parentItemId, string modSlot, EquipmentFilterDetails botEquipBlacklist)
|
||||||
string parentItemId,
|
|
||||||
string modSlot,
|
|
||||||
EquipmentFilterDetails botEquipBlacklist
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var modsFromDynamicPool = cloner.Clone(
|
var modsFromDynamicPool = cloner.Clone(botEquipmentModPoolService.GetCompatibleModsForWeaponSlot(parentItemId, modSlot));
|
||||||
botEquipmentModPoolService.GetCompatibleModsForWeaponSlot(parentItemId, modSlot)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (modsFromDynamicPool.Count == 0)
|
if (modsFromDynamicPool.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -1866,12 +1630,7 @@ public class BotEquipmentModGenerator(
|
|||||||
return filteredMods;
|
return filteredMods;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("bot-unable_to_filter_mod_slot_all_blacklisted", modSlot));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-unable_to_filter_mod_slot_all_blacklisted",
|
|
||||||
modSlot
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return modsFromDynamicPool;
|
return modsFromDynamicPool;
|
||||||
}
|
}
|
||||||
@@ -1883,11 +1642,7 @@ public class BotEquipmentModGenerator(
|
|||||||
/// <param name="botEquipBlacklist">Equipment blacklist details for bot level range</param>
|
/// <param name="botEquipBlacklist">Equipment blacklist details for bot level range</param>
|
||||||
/// <param name="modSlot">Mod slot mods belong to</param>
|
/// <param name="modSlot">Mod slot mods belong to</param>
|
||||||
/// <returns>New set of tpls not in blacklist(s)</returns>
|
/// <returns>New set of tpls not in blacklist(s)</returns>
|
||||||
public HashSet<MongoId> FilterModsByBlacklist(
|
public HashSet<MongoId> FilterModsByBlacklist(HashSet<MongoId> modTplPool, EquipmentFilterDetails? botEquipBlacklist, string modSlot)
|
||||||
HashSet<MongoId> modTplPool,
|
|
||||||
EquipmentFilterDetails? botEquipBlacklist,
|
|
||||||
string modSlot
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!modTplPool.Any())
|
if (!modTplPool.Any())
|
||||||
{
|
{
|
||||||
@@ -1898,10 +1653,7 @@ public class BotEquipmentModGenerator(
|
|||||||
// Get item blacklist and mod equipment blacklist as one Set
|
// Get item blacklist and mod equipment blacklist as one Set
|
||||||
var blacklist = new HashSet<MongoId>();
|
var blacklist = new HashSet<MongoId>();
|
||||||
blacklist.UnionWith(itemFilterService.GetBlacklistedItems());
|
blacklist.UnionWith(itemFilterService.GetBlacklistedItems());
|
||||||
if (
|
if (botEquipBlacklist?.Equipment is not null && botEquipBlacklist.Equipment.TryGetValue(modSlot, out var equipmentBlacklistValues))
|
||||||
botEquipBlacklist?.Equipment is not null
|
|
||||||
&& botEquipBlacklist.Equipment.TryGetValue(modSlot, out var equipmentBlacklistValues)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
blacklist.UnionWith(equipmentBlacklistValues);
|
blacklist.UnionWith(equipmentBlacklistValues);
|
||||||
}
|
}
|
||||||
@@ -1939,17 +1691,13 @@ public class BotEquipmentModGenerator(
|
|||||||
new { weaponId = cylinderMagTemplate.Id, weaponName = cylinderMagTemplate.Name }
|
new { weaponId = cylinderMagTemplate.Id, weaponName = cylinderMagTemplate.Name }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
var camoraSlots = cylinderMagTemplate.Properties.Slots.Where(slot =>
|
var camoraSlots = cylinderMagTemplate.Properties.Slots.Where(slot => slot.Name.StartsWith("camora"));
|
||||||
slot.Name.StartsWith("camora")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Attempt to generate camora slots for item
|
// Attempt to generate camora slots for item
|
||||||
modPool[cylinderMagTemplate.Id] = new Dictionary<string, HashSet<MongoId>>();
|
modPool[cylinderMagTemplate.Id] = new Dictionary<string, HashSet<MongoId>>();
|
||||||
foreach (var camora in camoraSlots)
|
foreach (var camora in camoraSlots)
|
||||||
{
|
{
|
||||||
modPool[cylinderMagTemplate.Id][camora.Name] = camora
|
modPool[cylinderMagTemplate.Id][camora.Name] = camora.Props.Filters.First().Filter.ToHashSet();
|
||||||
.Props.Filters.First()
|
|
||||||
.Filter.ToHashSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itemModPool = modPool[cylinderMagTemplate.Id];
|
itemModPool = modPool[cylinderMagTemplate.Id];
|
||||||
@@ -1969,12 +1717,7 @@ public class BotEquipmentModGenerator(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-missing_cartridge_slot", cylinderMagTemplate.Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-missing_cartridge_slot",
|
|
||||||
cylinderMagTemplate.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1984,11 +1727,7 @@ public class BotEquipmentModGenerator(
|
|||||||
while (exhaustibleModPool.HasValues())
|
while (exhaustibleModPool.HasValues())
|
||||||
{
|
{
|
||||||
modTpl = exhaustibleModPool.GetRandomValue();
|
modTpl = exhaustibleModPool.GetRandomValue();
|
||||||
if (
|
if (!botGeneratorHelper.IsItemIncompatibleWithCurrentItems(items, modTpl, modSlot).Incompatible.GetValueOrDefault(false))
|
||||||
!botGeneratorHelper
|
|
||||||
.IsItemIncompatibleWithCurrentItems(items, modTpl, modSlot)
|
|
||||||
.Incompatible.GetValueOrDefault(false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -1997,9 +1736,7 @@ public class BotEquipmentModGenerator(
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-no_compatible_camora_ammo_found", modSlot));
|
||||||
serverLocalisationService.GetText("bot-no_compatible_camora_ammo_found", modSlot)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2048,12 +1785,7 @@ public class BotEquipmentModGenerator(
|
|||||||
var weaponDetails = itemHelper.GetItem(weapon.Template);
|
var weaponDetails = itemHelper.GetItem(weapon.Template);
|
||||||
|
|
||||||
// Return original scopes array if whitelist not found
|
// Return original scopes array if whitelist not found
|
||||||
if (
|
if (!botWeaponSightWhitelist.TryGetValue(weaponDetails.Value.Parent, out var whitelistedSightTypes))
|
||||||
!botWeaponSightWhitelist.TryGetValue(
|
|
||||||
weaponDetails.Value.Parent,
|
|
||||||
out var whitelistedSightTypes
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
@@ -2089,17 +1821,14 @@ public class BotEquipmentModGenerator(
|
|||||||
// Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots)
|
// Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots)
|
||||||
// Should only find 1 as there's currently no items with a mod_scope AND a mod_scope_000
|
// Should only find 1 as there's currently no items with a mod_scope AND a mod_scope_000
|
||||||
HashSet<string> filter = ["mod_scope", "mod_scope_000"];
|
HashSet<string> filter = ["mod_scope", "mod_scope_000"];
|
||||||
var scopeSlot = itemDetails.Properties.Slots.Where(slot =>
|
var scopeSlot = itemDetails.Properties.Slots.Where(slot => filter.Contains(slot.Name));
|
||||||
filter.Contains(slot.Name)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Mods scope slot found must allow ALL whitelisted scope types OR be a mount
|
// Mods scope slot found must allow ALL whitelisted scope types OR be a mount
|
||||||
if (
|
if (
|
||||||
scopeSlot?.All(slot =>
|
scopeSlot?.All(slot =>
|
||||||
slot.Props.Filters.FirstOrDefault()
|
slot.Props.Filters.FirstOrDefault()
|
||||||
.Filter.All(tpl =>
|
.Filter.All(tpl =>
|
||||||
itemHelper.IsOfBaseclasses(tpl, whitelistedSightTypes)
|
itemHelper.IsOfBaseclasses(tpl, whitelistedSightTypes) || itemHelper.IsOfBaseclass(tpl, BaseClasses.MOUNT)
|
||||||
|| itemHelper.IsOfBaseclass(tpl, BaseClasses.MOUNT)
|
|
||||||
)
|
)
|
||||||
) ?? false
|
) ?? false
|
||||||
)
|
)
|
||||||
@@ -2115,9 +1844,7 @@ public class BotEquipmentModGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Scope whitelist too restrictive for: {weapon.Template} {weaponDetails.Value.Name}, skipping filter");
|
||||||
$"Scope whitelist too restrictive for: {weapon.Template} {weaponDetails.Value.Name}, skipping filter"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return scopes;
|
return scopes;
|
||||||
|
|||||||
@@ -48,13 +48,7 @@ public class BotGenerator(
|
|||||||
/// <param name="botTemplate">base bot template to use (e.g. assault/pmcbot)</param>
|
/// <param name="botTemplate">base bot template to use (e.g. assault/pmcbot)</param>
|
||||||
/// <param name="profile">profile of player generating pscav</param>
|
/// <param name="profile">profile of player generating pscav</param>
|
||||||
/// <returns>BotBase</returns>
|
/// <returns>BotBase</returns>
|
||||||
public PmcData GeneratePlayerScav(
|
public PmcData GeneratePlayerScav(MongoId sessionId, string role, string difficulty, BotType botTemplate, PmcData profile)
|
||||||
MongoId sessionId,
|
|
||||||
string role,
|
|
||||||
string difficulty,
|
|
||||||
BotType botTemplate,
|
|
||||||
PmcData profile
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var bot = GetBotBaseClone();
|
var bot = GetBotBaseClone();
|
||||||
bot.Info.Settings.BotDifficulty = difficulty;
|
bot.Info.Settings.BotDifficulty = difficulty;
|
||||||
@@ -119,10 +113,7 @@ public class BotGenerator(
|
|||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <param name="botGenerationDetails">details on how to generate bots</param>
|
/// <param name="botGenerationDetails">details on how to generate bots</param>
|
||||||
/// <returns>constructed bot</returns>
|
/// <returns>constructed bot</returns>
|
||||||
public BotBase PrepareAndGenerateBot(
|
public BotBase PrepareAndGenerateBot(MongoId sessionId, BotGenerationDetails botGenerationDetails)
|
||||||
MongoId sessionId,
|
|
||||||
BotGenerationDetails botGenerationDetails
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var preparedBotBase = GetPreparedBotBase(
|
var preparedBotBase = GetPreparedBotBase(
|
||||||
botGenerationDetails.EventRole ?? botGenerationDetails.Role, // Use eventRole if provided
|
botGenerationDetails.EventRole ?? botGenerationDetails.Role, // Use eventRole if provided
|
||||||
@@ -137,9 +128,7 @@ public class BotGenerator(
|
|||||||
var botJsonTemplateClone = cloner.Clone(botHelper.GetBotTemplate(botRole));
|
var botJsonTemplateClone = cloner.Clone(botHelper.GetBotTemplate(botRole));
|
||||||
if (botJsonTemplateClone is null)
|
if (botJsonTemplateClone is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable to retrieve: {botRole} bot template, cannot generate bot of this type");
|
||||||
$"Unable to retrieve: {botRole} bot template, cannot generate bot of this type"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenerateBot(sessionId, preparedBotBase, botJsonTemplateClone, botGenerationDetails);
|
return GenerateBot(sessionId, preparedBotBase, botJsonTemplateClone, botGenerationDetails);
|
||||||
@@ -179,29 +168,15 @@ public class BotGenerator(
|
|||||||
/// <param name="botJsonTemplate">Bot template from db/bots/x.json</param>
|
/// <param name="botJsonTemplate">Bot template from db/bots/x.json</param>
|
||||||
/// <param name="botGenerationDetails">details on how to generate the bot</param>
|
/// <param name="botGenerationDetails">details on how to generate the bot</param>
|
||||||
/// <returns>BotBase object</returns>
|
/// <returns>BotBase object</returns>
|
||||||
protected BotBase GenerateBot(
|
protected BotBase GenerateBot(MongoId sessionId, BotBase bot, BotType botJsonTemplate, BotGenerationDetails botGenerationDetails)
|
||||||
MongoId sessionId,
|
|
||||||
BotBase bot,
|
|
||||||
BotType botJsonTemplate,
|
|
||||||
BotGenerationDetails botGenerationDetails
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var botRoleLowercase = botGenerationDetails.Role.ToLowerInvariant();
|
var botRoleLowercase = botGenerationDetails.Role.ToLowerInvariant();
|
||||||
var botLevel = botLevelGenerator.GenerateBotLevel(
|
var botLevel = botLevelGenerator.GenerateBotLevel(botJsonTemplate.BotExperience.Level, botGenerationDetails, bot);
|
||||||
botJsonTemplate.BotExperience.Level,
|
|
||||||
botGenerationDetails,
|
|
||||||
bot
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only filter bot equipment, never players
|
// Only filter bot equipment, never players
|
||||||
if (!botGenerationDetails.IsPlayerScav)
|
if (!botGenerationDetails.IsPlayerScav)
|
||||||
{
|
{
|
||||||
botEquipmentFilterService.FilterBotEquipment(
|
botEquipmentFilterService.FilterBotEquipment(sessionId, botJsonTemplate, botLevel.Level.Value, botGenerationDetails);
|
||||||
sessionId,
|
|
||||||
botJsonTemplate,
|
|
||||||
botLevel.Level.Value,
|
|
||||||
botGenerationDetails
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bot.Info.Nickname = botNameService.GenerateUniqueBotNickname(
|
bot.Info.Nickname = botNameService.GenerateUniqueBotNickname(
|
||||||
@@ -212,9 +187,7 @@ public class BotGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Only Pmcs should have a lower nickname
|
// Only Pmcs should have a lower nickname
|
||||||
bot.Info.LowerNickname = botGenerationDetails.IsPmc
|
bot.Info.LowerNickname = botGenerationDetails.IsPmc ? bot.Info.Nickname.ToLowerInvariant() : string.Empty;
|
||||||
? bot.Info.Nickname.ToLowerInvariant()
|
|
||||||
: string.Empty;
|
|
||||||
|
|
||||||
// Only run when generating a 'fake' playerscav, not actual player scav
|
// Only run when generating a 'fake' playerscav, not actual player scav
|
||||||
if (!botGenerationDetails.IsPlayerScav && ShouldSimulatePlayerScav(botRoleLowercase))
|
if (!botGenerationDetails.IsPlayerScav && ShouldSimulatePlayerScav(botRoleLowercase))
|
||||||
@@ -228,10 +201,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
if (botGenerationDetails.Role != "gifter")
|
if (botGenerationDetails.Role != "gifter")
|
||||||
{
|
{
|
||||||
seasonalEventService.RemoveChristmasItemsFromBotInventory(
|
seasonalEventService.RemoveChristmasItemsFromBotInventory(botJsonTemplate.BotInventory, botGenerationDetails.Role);
|
||||||
botJsonTemplate.BotInventory,
|
|
||||||
botGenerationDetails.Role
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,14 +231,10 @@ public class BotGenerator(
|
|||||||
botGenerationDetails.Role
|
botGenerationDetails.Role
|
||||||
);
|
);
|
||||||
bot.Info.Settings.UseSimpleAnimator = botJsonTemplate.BotExperience.UseSimpleAnimator;
|
bot.Info.Settings.UseSimpleAnimator = botJsonTemplate.BotExperience.UseSimpleAnimator;
|
||||||
var chosenVoiceName = weightedRandomHelper.GetWeightedValue(
|
var chosenVoiceName = weightedRandomHelper.GetWeightedValue(botJsonTemplate.BotAppearance.Voice);
|
||||||
botJsonTemplate.BotAppearance.Voice
|
|
||||||
);
|
|
||||||
bot.Customization.Voice = databaseService
|
bot.Customization.Voice = databaseService
|
||||||
.GetCustomization()
|
.GetCustomization()
|
||||||
.FirstOrDefault(customisation =>
|
.FirstOrDefault(customisation => customisation.Value.Name.Equals(chosenVoiceName, StringComparison.OrdinalIgnoreCase))
|
||||||
customisation.Value.Name.Equals(chosenVoiceName, StringComparison.OrdinalIgnoreCase)
|
|
||||||
)
|
|
||||||
.Key;
|
.Key;
|
||||||
bot.Health = GenerateHealth(botJsonTemplate.BotHealth, botGenerationDetails.IsPlayerScav);
|
bot.Health = GenerateHealth(botJsonTemplate.BotHealth, botGenerationDetails.IsPlayerScav);
|
||||||
bot.Skills = GenerateSkills(botJsonTemplate.BotSkills);
|
bot.Skills = GenerateSkills(botJsonTemplate.BotSkills);
|
||||||
@@ -323,8 +289,7 @@ public class BotGenerator(
|
|||||||
/// <returns>True if name should be simulated pscav</returns>
|
/// <returns>True if name should be simulated pscav</returns>
|
||||||
protected bool ShouldSimulatePlayerScav(string botRole)
|
protected bool ShouldSimulatePlayerScav(string botRole)
|
||||||
{
|
{
|
||||||
return botRole == Roles.Assault
|
return botRole == Roles.Assault && randomUtil.GetChance100(_botConfig.ChanceAssaultScavHasPlayerScavName);
|
||||||
&& randomUtil.GetChance100(_botConfig.ChanceAssaultScavHasPlayerScavName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -334,19 +299,13 @@ public class BotGenerator(
|
|||||||
/// <param name="botDifficulty">the killed bots difficulty</param>
|
/// <param name="botDifficulty">the killed bots difficulty</param>
|
||||||
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
||||||
/// <returns>Experience for kill</returns>
|
/// <returns>Experience for kill</returns>
|
||||||
protected int GetExperienceRewardForKillByDifficulty(
|
protected int GetExperienceRewardForKillByDifficulty(Dictionary<string, MinMax<int>> experiences, string botDifficulty, string role)
|
||||||
Dictionary<string, MinMax<int>> experiences,
|
|
||||||
string botDifficulty,
|
|
||||||
string role
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!experiences.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
if (!experiences.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Unable to find experience: {botDifficulty} for {role} bot, falling back to `normal`");
|
||||||
$"Unable to find experience: {botDifficulty} for {role} bot, falling back to `normal`"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomUtil.GetInt(experiences["normal"].Min, experiences["normal"].Max);
|
return randomUtil.GetInt(experiences["normal"].Min, experiences["normal"].Max);
|
||||||
@@ -369,17 +328,11 @@ public class BotGenerator(
|
|||||||
/// <param name="botDifficulty">Difficulty of bot to look up</param>
|
/// <param name="botDifficulty">Difficulty of bot to look up</param>
|
||||||
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
||||||
/// <returns>Standing change value</returns>
|
/// <returns>Standing change value</returns>
|
||||||
protected double GetStandingChangeForKillByDifficulty(
|
protected double GetStandingChangeForKillByDifficulty(Dictionary<string, double> standingsForKill, string botDifficulty, string role)
|
||||||
Dictionary<string, double> standingsForKill,
|
|
||||||
string botDifficulty,
|
|
||||||
string role
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!standingsForKill.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
if (!standingsForKill.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Unable to find standing for kill value for: {role} {botDifficulty}, falling back to `normal`");
|
||||||
$"Unable to find standing for kill value for: {role} {botDifficulty}, falling back to `normal`"
|
|
||||||
);
|
|
||||||
|
|
||||||
return standingsForKill["normal"];
|
return standingsForKill["normal"];
|
||||||
}
|
}
|
||||||
@@ -394,17 +347,11 @@ public class BotGenerator(
|
|||||||
/// <param name="botDifficulty">Difficulty of bot to look up</param>
|
/// <param name="botDifficulty">Difficulty of bot to look up</param>
|
||||||
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
/// <param name="role">Role of bot (optional, used for error logging)</param>
|
||||||
/// <returns>Standing change value</returns>
|
/// <returns>Standing change value</returns>
|
||||||
protected double GetAggressorBonusByDifficulty(
|
protected double GetAggressorBonusByDifficulty(Dictionary<string, double> aggressorBonuses, string botDifficulty, string role)
|
||||||
Dictionary<string, double> aggressorBonuses,
|
|
||||||
string botDifficulty,
|
|
||||||
string role
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!aggressorBonuses.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
if (!aggressorBonuses.TryGetValue(botDifficulty.ToLowerInvariant(), out var result))
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Unable to find aggressor bonus for kill value for: {role} {botDifficulty}, falling back to `normal`");
|
||||||
$"Unable to find aggressor bonus for kill value for: {role} {botDifficulty}, falling back to `normal`"
|
|
||||||
);
|
|
||||||
|
|
||||||
return aggressorBonuses["normal"];
|
return aggressorBonuses["normal"];
|
||||||
}
|
}
|
||||||
@@ -465,11 +412,7 @@ public class BotGenerator(
|
|||||||
/// <param name="bot">Bot to adjust</param>
|
/// <param name="bot">Bot to adjust</param>
|
||||||
/// <param name="appearance">Appearance settings to choose from</param>
|
/// <param name="appearance">Appearance settings to choose from</param>
|
||||||
/// <param name="botGenerationDetails">Generation details</param>
|
/// <param name="botGenerationDetails">Generation details</param>
|
||||||
protected void SetBotAppearance(
|
protected void SetBotAppearance(BotBase bot, Appearance appearance, BotGenerationDetails botGenerationDetails)
|
||||||
BotBase bot,
|
|
||||||
Appearance appearance,
|
|
||||||
BotGenerationDetails botGenerationDetails
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Choose random values by weight
|
// Choose random values by weight
|
||||||
bot.Customization.Head = weightedRandomHelper.GetWeightedValue(appearance.Head);
|
bot.Customization.Head = weightedRandomHelper.GetWeightedValue(appearance.Head);
|
||||||
@@ -480,9 +423,7 @@ public class BotGenerator(
|
|||||||
var chosenBodyTemplate = databaseService.GetCustomization()[bot.Customization.Body.Value];
|
var chosenBodyTemplate = databaseService.GetCustomization()[bot.Customization.Body.Value];
|
||||||
|
|
||||||
// Some bodies have matching hands, look up body to see if this is the case
|
// Some bodies have matching hands, look up body to see if this is the case
|
||||||
var chosenBody = bodyGlobalDictDb.FirstOrDefault(c =>
|
var chosenBody = bodyGlobalDictDb.FirstOrDefault(c => c.Key == chosenBodyTemplate?.Name.Trim());
|
||||||
c.Key == chosenBodyTemplate?.Name.Trim()
|
|
||||||
);
|
|
||||||
bot.Customization.Hands =
|
bot.Customization.Hands =
|
||||||
chosenBody.Value?.IsNotRandom ?? false
|
chosenBody.Value?.IsNotRandom ?? false
|
||||||
? chosenBody.Value.Hands // Has fixed hands for chosen body, update to match
|
? chosenBody.Value.Hands // Has fixed hands for chosen body, update to match
|
||||||
@@ -497,9 +438,7 @@ public class BotGenerator(
|
|||||||
/// <returns>Health object</returns>
|
/// <returns>Health object</returns>
|
||||||
protected BotBaseHealth GenerateHealth(BotTypeHealth healthObj, bool playerScav = false)
|
protected BotBaseHealth GenerateHealth(BotTypeHealth healthObj, bool playerScav = false)
|
||||||
{
|
{
|
||||||
var bodyParts = playerScav
|
var bodyParts = playerScav ? GetLowestHpBodyPart(healthObj.BodyParts) : randomUtil.GetArrayValue(healthObj.BodyParts);
|
||||||
? GetLowestHpBodyPart(healthObj.BodyParts)
|
|
||||||
: randomUtil.GetArrayValue(healthObj.BodyParts);
|
|
||||||
|
|
||||||
BotBaseHealth health = new()
|
BotBaseHealth health = new()
|
||||||
{
|
{
|
||||||
@@ -515,10 +454,7 @@ public class BotGenerator(
|
|||||||
},
|
},
|
||||||
Temperature = new CurrentMinMax
|
Temperature = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(healthObj.Temperature.Min, healthObj.Temperature.Max),
|
||||||
healthObj.Temperature.Min,
|
|
||||||
healthObj.Temperature.Max
|
|
||||||
),
|
|
||||||
Maximum = healthObj.Temperature.Max,
|
Maximum = healthObj.Temperature.Max,
|
||||||
},
|
},
|
||||||
BodyParts = new Dictionary<string, BodyPartHealth>
|
BodyParts = new Dictionary<string, BodyPartHealth>
|
||||||
@@ -540,10 +476,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.Chest.Min, bodyParts.Chest.Max),
|
||||||
bodyParts.Chest.Min,
|
|
||||||
bodyParts.Chest.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.Chest.Max),
|
Maximum = Math.Round(bodyParts.Chest.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -554,10 +487,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.Stomach.Min, bodyParts.Stomach.Max),
|
||||||
bodyParts.Stomach.Min,
|
|
||||||
bodyParts.Stomach.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.Stomach.Max),
|
Maximum = Math.Round(bodyParts.Stomach.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -568,10 +498,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.LeftArm.Min, bodyParts.LeftArm.Max),
|
||||||
bodyParts.LeftArm.Min,
|
|
||||||
bodyParts.LeftArm.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.LeftArm.Max),
|
Maximum = Math.Round(bodyParts.LeftArm.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -582,10 +509,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.RightArm.Min, bodyParts.RightArm.Max),
|
||||||
bodyParts.RightArm.Min,
|
|
||||||
bodyParts.RightArm.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.RightArm.Max),
|
Maximum = Math.Round(bodyParts.RightArm.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -596,10 +520,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.LeftLeg.Min, bodyParts.LeftLeg.Max),
|
||||||
bodyParts.LeftLeg.Min,
|
|
||||||
bodyParts.LeftLeg.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.LeftLeg.Max),
|
Maximum = Math.Round(bodyParts.LeftLeg.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -610,10 +531,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = randomUtil.GetDouble(
|
Current = randomUtil.GetDouble(bodyParts.RightLeg.Min, bodyParts.RightLeg.Max),
|
||||||
bodyParts.RightLeg.Min,
|
|
||||||
bodyParts.RightLeg.Max
|
|
||||||
),
|
|
||||||
Maximum = Math.Round(bodyParts.RightLeg.Max),
|
Maximum = Math.Round(bodyParts.RightLeg.Max),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -642,12 +560,7 @@ public class BotGenerator(
|
|||||||
.Select(bp => new
|
.Select(bp => new
|
||||||
{
|
{
|
||||||
BodyPart = bp,
|
BodyPart = bp,
|
||||||
TotalMaxHp = bp.Head.Max
|
TotalMaxHp = bp.Head.Max + bp.Chest.Max + bp.LeftArm.Max + bp.RightArm.Max + bp.LeftLeg.Max + bp.RightLeg.Max,
|
||||||
+ bp.Chest.Max
|
|
||||||
+ bp.LeftArm.Max
|
|
||||||
+ bp.RightArm.Max
|
|
||||||
+ bp.LeftLeg.Max
|
|
||||||
+ bp.RightLeg.Max,
|
|
||||||
})
|
})
|
||||||
.OrderBy(x => x.TotalMaxHp)
|
.OrderBy(x => x.TotalMaxHp)
|
||||||
.FirstOrDefault()
|
.FirstOrDefault()
|
||||||
@@ -676,9 +589,7 @@ public class BotGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="skills">Skills to randomise</param>
|
/// <param name="skills">Skills to randomise</param>
|
||||||
/// <returns>Skills with randomised progress values as a collection</returns>
|
/// <returns>Skills with randomised progress values as a collection</returns>
|
||||||
protected List<CommonSkill> GetCommonSkillsWithRandomisedProgressValue(
|
protected List<CommonSkill> GetCommonSkillsWithRandomisedProgressValue(Dictionary<string, MinMax<double>> skills)
|
||||||
Dictionary<string, MinMax<double>> skills
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return skills
|
return skills
|
||||||
.Select(kvp =>
|
.Select(kvp =>
|
||||||
@@ -707,9 +618,7 @@ public class BotGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="masteringSkills">Skills to randomise</param>
|
/// <param name="masteringSkills">Skills to randomise</param>
|
||||||
/// <returns>Skills with randomised progress values as a collection</returns>
|
/// <returns>Skills with randomised progress values as a collection</returns>
|
||||||
protected List<MasterySkill> GetMasteringSkillsWithRandomisedProgressValue(
|
protected List<MasterySkill> GetMasteringSkillsWithRandomisedProgressValue(Dictionary<string, MinMax<double>>? masteringSkills)
|
||||||
Dictionary<string, MinMax<double>>? masteringSkills
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (masteringSkills is null)
|
if (masteringSkills is null)
|
||||||
{
|
{
|
||||||
@@ -727,11 +636,7 @@ public class BotGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All skills have id and progress props
|
// All skills have id and progress props
|
||||||
return new MasterySkill
|
return new MasterySkill { Id = kvp.Key, Progress = randomUtil.GetDouble(skill.Min, skill.Max) };
|
||||||
{
|
|
||||||
Id = kvp.Key,
|
|
||||||
Progress = randomUtil.GetDouble(skill.Min, skill.Max),
|
|
||||||
};
|
|
||||||
})
|
})
|
||||||
.Where(baseSkill => baseSkill != null)
|
.Where(baseSkill => baseSkill != null)
|
||||||
.ToList();
|
.ToList();
|
||||||
@@ -818,9 +723,7 @@ public class BotGenerator(
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Everyone else gets a weighted randomised category
|
// Everyone else gets a weighted randomised category
|
||||||
botInfo.MemberCategory = weightedRandomHelper.GetWeightedValue(
|
botInfo.MemberCategory = weightedRandomHelper.GetWeightedValue(_pmcConfig.AccountTypeWeight);
|
||||||
_pmcConfig.AccountTypeWeight
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,11 +51,7 @@ public class BotInventoryGenerator(
|
|||||||
|
|
||||||
private readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
|
private readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
|
||||||
|
|
||||||
private readonly FrozenSet<string> _slotsToCheck =
|
private readonly FrozenSet<string> _slotsToCheck = [nameof(EquipmentSlots.Pockets), nameof(EquipmentSlots.SecuredContainer)];
|
||||||
[
|
|
||||||
nameof(EquipmentSlots.Pockets),
|
|
||||||
nameof(EquipmentSlots.SecuredContainer),
|
|
||||||
];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add equipment/weapons/loot to bot
|
/// Add equipment/weapons/loot to bot
|
||||||
@@ -86,9 +82,7 @@ public class BotInventoryGenerator(
|
|||||||
var botInventory = GenerateInventoryBase();
|
var botInventory = GenerateInventoryBase();
|
||||||
|
|
||||||
// Get generated raid details bot will be spawned in
|
// Get generated raid details bot will be spawned in
|
||||||
var raidConfig = profileActivityService
|
var raidConfig = profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
|
||||||
.GetProfileActivityRaidData(sessionId)
|
|
||||||
?.RaidConfiguration;
|
|
||||||
|
|
||||||
GenerateAndAddEquipmentToBot(
|
GenerateAndAddEquipmentToBot(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -115,15 +109,7 @@ public class BotInventoryGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Pick loot and add to bots containers (rig/backpack/pockets/secure)
|
// Pick loot and add to bots containers (rig/backpack/pockets/secure)
|
||||||
botLootGenerator.GenerateLoot(
|
botLootGenerator.GenerateLoot(sessionId, botJsonTemplate, botGenerationDetails, isPmc, botRole, botInventory, botLevel);
|
||||||
sessionId,
|
|
||||||
botJsonTemplate,
|
|
||||||
botGenerationDetails,
|
|
||||||
isPmc,
|
|
||||||
botRole,
|
|
||||||
botInventory,
|
|
||||||
botLevel
|
|
||||||
);
|
|
||||||
|
|
||||||
return botInventory;
|
return botInventory;
|
||||||
}
|
}
|
||||||
@@ -150,11 +136,7 @@ public class BotInventoryGenerator(
|
|||||||
new Item { Id = questRaidItemsId, Template = ItemTpl.STASH_QUESTRAID },
|
new Item { Id = questRaidItemsId, Template = ItemTpl.STASH_QUESTRAID },
|
||||||
new Item { Id = questStashItemsId, Template = ItemTpl.STASH_QUESTOFFLINE },
|
new Item { Id = questStashItemsId, Template = ItemTpl.STASH_QUESTOFFLINE },
|
||||||
new Item { Id = sortingTableId, Template = ItemTpl.SORTINGTABLE_SORTING_TABLE },
|
new Item { Id = sortingTableId, Template = ItemTpl.SORTINGTABLE_SORTING_TABLE },
|
||||||
new Item
|
new Item { Id = hideoutCustomizationStashId, Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION },
|
||||||
{
|
|
||||||
Id = hideoutCustomizationStashId,
|
|
||||||
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
Equipment = equipmentId,
|
Equipment = equipmentId,
|
||||||
Stash = stashId,
|
Stash = stashId,
|
||||||
@@ -192,10 +174,7 @@ public class BotInventoryGenerator(
|
|||||||
GetRaidConfigurationRequestData? raidConfig
|
GetRaidConfigurationRequestData? raidConfig
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_botConfig.Equipment.TryGetValue(
|
_botConfig.Equipment.TryGetValue(botGeneratorHelper.GetBotEquipmentRole(botRole), out var botEquipConfig);
|
||||||
botGeneratorHelper.GetBotEquipmentRole(botRole),
|
|
||||||
out var botEquipConfig
|
|
||||||
);
|
|
||||||
var randomistionDetails = botHelper.GetBotRandomizationDetails(botLevel, botEquipConfig);
|
var randomistionDetails = botHelper.GetBotRandomizationDetails(botLevel, botEquipConfig);
|
||||||
|
|
||||||
// Apply nighttime changes if its nighttime + there's changes to make
|
// Apply nighttime changes if its nighttime + there's changes to make
|
||||||
@@ -205,11 +184,7 @@ public class BotInventoryGenerator(
|
|||||||
&& weatherHelper.IsNightTime(raidConfig.TimeVariant, raidConfig.Location)
|
&& weatherHelper.IsNightTime(raidConfig.TimeVariant, raidConfig.Location)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
foreach (
|
foreach (var (equipment, weight) in randomistionDetails.NighttimeChanges.EquipmentModsModifiers)
|
||||||
var (equipment, weight) in randomistionDetails
|
|
||||||
.NighttimeChanges
|
|
||||||
.EquipmentModsModifiers
|
|
||||||
)
|
|
||||||
// Never let mod chance go outside 0 - 100
|
// Never let mod chance go outside 0 - 100
|
||||||
{
|
{
|
||||||
var newWeight = weight + randomistionDetails.EquipmentMods[equipment];
|
var newWeight = weight + randomistionDetails.EquipmentMods[equipment];
|
||||||
@@ -260,11 +235,7 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
RootEquipmentSlot = EquipmentSlots.Pockets,
|
RootEquipmentSlot = EquipmentSlots.Pockets,
|
||||||
// Unheard profiles have unique sized pockets
|
// Unheard profiles have unique sized pockets
|
||||||
RootEquipmentPool = GetPocketPoolByGameEdition(
|
RootEquipmentPool = GetPocketPoolByGameEdition(chosenGameVersion, templateInventory, isPmc),
|
||||||
chosenGameVersion,
|
|
||||||
templateInventory,
|
|
||||||
isPmc
|
|
||||||
),
|
|
||||||
ModPool = templateInventory.Mods,
|
ModPool = templateInventory.Mods,
|
||||||
SpawnChances = wornItemChances,
|
SpawnChances = wornItemChances,
|
||||||
BotData = new BotData
|
BotData = new BotData
|
||||||
@@ -425,10 +396,7 @@ public class BotInventoryGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="templateEquipment">Equipment to filter TacticalVest of</param>
|
/// <param name="templateEquipment">Equipment to filter TacticalVest of</param>
|
||||||
/// <param name="botRole">Role of bot vests are being filtered for</param>
|
/// <param name="botRole">Role of bot vests are being filtered for</param>
|
||||||
public void FilterRigsToThoseWithProtection(
|
public void FilterRigsToThoseWithProtection(Dictionary<EquipmentSlots, Dictionary<MongoId, double>> templateEquipment, string botRole)
|
||||||
Dictionary<EquipmentSlots, Dictionary<MongoId, double>> templateEquipment,
|
|
||||||
string botRole
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest]
|
var tacVestsWithArmor = templateEquipment[EquipmentSlots.TacticalVest]
|
||||||
.Where(kvp => itemHelper.ItemHasSlots(kvp.Key))
|
.Where(kvp => itemHelper.ItemHasSlots(kvp.Key))
|
||||||
@@ -438,9 +406,7 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Unable to filter to only armored rigs as bot: {botRole} has none in pool");
|
||||||
$"Unable to filter to only armored rigs as bot: {botRole} has none in pool"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -469,9 +435,7 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Unable to filter to only unarmored rigs as bot: {botRole} has none in pool");
|
||||||
$"Unable to filter to only unarmored rigs as bot: {botRole} has none in pool"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -489,18 +453,11 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
double? spawnChance = _slotsToCheck.Contains(settings.RootEquipmentSlot.ToString())
|
double? spawnChance = _slotsToCheck.Contains(settings.RootEquipmentSlot.ToString())
|
||||||
? 100
|
? 100
|
||||||
: settings.SpawnChances.EquipmentChances.GetValueOrDefault(
|
: settings.SpawnChances.EquipmentChances.GetValueOrDefault(settings.RootEquipmentSlot.ToString());
|
||||||
settings.RootEquipmentSlot.ToString()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!spawnChance.HasValue)
|
if (!spawnChance.HasValue)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("bot-no_spawn_chance_defined_for_equipment_slot", settings.RootEquipmentSlot));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-no_spawn_chance_defined_for_equipment_slot",
|
|
||||||
settings.RootEquipmentSlot
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -522,19 +479,12 @@ public class BotInventoryGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chosenItemTpl = weightedRandomHelper.GetWeightedValue(
|
var chosenItemTpl = weightedRandomHelper.GetWeightedValue(settings.RootEquipmentPool);
|
||||||
settings.RootEquipmentPool
|
|
||||||
);
|
|
||||||
var dbResult = itemHelper.GetItem(chosenItemTpl);
|
var dbResult = itemHelper.GetItem(chosenItemTpl);
|
||||||
|
|
||||||
if (!dbResult.Key)
|
if (!dbResult.Key)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-missing_item_template", chosenItemTpl));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-missing_item_template",
|
|
||||||
chosenItemTpl
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug($"EquipmentSlot-> {settings.RootEquipmentSlot}");
|
logger.Debug($"EquipmentSlot-> {settings.RootEquipmentSlot}");
|
||||||
@@ -584,10 +534,7 @@ public class BotInventoryGenerator(
|
|||||||
Template = pickedItemDb.Id,
|
Template = pickedItemDb.Id,
|
||||||
ParentId = settings.Inventory.Equipment,
|
ParentId = settings.Inventory.Equipment,
|
||||||
SlotId = settings.RootEquipmentSlot.ToString(),
|
SlotId = settings.RootEquipmentSlot.ToString(),
|
||||||
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(
|
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(pickedItemDb, settings.BotData.Role),
|
||||||
pickedItemDb,
|
|
||||||
settings.BotData.Role
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var botEquipBlacklist = botEquipmentFilterService.GetBotEquipmentBlacklist(
|
var botEquipBlacklist = botEquipmentFilterService.GetBotEquipmentBlacklist(
|
||||||
@@ -599,27 +546,17 @@ public class BotInventoryGenerator(
|
|||||||
if (
|
if (
|
||||||
_botConfig.Equipment.ContainsKey(settings.BotData.EquipmentRole)
|
_botConfig.Equipment.ContainsKey(settings.BotData.EquipmentRole)
|
||||||
&& settings.RandomisationDetails?.RandomisedArmorSlots != null
|
&& settings.RandomisationDetails?.RandomisedArmorSlots != null
|
||||||
&& settings.RandomisationDetails.RandomisedArmorSlots.Contains(
|
&& settings.RandomisationDetails.RandomisedArmorSlots.Contains(settings.RootEquipmentSlot.ToString())
|
||||||
settings.RootEquipmentSlot.ToString()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
// Filter out mods from relevant blacklist
|
// Filter out mods from relevant blacklist
|
||||||
{
|
{
|
||||||
settings.ModPool[pickedItemDb.Id] = GetFilteredDynamicModsForItem(
|
settings.ModPool[pickedItemDb.Id] = GetFilteredDynamicModsForItem(pickedItemDb.Id, botEquipBlacklist.Equipment);
|
||||||
pickedItemDb.Id,
|
|
||||||
botEquipBlacklist.Equipment
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemIsOnGenerateModBlacklist =
|
var itemIsOnGenerateModBlacklist =
|
||||||
settings.GenerateModsBlacklist != null
|
settings.GenerateModsBlacklist != null && settings.GenerateModsBlacklist.Contains(pickedItemDb.Id);
|
||||||
&& settings.GenerateModsBlacklist.Contains(pickedItemDb.Id);
|
|
||||||
// Does item have slots for sub-mods to be inserted into
|
// Does item have slots for sub-mods to be inserted into
|
||||||
if (
|
if (pickedItemDb.Properties?.Slots is not null && pickedItemDb.Properties.Slots.Any() && !itemIsOnGenerateModBlacklist)
|
||||||
pickedItemDb.Properties?.Slots is not null
|
|
||||||
&& pickedItemDb.Properties.Slots.Any()
|
|
||||||
&& !itemIsOnGenerateModBlacklist
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var childItemsToAdd = botEquipmentModGenerator.GenerateModsForEquipment(
|
var childItemsToAdd = botEquipmentModGenerator.GenerateModsForEquipment(
|
||||||
[item],
|
[item],
|
||||||
@@ -667,18 +604,14 @@ public class BotInventoryGenerator(
|
|||||||
return modsForSlot;
|
return modsForSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
var filteredMods = modsForSlot
|
var filteredMods = modsForSlot.Where(mod => !blacklistedMods.Contains(mod)).ToHashSet();
|
||||||
.Where(mod => !blacklistedMods.Contains(mod))
|
|
||||||
.ToHashSet();
|
|
||||||
if (filteredMods.Any())
|
if (filteredMods.Any())
|
||||||
{
|
{
|
||||||
// There's at least one tpl remaining, send it
|
// There's at least one tpl remaining, send it
|
||||||
return filteredMods;
|
return filteredMods;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warning(
|
logger.Warning($"Filtering: '{modSlot}' resulted in 0 mods. Reverting to original set for slot");
|
||||||
$"Filtering: '{modSlot}' resulted in 0 mods. Reverting to original set for slot"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Return original
|
// Return original
|
||||||
return modsForSlot;
|
return modsForSlot;
|
||||||
@@ -712,9 +645,7 @@ public class BotInventoryGenerator(
|
|||||||
foreach (var desiredWeapons in weaponSlotsToFill)
|
foreach (var desiredWeapons in weaponSlotsToFill)
|
||||||
// Add weapon to bot if true and bot json has something to put into the slot
|
// Add weapon to bot if true and bot json has something to put into the slot
|
||||||
{
|
{
|
||||||
if (
|
if (desiredWeapons.ShouldSpawn && templateInventory.Equipment[desiredWeapons.Slot].Any())
|
||||||
desiredWeapons.ShouldSpawn && templateInventory.Equipment[desiredWeapons.Slot].Any()
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
AddWeaponAndMagazinesToInventory(
|
AddWeaponAndMagazinesToInventory(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -738,31 +669,19 @@ public class BotInventoryGenerator(
|
|||||||
/// <returns>What slots bot should have weapons generated for</returns>
|
/// <returns>What slots bot should have weapons generated for</returns>
|
||||||
public IEnumerable<DesiredWeapons> GetDesiredWeaponsForBot(Chances equipmentChances)
|
public IEnumerable<DesiredWeapons> GetDesiredWeaponsForBot(Chances equipmentChances)
|
||||||
{
|
{
|
||||||
var shouldSpawnPrimary = randomUtil.GetChance100(
|
var shouldSpawnPrimary = randomUtil.GetChance100(equipmentChances.EquipmentChances["FirstPrimaryWeapon"]);
|
||||||
equipmentChances.EquipmentChances["FirstPrimaryWeapon"]
|
|
||||||
);
|
|
||||||
return
|
return
|
||||||
[
|
[
|
||||||
new DesiredWeapons
|
new DesiredWeapons { Slot = EquipmentSlots.FirstPrimaryWeapon, ShouldSpawn = shouldSpawnPrimary },
|
||||||
{
|
|
||||||
Slot = EquipmentSlots.FirstPrimaryWeapon,
|
|
||||||
ShouldSpawn = shouldSpawnPrimary,
|
|
||||||
},
|
|
||||||
new DesiredWeapons
|
new DesiredWeapons
|
||||||
{
|
{
|
||||||
Slot = EquipmentSlots.SecondPrimaryWeapon,
|
Slot = EquipmentSlots.SecondPrimaryWeapon,
|
||||||
ShouldSpawn =
|
ShouldSpawn = shouldSpawnPrimary && randomUtil.GetChance100(equipmentChances.EquipmentChances["SecondPrimaryWeapon"]),
|
||||||
shouldSpawnPrimary
|
|
||||||
&& randomUtil.GetChance100(
|
|
||||||
equipmentChances.EquipmentChances["SecondPrimaryWeapon"]
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
new DesiredWeapons
|
new DesiredWeapons
|
||||||
{
|
{
|
||||||
Slot = EquipmentSlots.Holster,
|
Slot = EquipmentSlots.Holster,
|
||||||
ShouldSpawn =
|
ShouldSpawn = !shouldSpawnPrimary || randomUtil.GetChance100(equipmentChances.EquipmentChances["Holster"]), // No primary = force pistol
|
||||||
!shouldSpawnPrimary
|
|
||||||
|| randomUtil.GetChance100(equipmentChances.EquipmentChances["Holster"]), // No primary = force pistol
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -804,12 +723,7 @@ public class BotInventoryGenerator(
|
|||||||
|
|
||||||
botInventory.Items.AddRange(generatedWeapon.Weapon);
|
botInventory.Items.AddRange(generatedWeapon.Weapon);
|
||||||
|
|
||||||
botWeaponGenerator.AddExtraMagazinesToInventory(
|
botWeaponGenerator.AddExtraMagazinesToInventory(generatedWeapon, itemGenerationWeights.Items.Magazines, botInventory, botRole);
|
||||||
generatedWeapon,
|
|
||||||
itemGenerationWeights.Items.Magazines,
|
|
||||||
botInventory,
|
|
||||||
botRole
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Generators;
|
namespace SPTarkov.Server.Core.Generators;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class BotLevelGenerator(
|
public class BotLevelGenerator(ISptLogger<BotLevelGenerator> logger, RandomUtil randomUtil, DatabaseService databaseService)
|
||||||
ISptLogger<BotLevelGenerator> logger,
|
|
||||||
RandomUtil randomUtil,
|
|
||||||
DatabaseService databaseService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return a randomised bot level and exp value
|
/// Return a randomised bot level and exp value
|
||||||
@@ -24,11 +20,7 @@ public class BotLevelGenerator(
|
|||||||
/// <param name="botGenerationDetails">Details to help generate a bot</param>
|
/// <param name="botGenerationDetails">Details to help generate a bot</param>
|
||||||
/// <param name="bot">Bot the level is being generated for</param>
|
/// <param name="bot">Bot the level is being generated for</param>
|
||||||
/// <returns>IRandomisedBotLevelResult object</returns>
|
/// <returns>IRandomisedBotLevelResult object</returns>
|
||||||
public RandomisedBotLevelResult GenerateBotLevel(
|
public RandomisedBotLevelResult GenerateBotLevel(MinMax<int> levelDetails, BotGenerationDetails botGenerationDetails, BotBase bot)
|
||||||
MinMax<int> levelDetails,
|
|
||||||
BotGenerationDetails botGenerationDetails,
|
|
||||||
BotBase bot
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!botGenerationDetails.IsPmc)
|
if (!botGenerationDetails.IsPmc)
|
||||||
{
|
{
|
||||||
@@ -36,18 +28,11 @@ public class BotLevelGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var expTable = databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
|
var expTable = databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
|
||||||
var botLevelRange = GetRelativePmcBotLevelRange(
|
var botLevelRange = GetRelativePmcBotLevelRange(botGenerationDetails, levelDetails, expTable.Length);
|
||||||
botGenerationDetails,
|
|
||||||
levelDetails,
|
|
||||||
expTable.Length
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get random level based on the exp table.
|
// Get random level based on the exp table.
|
||||||
var exp = 0;
|
var exp = 0;
|
||||||
var level = int.Parse(
|
var level = int.Parse(ChooseBotLevel(botLevelRange.Min, botLevelRange.Max, 1, 1.15).ToString(CultureInfo.InvariantCulture)); // TODO - nasty double to string to int conversion
|
||||||
ChooseBotLevel(botLevelRange.Min, botLevelRange.Max, 1, 1.15)
|
|
||||||
.ToString(CultureInfo.InvariantCulture)
|
|
||||||
); // TODO - nasty double to string to int conversion
|
|
||||||
for (var i = 0; i < level; i++)
|
for (var i = 0; i < level; i++)
|
||||||
{
|
{
|
||||||
exp += expTable[i].Experience;
|
exp += expTable[i].Experience;
|
||||||
|
|||||||
@@ -51,11 +51,7 @@ public class BotLootGenerator(
|
|||||||
limitsForBotDict[limit.Key] = 0;
|
limitsForBotDict[limit.Key] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ItemSpawnLimitSettings
|
return new ItemSpawnLimitSettings { CurrentLimits = limitsForBotDict, GlobalLimits = GetItemSpawnLimitsForBotType(botRole) };
|
||||||
{
|
|
||||||
CurrentLimits = limitsForBotDict,
|
|
||||||
GlobalLimits = GetItemSpawnLimitsForBotType(botRole),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -95,20 +91,14 @@ public class BotLootGenerator(
|
|||||||
|| itemCounts.Grenades.Weights is null
|
|| itemCounts.Grenades.Weights is null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("bot-unable_to_generate_bot_loot", botRole));
|
||||||
serverLocalisationService.GetText("bot-unable_to_generate_bot_loot", botRole)
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var backpackLootCount = weightedRandomHelper.GetWeightedValue(
|
var backpackLootCount = weightedRandomHelper.GetWeightedValue(itemCounts.BackpackLoot.Weights);
|
||||||
itemCounts.BackpackLoot.Weights
|
|
||||||
);
|
|
||||||
var pocketLootCount = weightedRandomHelper.GetWeightedValue(itemCounts.PocketLoot.Weights);
|
var pocketLootCount = weightedRandomHelper.GetWeightedValue(itemCounts.PocketLoot.Weights);
|
||||||
var vestLootCount = weightedRandomHelper.GetWeightedValue(itemCounts.VestLoot.Weights);
|
var vestLootCount = weightedRandomHelper.GetWeightedValue(itemCounts.VestLoot.Weights);
|
||||||
var specialLootItemCount = weightedRandomHelper.GetWeightedValue(
|
var specialLootItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.SpecialItems.Weights);
|
||||||
itemCounts.SpecialItems.Weights
|
|
||||||
);
|
|
||||||
var healingItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Healing.Weights);
|
var healingItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Healing.Weights);
|
||||||
var drugItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Drugs.Weights);
|
var drugItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Drugs.Weights);
|
||||||
var foodItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Food.Weights);
|
var foodItemCount = weightedRandomHelper.GetWeightedValue(itemCounts.Food.Weights);
|
||||||
@@ -142,12 +132,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Special items
|
// Special items
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Special, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.Special,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
specialLootItemCount,
|
specialLootItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -158,12 +143,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Healing items / Meds
|
// Healing items / Meds
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.HealingItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.HealingItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
healingItemCount,
|
healingItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -176,12 +156,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Drugs
|
// Drugs
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.DrugItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.DrugItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
drugItemCount,
|
drugItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -194,12 +169,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Food
|
// Food
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.FoodItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.FoodItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
foodItemCount,
|
foodItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -212,12 +182,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Drink
|
// Drink
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.DrinkItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.DrinkItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
drinkItemCount,
|
drinkItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -230,12 +195,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Currency
|
// Currency
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.CurrencyItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.CurrencyItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
currencyItemCount,
|
currencyItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -248,12 +208,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Stims
|
// Stims
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.StimItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.StimItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
stimItemCount,
|
stimItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -266,12 +221,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Grenades
|
// Grenades
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.GrenadeItems, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.GrenadeItems,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
[EquipmentSlots.Pockets, EquipmentSlots.TacticalVest], // Can't use containersBotHasEquipped as we don't want grenades added to backpack
|
[EquipmentSlots.Pockets, EquipmentSlots.TacticalVest], // Can't use containersBotHasEquipped as we don't want grenades added to backpack
|
||||||
grenadeCount,
|
grenadeCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -304,20 +254,11 @@ public class BotLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var backpackLootRoubleTotal = isPmc
|
var backpackLootRoubleTotal = isPmc
|
||||||
? _pmcConfig.LootSettings.Backpack.GetRoubleValue(
|
? _pmcConfig.LootSettings.Backpack.GetRoubleValue(botLevel, botGenerationDetails.Location)
|
||||||
botLevel,
|
|
||||||
botGenerationDetails.Location
|
|
||||||
)
|
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Backpack, botJsonTemplate, itemPriceLimits?.Backpack),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.Backpack,
|
|
||||||
botJsonTemplate,
|
|
||||||
itemPriceLimits?.Backpack
|
|
||||||
),
|
|
||||||
[EquipmentSlots.Backpack],
|
[EquipmentSlots.Backpack],
|
||||||
backpackLootCount,
|
backpackLootCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -329,22 +270,14 @@ public class BotLootGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var vestLootRoubleTotal = isPmc
|
var vestLootRoubleTotal = isPmc ? _pmcConfig.LootSettings.Vest.GetRoubleValue(botLevel, botGenerationDetails.Location) : 0;
|
||||||
? _pmcConfig.LootSettings.Vest.GetRoubleValue(botLevel, botGenerationDetails.Location)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
// TacticalVest - generate loot if they have one
|
// TacticalVest - generate loot if they have one
|
||||||
if (containersBotHasAvailable.Contains(EquipmentSlots.TacticalVest))
|
if (containersBotHasAvailable.Contains(EquipmentSlots.TacticalVest))
|
||||||
// Vest
|
// Vest
|
||||||
{
|
{
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Vest, botJsonTemplate, itemPriceLimits?.Vest),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.Vest,
|
|
||||||
botJsonTemplate,
|
|
||||||
itemPriceLimits?.Vest
|
|
||||||
),
|
|
||||||
[EquipmentSlots.TacticalVest],
|
[EquipmentSlots.TacticalVest],
|
||||||
vestLootCount,
|
vestLootCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -356,19 +289,11 @@ public class BotLootGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pocketLootRoubleTotal = isPmc
|
var pocketLootRoubleTotal = isPmc ? _pmcConfig.LootSettings.Pocket.GetRoubleValue(botLevel, botGenerationDetails.Location) : 0;
|
||||||
? _pmcConfig.LootSettings.Pocket.GetRoubleValue(botLevel, botGenerationDetails.Location)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
// Pockets
|
// Pockets
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Pocket, botJsonTemplate, itemPriceLimits?.Pocket),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.Pocket,
|
|
||||||
botJsonTemplate,
|
|
||||||
itemPriceLimits?.Pocket
|
|
||||||
),
|
|
||||||
[EquipmentSlots.Pockets],
|
[EquipmentSlots.Pockets],
|
||||||
pocketLootCount,
|
pocketLootCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -385,12 +310,7 @@ public class BotLootGenerator(
|
|||||||
if (!isPmc || (isPmc && _pmcConfig.AddSecureContainerLootFromBotConfig))
|
if (!isPmc || (isPmc && _pmcConfig.AddSecureContainerLootFromBotConfig))
|
||||||
{
|
{
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
botLootCacheService.GetLootFromCache(
|
botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Secure, botJsonTemplate),
|
||||||
botRole,
|
|
||||||
isPmc,
|
|
||||||
LootCacheType.Secure,
|
|
||||||
botJsonTemplate
|
|
||||||
),
|
|
||||||
[EquipmentSlots.SecuredContainer],
|
[EquipmentSlots.SecuredContainer],
|
||||||
50,
|
50,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -423,17 +343,11 @@ public class BotLootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="botInventory">Bot to check</param>
|
/// <param name="botInventory">Bot to check</param>
|
||||||
/// <returns>Array of available slots</returns>
|
/// <returns>Array of available slots</returns>
|
||||||
protected HashSet<EquipmentSlots> GetAvailableContainersBotCanStoreItemsIn(
|
protected HashSet<EquipmentSlots> GetAvailableContainersBotCanStoreItemsIn(BotBaseInventory botInventory)
|
||||||
BotBaseInventory botInventory
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
HashSet<EquipmentSlots> result = [EquipmentSlots.Pockets];
|
HashSet<EquipmentSlots> result = [EquipmentSlots.Pockets];
|
||||||
|
|
||||||
if (
|
if ((botInventory.Items ?? []).Any(item => item.SlotId == nameof(EquipmentSlots.TacticalVest)))
|
||||||
(botInventory.Items ?? []).Any(item =>
|
|
||||||
item.SlotId == nameof(EquipmentSlots.TacticalVest)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
result.Add(EquipmentSlots.TacticalVest);
|
result.Add(EquipmentSlots.TacticalVest);
|
||||||
}
|
}
|
||||||
@@ -467,10 +381,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// AFAK
|
// AFAK
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
new Dictionary<MongoId, double>
|
new Dictionary<MongoId, double> { { ItemTpl.MEDKIT_AFAK_TACTICAL_INDIVIDUAL_FIRST_AID_KIT, 1 } },
|
||||||
{
|
|
||||||
{ ItemTpl.MEDKIT_AFAK_TACTICAL_INDIVIDUAL_FIRST_AID_KIT, 1 },
|
|
||||||
},
|
|
||||||
[EquipmentSlots.SecuredContainer],
|
[EquipmentSlots.SecuredContainer],
|
||||||
10,
|
10,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -527,17 +438,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning($"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}");
|
||||||
$"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}"
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (itemSpawnLimits is not null && ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
|
||||||
itemSpawnLimits is not null
|
|
||||||
&& ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Remove item from pool to prevent it being picked again
|
// Remove item from pool to prevent it being picked again
|
||||||
pool.Remove(weightedItemTpl);
|
pool.Remove(weightedItemTpl);
|
||||||
@@ -553,19 +459,14 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
Id = newRootItemId,
|
Id = newRootItemId,
|
||||||
Template = itemToAddTemplate?.Id ?? MongoId.Empty(),
|
Template = itemToAddTemplate?.Id ?? MongoId.Empty(),
|
||||||
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(
|
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(itemToAddTemplate, botRole),
|
||||||
itemToAddTemplate,
|
|
||||||
botRole
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Is Simple-Wallet / WZ wallet
|
// Is Simple-Wallet / WZ wallet
|
||||||
if (_botConfig.WalletLoot.WalletTplPool.Contains(weightedItemTpl))
|
if (_botConfig.WalletLoot.WalletTplPool.Contains(weightedItemTpl))
|
||||||
{
|
{
|
||||||
var addCurrencyToWallet = randomUtil.GetChance100(
|
var addCurrencyToWallet = randomUtil.GetChance100(_botConfig.WalletLoot.ChancePercent);
|
||||||
_botConfig.WalletLoot.ChancePercent
|
|
||||||
);
|
|
||||||
if (addCurrencyToWallet)
|
if (addCurrencyToWallet)
|
||||||
{
|
{
|
||||||
// Create the currency items we want to add to wallet
|
// Create the currency items we want to add to wallet
|
||||||
@@ -584,12 +485,7 @@ public class BotLootGenerator(
|
|||||||
// Add each currency to wallet
|
// Add each currency to wallet
|
||||||
foreach (var itemToAdd in itemsToAdd)
|
foreach (var itemToAdd in itemsToAdd)
|
||||||
{
|
{
|
||||||
inventoryHelper.PlaceItemInContainer(
|
inventoryHelper.PlaceItemInContainer(containerGrid, itemToAdd, itemWithChildrenToAdd[0].Id, "main");
|
||||||
containerGrid,
|
|
||||||
itemToAdd,
|
|
||||||
itemWithChildrenToAdd[0].Id,
|
|
||||||
"main"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itemWithChildrenToAdd.AddRange(itemsToAdd.SelectMany(x => x));
|
itemWithChildrenToAdd.AddRange(itemsToAdd.SelectMany(x => x));
|
||||||
@@ -618,9 +514,7 @@ public class BotLootGenerator(
|
|||||||
// Bot has no container to put item in, exit
|
// Bot has no container to put item in, exit
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Unable to add: {totalItemCount} items to bot as it lacks a container to include them");
|
||||||
$"Unable to add: {totalItemCount} items to bot as it lacks a container to include them"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -670,24 +564,17 @@ public class BotLootGenerator(
|
|||||||
List<List<Item>> result = [];
|
List<List<Item>> result = [];
|
||||||
|
|
||||||
// Choose how many stacks of currency will be added to wallet
|
// Choose how many stacks of currency will be added to wallet
|
||||||
var itemCount = randomUtil.GetInt(
|
var itemCount = randomUtil.GetInt(_botConfig.WalletLoot.ItemCount.Min, _botConfig.WalletLoot.ItemCount.Max);
|
||||||
_botConfig.WalletLoot.ItemCount.Min,
|
|
||||||
_botConfig.WalletLoot.ItemCount.Max
|
|
||||||
);
|
|
||||||
for (var index = 0; index < itemCount; index++)
|
for (var index = 0; index < itemCount; index++)
|
||||||
{
|
{
|
||||||
// Choose the size of the currency stack - default is 5k, 10k, 15k, 20k, 25k
|
// Choose the size of the currency stack - default is 5k, 10k, 15k, 20k, 25k
|
||||||
var chosenStackCount = weightedRandomHelper.GetWeightedValue(
|
var chosenStackCount = weightedRandomHelper.GetWeightedValue(_botConfig.WalletLoot.StackSizeWeight);
|
||||||
_botConfig.WalletLoot.StackSizeWeight
|
|
||||||
);
|
|
||||||
List<Item> items =
|
List<Item> items =
|
||||||
[
|
[
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
Template = weightedRandomHelper.GetWeightedValue(
|
Template = weightedRandomHelper.GetWeightedValue(_botConfig.WalletLoot.CurrencyWeight),
|
||||||
_botConfig.WalletLoot.CurrencyWeight
|
|
||||||
),
|
|
||||||
ParentId = walletId,
|
ParentId = walletId,
|
||||||
Upd = new Upd { StackObjectsCount = int.Parse(chosenStackCount) },
|
Upd = new Upd { StackObjectsCount = int.Parse(chosenStackCount) },
|
||||||
},
|
},
|
||||||
@@ -705,12 +592,7 @@ public class BotLootGenerator(
|
|||||||
/// <param name="itemToAddChildrenTo">Item to add children to</param>
|
/// <param name="itemToAddChildrenTo">Item to add children to</param>
|
||||||
/// <param name="isPmc">Is the item being generated for a pmc (affects money/ammo stack sizes)</param>
|
/// <param name="isPmc">Is the item being generated for a pmc (affects money/ammo stack sizes)</param>
|
||||||
/// <param name="botRole">role bot has that owns item</param>
|
/// <param name="botRole">role bot has that owns item</param>
|
||||||
public void AddRequiredChildItemsToParent(
|
public void AddRequiredChildItemsToParent(TemplateItem? itemToAddTemplate, List<Item> itemToAddChildrenTo, bool isPmc, string botRole)
|
||||||
TemplateItem? itemToAddTemplate,
|
|
||||||
List<Item> itemToAddChildrenTo,
|
|
||||||
bool isPmc,
|
|
||||||
string botRole
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Fill ammo box
|
// Fill ammo box
|
||||||
if (itemHelper.IsOfBaseclass(itemToAddTemplate.Id, BaseClasses.AMMO_BOX))
|
if (itemHelper.IsOfBaseclass(itemToAddTemplate.Id, BaseClasses.AMMO_BOX))
|
||||||
@@ -792,9 +674,7 @@ public class BotLootGenerator(
|
|||||||
var weaponRootItem = generatedWeapon.Weapon?.FirstOrDefault();
|
var weaponRootItem = generatedWeapon.Weapon?.FirstOrDefault();
|
||||||
if (weaponRootItem is null)
|
if (weaponRootItem is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Generated null loose weapon: {chosenWeaponType} for: {botRole} level: {botLevel}, skipping");
|
||||||
$"Generated null loose weapon: {chosenWeaponType} for: {botRole} level: {botLevel}, skipping"
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -811,9 +691,7 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Failed to add additional weapon: {weaponRootItem.Id} to bot backpack, reason: {result.ToString()}");
|
||||||
$"Failed to add additional weapon: {weaponRootItem.Id} to bot backpack, reason: {result.ToString()}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -826,11 +704,7 @@ public class BotLootGenerator(
|
|||||||
/// <param name="botRole">Bot type</param>
|
/// <param name="botRole">Bot type</param>
|
||||||
/// <param name="itemSpawnLimits"></param>
|
/// <param name="itemSpawnLimits"></param>
|
||||||
/// <returns>true if item has reached spawn limit</returns>
|
/// <returns>true if item has reached spawn limit</returns>
|
||||||
protected bool ItemHasReachedSpawnLimit(
|
protected bool ItemHasReachedSpawnLimit(TemplateItem? itemTemplate, string botRole, ItemSpawnLimitSettings? itemSpawnLimits)
|
||||||
TemplateItem? itemTemplate,
|
|
||||||
string botRole,
|
|
||||||
ItemSpawnLimitSettings? itemSpawnLimits
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// PMCs and scavs have different sections of bot config for spawn limits
|
// PMCs and scavs have different sections of bot config for spawn limits
|
||||||
if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0)
|
if (itemSpawnLimits is not null && itemSpawnLimits.GlobalLimits?.Count == 0)
|
||||||
@@ -861,10 +735,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Check if over limit
|
// Check if over limit
|
||||||
var currentLimitCount = itemSpawnLimits.CurrentLimits[idToCheckFor.Value];
|
var currentLimitCount = itemSpawnLimits.CurrentLimits[idToCheckFor.Value];
|
||||||
if (
|
if (itemSpawnLimits.CurrentLimits[idToCheckFor.Value] > itemSpawnLimits.GlobalLimits[idToCheckFor.Value])
|
||||||
itemSpawnLimits.CurrentLimits[idToCheckFor.Value]
|
|
||||||
> itemSpawnLimits.GlobalLimits[idToCheckFor.Value]
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
|
// Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
|
||||||
if (currentLimitCount > currentLimitCount * 10)
|
if (currentLimitCount > currentLimitCount * 10)
|
||||||
@@ -911,9 +782,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
itemHelper.AddUpdObjectToItem(moneyItem);
|
itemHelper.AddUpdObjectToItem(moneyItem);
|
||||||
|
|
||||||
moneyItem.Upd.StackObjectsCount = int.Parse(
|
moneyItem.Upd.StackObjectsCount = int.Parse(weightedRandomHelper.GetWeightedValue(currencyWeight));
|
||||||
weightedRandomHelper.GetWeightedValue(currencyWeight)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -948,12 +817,7 @@ public class BotLootGenerator(
|
|||||||
return _botConfig.ItemSpawnLimits[botRole.ToLowerInvariant()];
|
return _botConfig.ItemSpawnLimits[botRole.ToLowerInvariant()];
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("bot-unable_to_find_spawn_limits_fallback_to_defaults", botRole));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-unable_to_find_spawn_limits_fallback_to_defaults",
|
|
||||||
botRole
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -964,10 +828,7 @@ public class BotLootGenerator(
|
|||||||
/// <param name="itemTemplate">item we want to look for in spawn limits</param>
|
/// <param name="itemTemplate">item we want to look for in spawn limits</param>
|
||||||
/// <param name="spawnLimits">Limits to check for item</param>
|
/// <param name="spawnLimits">Limits to check for item</param>
|
||||||
/// <returns>id as string, otherwise undefined</returns>
|
/// <returns>id as string, otherwise undefined</returns>
|
||||||
public MongoId? GetMatchingIdFromSpawnLimits(
|
public MongoId? GetMatchingIdFromSpawnLimits(TemplateItem itemTemplate, Dictionary<MongoId, double> spawnLimits)
|
||||||
TemplateItem itemTemplate,
|
|
||||||
Dictionary<MongoId, double> spawnLimits
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (spawnLimits.ContainsKey(itemTemplate.Id))
|
if (spawnLimits.ContainsKey(itemTemplate.Id))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
protected const string _modMagazineSlotId = "mod_magazine";
|
protected const string _modMagazineSlotId = "mod_magazine";
|
||||||
protected readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
|
protected readonly BotConfig _botConfig = configServer.GetConfig<BotConfig>();
|
||||||
protected readonly IEnumerable<IInventoryMagGen> _inventoryMagGenComponents = MagGenSetUp(
|
protected readonly IEnumerable<IInventoryMagGen> _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents);
|
||||||
inventoryMagGenComponents
|
|
||||||
);
|
|
||||||
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
||||||
protected readonly RepairConfig _repairConfig = configServer.GetConfig<RepairConfig>();
|
protected readonly RepairConfig _repairConfig = configServer.GetConfig<RepairConfig>();
|
||||||
|
|
||||||
@@ -93,10 +91,7 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="equipmentSlot">Primary/secondary/holster</param>
|
/// <param name="equipmentSlot">Primary/secondary/holster</param>
|
||||||
/// <param name="botTemplateInventory">e.g. assault.json</param>
|
/// <param name="botTemplateInventory">e.g. assault.json</param>
|
||||||
/// <returns>Weapon template</returns>
|
/// <returns>Weapon template</returns>
|
||||||
public MongoId PickWeightedWeaponTemplateFromPool(
|
public MongoId PickWeightedWeaponTemplateFromPool(string equipmentSlot, BotTypeInventory botTemplateInventory)
|
||||||
string equipmentSlot,
|
|
||||||
BotTypeInventory botTemplateInventory
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse(equipmentSlot, out EquipmentSlots key))
|
if (!Enum.TryParse(equipmentSlot, out EquipmentSlots key))
|
||||||
{
|
{
|
||||||
@@ -146,23 +141,14 @@ public class BotWeaponGenerator(
|
|||||||
// Find ammo to use when filling magazines/chamber
|
// Find ammo to use when filling magazines/chamber
|
||||||
if (botTemplateInventory.Ammo is null)
|
if (botTemplateInventory.Ammo is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-no_ammo_found_in_bot_json", botRole));
|
||||||
serverLocalisationService.GetText("bot-no_ammo_found_in_bot_json", botRole)
|
|
||||||
);
|
|
||||||
logger.Error(serverLocalisationService.GetText("bot-generation_failed"));
|
logger.Error(serverLocalisationService.GetText("bot-generation_failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var ammoTpl = GetWeightedCompatibleAmmo(botTemplateInventory.Ammo, weaponItemTemplate);
|
var ammoTpl = GetWeightedCompatibleAmmo(botTemplateInventory.Ammo, weaponItemTemplate);
|
||||||
|
|
||||||
// Create with just base weapon item
|
// Create with just base weapon item
|
||||||
var weaponWithModsArray = ConstructWeaponBaseList(
|
var weaponWithModsArray = ConstructWeaponBaseList(weaponTpl, weaponParentId, slotName, weaponItemTemplate, botRole).ToList();
|
||||||
weaponTpl,
|
|
||||||
weaponParentId,
|
|
||||||
slotName,
|
|
||||||
weaponItemTemplate,
|
|
||||||
botRole
|
|
||||||
)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Chance to add randomised weapon enhancement
|
// Chance to add randomised weapon enhancement
|
||||||
if (isPmc && randomUtil.GetChance100(_pmcConfig.WeaponHasEnhancementChancePercent))
|
if (isPmc && randomUtil.GetChance100(_pmcConfig.WeaponHasEnhancementChancePercent))
|
||||||
@@ -198,28 +184,17 @@ public class BotWeaponGenerator(
|
|||||||
WeaponStats = new WeaponStats(),
|
WeaponStats = new WeaponStats(),
|
||||||
ConflictingItemTpls = [],
|
ConflictingItemTpls = [],
|
||||||
};
|
};
|
||||||
weaponWithModsArray = botEquipmentModGenerator.GenerateModsForWeapon(
|
weaponWithModsArray = botEquipmentModGenerator.GenerateModsForWeapon(sessionId, generateWeaponModsRequest);
|
||||||
sessionId,
|
|
||||||
generateWeaponModsRequest
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use weapon preset from globals.json if weapon isn't valid
|
// Use weapon preset from globals.json if weapon isn't valid
|
||||||
if (!IsWeaponValid(weaponWithModsArray, botRole))
|
if (!IsWeaponValid(weaponWithModsArray, botRole))
|
||||||
// Weapon is bad, fall back to weapons preset
|
// Weapon is bad, fall back to weapons preset
|
||||||
{
|
{
|
||||||
weaponWithModsArray = GetPresetWeaponMods(
|
weaponWithModsArray = GetPresetWeaponMods(weaponTpl, slotName, weaponParentId, weaponItemTemplate, botRole);
|
||||||
weaponTpl,
|
|
||||||
slotName,
|
|
||||||
weaponParentId,
|
|
||||||
weaponItemTemplate,
|
|
||||||
botRole
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempList = cloner.Clone(
|
var tempList = cloner.Clone(weaponWithModsArray.Where(item => item.SlotId == _modMagazineSlotId));
|
||||||
weaponWithModsArray.Where(item => item.SlotId == _modMagazineSlotId)
|
|
||||||
);
|
|
||||||
// Fill existing magazines to full and sync ammo type
|
// Fill existing magazines to full and sync ammo type
|
||||||
foreach (var magazine in tempList)
|
foreach (var magazine in tempList)
|
||||||
{
|
{
|
||||||
@@ -229,16 +204,11 @@ public class BotWeaponGenerator(
|
|||||||
// Add cartridge(s) to gun chamber(s)
|
// Add cartridge(s) to gun chamber(s)
|
||||||
if (
|
if (
|
||||||
(weaponItemTemplate.Properties?.Chambers).Any()
|
(weaponItemTemplate.Properties?.Chambers).Any()
|
||||||
&& weaponItemTemplate
|
&& weaponItemTemplate.Properties.Chambers.FirstOrDefault().Props.Filters.FirstOrDefault().Filter.Contains(ammoTpl)
|
||||||
.Properties.Chambers.FirstOrDefault()
|
|
||||||
.Props.Filters.FirstOrDefault()
|
|
||||||
.Filter.Contains(ammoTpl)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001
|
// Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001
|
||||||
var chamberSlotNames = weaponItemTemplate.Properties.Chambers.Select(chamberSlot =>
|
var chamberSlotNames = weaponItemTemplate.Properties.Chambers.Select(chamberSlot => chamberSlot.Name);
|
||||||
chamberSlot.Name
|
|
||||||
);
|
|
||||||
AddCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames.ToList());
|
AddCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,11 +244,7 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponWithModsList">Weapon and mods</param>
|
/// <param name="weaponWithModsList">Weapon and mods</param>
|
||||||
/// <param name="ammoTemplate">Cartridge to add to weapon</param>
|
/// <param name="ammoTemplate">Cartridge to add to weapon</param>
|
||||||
/// <param name="chamberSlotIds">Name of slots to create or add ammo to</param>
|
/// <param name="chamberSlotIds">Name of slots to create or add ammo to</param>
|
||||||
protected void AddCartridgeToChamber(
|
protected void AddCartridgeToChamber(List<Item> weaponWithModsList, MongoId ammoTemplate, IEnumerable<string> chamberSlotIds)
|
||||||
List<Item> weaponWithModsList,
|
|
||||||
MongoId ammoTemplate,
|
|
||||||
IEnumerable<string> chamberSlotIds
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var slotId in chamberSlotIds)
|
foreach (var slotId in chamberSlotIds)
|
||||||
{
|
{
|
||||||
@@ -332,10 +298,7 @@ public class BotWeaponGenerator(
|
|||||||
Template = weaponTemplate,
|
Template = weaponTemplate,
|
||||||
ParentId = weaponParentId,
|
ParentId = weaponParentId,
|
||||||
SlotId = equipmentSlot,
|
SlotId = equipmentSlot,
|
||||||
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(
|
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(weaponItemTemplate, botRole),
|
||||||
weaponItemTemplate,
|
|
||||||
botRole
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -359,10 +322,7 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
// Invalid weapon generated, fallback to preset
|
// Invalid weapon generated, fallback to preset
|
||||||
logger.Warning(
|
logger.Warning(
|
||||||
serverLocalisationService.GetText(
|
serverLocalisationService.GetText("bot-weapon_generated_incorrect_using_default", $"{weaponTemplate} - {itemTemplate.Name}")
|
||||||
"bot-weapon_generated_incorrect_using_default",
|
|
||||||
$"{weaponTemplate} - {itemTemplate.Name}"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
List<Item> weaponMods = [];
|
List<Item> weaponMods = [];
|
||||||
|
|
||||||
@@ -383,18 +343,13 @@ public class BotWeaponGenerator(
|
|||||||
var parentItem = preset.Items[0];
|
var parentItem = preset.Items[0];
|
||||||
parentItem.ParentId = weaponParentId;
|
parentItem.ParentId = weaponParentId;
|
||||||
parentItem.SlotId = equipmentSlot;
|
parentItem.SlotId = equipmentSlot;
|
||||||
parentItem.Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(
|
parentItem.Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(itemTemplate, botRole);
|
||||||
itemTemplate,
|
|
||||||
botRole
|
|
||||||
);
|
|
||||||
preset.Items[0] = parentItem;
|
preset.Items[0] = parentItem;
|
||||||
weaponMods.AddRange(preset.Items);
|
weaponMods.AddRange(preset.Items);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-missing_weapon_preset", weaponTemplate));
|
||||||
serverLocalisationService.GetText("bot-missing_weapon_preset", weaponTemplate)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return weaponMods;
|
return weaponMods;
|
||||||
@@ -417,16 +372,10 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over required slots in db item, check mod exists for that slot
|
// Iterate over required slots in db item, check mod exists for that slot
|
||||||
foreach (
|
foreach (var modSlotTemplate in modTemplate.Properties.Slots?.Where(slot => slot.Required.GetValueOrDefault(false)) ?? [])
|
||||||
var modSlotTemplate in modTemplate.Properties.Slots?.Where(slot =>
|
|
||||||
slot.Required.GetValueOrDefault(false)
|
|
||||||
) ?? []
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var slotName = modSlotTemplate.Name;
|
var slotName = modSlotTemplate.Name;
|
||||||
var hasWeaponSlotItem = weaponItemList.Any(weaponItem =>
|
var hasWeaponSlotItem = weaponItemList.Any(weaponItem => weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName);
|
||||||
weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName
|
|
||||||
);
|
|
||||||
if (!hasWeaponSlotItem)
|
if (!hasWeaponSlotItem)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(
|
||||||
@@ -467,18 +416,12 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
var weaponAndMods = generatedWeaponResult.Weapon;
|
var weaponAndMods = generatedWeaponResult.Weapon;
|
||||||
var weaponTemplate = generatedWeaponResult.WeaponTemplate;
|
var weaponTemplate = generatedWeaponResult.WeaponTemplate;
|
||||||
var magazineTpl = GetMagazineTemplateFromWeaponTemplate(
|
var magazineTpl = GetMagazineTemplateFromWeaponTemplate(weaponAndMods, weaponTemplate, botRole);
|
||||||
weaponAndMods,
|
|
||||||
weaponTemplate,
|
|
||||||
botRole
|
|
||||||
);
|
|
||||||
|
|
||||||
var magTemplate = itemHelper.GetItem(magazineTpl.Value).Value;
|
var magTemplate = itemHelper.GetItem(magazineTpl.Value).Value;
|
||||||
if (magTemplate is null)
|
if (magTemplate is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-unable_to_find_magazine_item", magazineTpl));
|
||||||
serverLocalisationService.GetText("bot-unable_to_find_magazine_item", magazineTpl)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -487,36 +430,20 @@ public class BotWeaponGenerator(
|
|||||||
var ammoTemplate = itemHelper.GetItem(generatedWeaponResult.ChosenAmmoTemplate);
|
var ammoTemplate = itemHelper.GetItem(generatedWeaponResult.ChosenAmmoTemplate);
|
||||||
if (!ammoTemplate.Key)
|
if (!ammoTemplate.Key)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-unable_to_find_ammo_item", generatedWeaponResult.ChosenAmmoTemplate));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-unable_to_find_ammo_item",
|
|
||||||
generatedWeaponResult.ChosenAmmoTemplate
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has an UBGL
|
// Has an UBGL
|
||||||
if (
|
if (generatedWeaponResult.ChosenUbglAmmoTemplate is not null && !generatedWeaponResult.ChosenUbglAmmoTemplate.Value.IsEmpty())
|
||||||
generatedWeaponResult.ChosenUbglAmmoTemplate is not null
|
|
||||||
&& !generatedWeaponResult.ChosenUbglAmmoTemplate.Value.IsEmpty()
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
AddUbglGrenadesToBotInventory(weaponAndMods, generatedWeaponResult, inventory);
|
AddUbglGrenadesToBotInventory(weaponAndMods, generatedWeaponResult, inventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
var inventoryMagGenModel = new InventoryMagGen(
|
var inventoryMagGenModel = new InventoryMagGen(magWeights, magTemplate, weaponTemplate, ammoTemplate.Value, inventory);
|
||||||
magWeights,
|
|
||||||
magTemplate,
|
|
||||||
weaponTemplate,
|
|
||||||
ammoTemplate.Value,
|
|
||||||
inventory
|
|
||||||
);
|
|
||||||
|
|
||||||
_inventoryMagGenComponents
|
_inventoryMagGenComponents.FirstOrDefault(v => v.CanHandleInventoryMagGen(inventoryMagGenModel)).Process(inventoryMagGenModel);
|
||||||
.FirstOrDefault(v => v.CanHandleInventoryMagGen(inventoryMagGenModel))
|
|
||||||
.Process(inventoryMagGenModel);
|
|
||||||
|
|
||||||
// Add x stacks of bullets to SecuredContainer (bots use a magic mag packing skill to reload instantly)
|
// Add x stacks of bullets to SecuredContainer (bots use a magic mag packing skill to reload instantly)
|
||||||
AddAmmoToSecureContainer(
|
AddAmmoToSecureContainer(
|
||||||
@@ -551,29 +478,14 @@ public class BotWeaponGenerator(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// get ammo template from db
|
// get ammo template from db
|
||||||
var ubglAmmoDbTemplate = itemHelper
|
var ubglAmmoDbTemplate = itemHelper.GetItem(generatedWeaponResult.ChosenUbglAmmoTemplate.Value).Value;
|
||||||
.GetItem(generatedWeaponResult.ChosenUbglAmmoTemplate.Value)
|
|
||||||
.Value;
|
|
||||||
|
|
||||||
// Add greandes to bot inventory
|
// Add greandes to bot inventory
|
||||||
var ubglAmmoGenModel = new InventoryMagGen(
|
var ubglAmmoGenModel = new InventoryMagGen(ubglMinMax, ubglDbTemplate, ubglDbTemplate, ubglAmmoDbTemplate, inventory);
|
||||||
ubglMinMax,
|
_inventoryMagGenComponents.FirstOrDefault(v => v.CanHandleInventoryMagGen(ubglAmmoGenModel)).Process(ubglAmmoGenModel);
|
||||||
ubglDbTemplate,
|
|
||||||
ubglDbTemplate,
|
|
||||||
ubglAmmoDbTemplate,
|
|
||||||
inventory
|
|
||||||
);
|
|
||||||
_inventoryMagGenComponents
|
|
||||||
.FirstOrDefault(v => v.CanHandleInventoryMagGen(ubglAmmoGenModel))
|
|
||||||
.Process(ubglAmmoGenModel);
|
|
||||||
|
|
||||||
// Store extra grenades in secure container
|
// Store extra grenades in secure container
|
||||||
AddAmmoToSecureContainer(
|
AddAmmoToSecureContainer(5, generatedWeaponResult.ChosenUbglAmmoTemplate.Value, 20, inventory);
|
||||||
5,
|
|
||||||
generatedWeaponResult.ChosenUbglAmmoTemplate.Value,
|
|
||||||
20,
|
|
||||||
inventory
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -583,12 +495,7 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="ammoTpl">Ammo type to add.</param>
|
/// <param name="ammoTpl">Ammo type to add.</param>
|
||||||
/// <param name="stackSize">Size of the ammo stack to add.</param>
|
/// <param name="stackSize">Size of the ammo stack to add.</param>
|
||||||
/// <param name="inventory">Player inventory.</param>
|
/// <param name="inventory">Player inventory.</param>
|
||||||
protected void AddAmmoToSecureContainer(
|
protected void AddAmmoToSecureContainer(int stackCount, MongoId ammoTpl, int stackSize, BotBaseInventory inventory)
|
||||||
int stackCount,
|
|
||||||
MongoId ammoTpl,
|
|
||||||
int stackSize,
|
|
||||||
BotBaseInventory inventory
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var container = new HashSet<EquipmentSlots> { EquipmentSlots.SecuredContainer };
|
var container = new HashSet<EquipmentSlots> { EquipmentSlots.SecuredContainer };
|
||||||
for (var i = 0; i < stackCount; i++)
|
for (var i = 0; i < stackCount; i++)
|
||||||
@@ -618,11 +525,7 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponTemplate">Weapon to get magazine template for.</param>
|
/// <param name="weaponTemplate">Weapon to get magazine template for.</param>
|
||||||
/// <param name="botRole">The bot type we are getting the magazine for.</param>
|
/// <param name="botRole">The bot type we are getting the magazine for.</param>
|
||||||
/// <returns>Magazine template string.</returns>
|
/// <returns>Magazine template string.</returns>
|
||||||
protected MongoId? GetMagazineTemplateFromWeaponTemplate(
|
protected MongoId? GetMagazineTemplateFromWeaponTemplate(IEnumerable<Item> weaponMods, TemplateItem weaponTemplate, string botRole)
|
||||||
IEnumerable<Item> weaponMods,
|
|
||||||
TemplateItem weaponTemplate,
|
|
||||||
string botRole
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var magazine = weaponMods.FirstOrDefault(m => m.SlotId == _modMagazineSlotId);
|
var magazine = weaponMods.FirstOrDefault(m => m.SlotId == _modMagazineSlotId);
|
||||||
if (magazine is null)
|
if (magazine is null)
|
||||||
@@ -667,16 +570,10 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="cartridgePool">Dictionary of all cartridges keyed by type e.g. Caliber556x45NATO</param>
|
/// <param name="cartridgePool">Dictionary of all cartridges keyed by type e.g. Caliber556x45NATO</param>
|
||||||
/// <param name="weaponTemplate">Weapon details from database we want to pick ammo for</param>
|
/// <param name="weaponTemplate">Weapon details from database we want to pick ammo for</param>
|
||||||
/// <returns>Ammo template that works with the desired gun</returns>
|
/// <returns>Ammo template that works with the desired gun</returns>
|
||||||
protected MongoId GetWeightedCompatibleAmmo(
|
protected MongoId GetWeightedCompatibleAmmo(Dictionary<string, Dictionary<MongoId, double>> cartridgePool, TemplateItem weaponTemplate)
|
||||||
Dictionary<string, Dictionary<MongoId, double>> cartridgePool,
|
|
||||||
TemplateItem weaponTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var desiredCaliber = GetWeaponCaliber(weaponTemplate);
|
var desiredCaliber = GetWeaponCaliber(weaponTemplate);
|
||||||
if (
|
if (!cartridgePool.TryGetValue(desiredCaliber, out var cartridgePoolForWeapon) || cartridgePoolForWeapon?.Count == 0)
|
||||||
!cartridgePool.TryGetValue(desiredCaliber, out var cartridgePoolForWeapon)
|
|
||||||
|| cartridgePoolForWeapon?.Count == 0
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
@@ -699,9 +596,7 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get cartridges the weapons first chamber allow
|
// Get cartridges the weapons first chamber allow
|
||||||
var compatibleCartridgesInTemplate = GetCompatibleCartridgesFromWeaponTemplate(
|
var compatibleCartridgesInTemplate = GetCompatibleCartridgesFromWeaponTemplate(weaponTemplate);
|
||||||
weaponTemplate
|
|
||||||
);
|
|
||||||
if (compatibleCartridgesInTemplate.Count == 0)
|
if (compatibleCartridgesInTemplate.Count == 0)
|
||||||
// No chamber data found in weapon, send default
|
// No chamber data found in weapon, send default
|
||||||
{
|
{
|
||||||
@@ -722,9 +617,7 @@ public class BotWeaponGenerator(
|
|||||||
if (!compatibleCartridges.Any())
|
if (!compatibleCartridges.Any())
|
||||||
{
|
{
|
||||||
// Get cartridges from the weapons first magazine in filters
|
// Get cartridges from the weapons first magazine in filters
|
||||||
var compatibleCartridgesInMagazine = GetCompatibleCartridgesFromMagazineTemplate(
|
var compatibleCartridgesInMagazine = GetCompatibleCartridgesFromMagazineTemplate(weaponTemplate);
|
||||||
weaponTemplate
|
|
||||||
);
|
|
||||||
if (compatibleCartridgesInMagazine.Count == 0)
|
if (compatibleCartridgesInMagazine.Count == 0)
|
||||||
{
|
{
|
||||||
// No compatible cartridges found in magazine, use default
|
// No compatible cartridges found in magazine, use default
|
||||||
@@ -732,9 +625,7 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the caliber data from the first compatible round in the magazine
|
// Get the caliber data from the first compatible round in the magazine
|
||||||
var magazineCaliberData = itemHelper
|
var magazineCaliberData = itemHelper.GetItem(compatibleCartridgesInMagazine.FirstOrDefault()).Value.Properties.Caliber;
|
||||||
.GetItem(compatibleCartridgesInMagazine.FirstOrDefault())
|
|
||||||
.Value.Properties.Caliber;
|
|
||||||
cartridgePoolForWeapon = cartridgePool[magazineCaliberData];
|
cartridgePoolForWeapon = cartridgePool[magazineCaliberData];
|
||||||
|
|
||||||
foreach (var cartridgeKvP in cartridgePoolForWeapon)
|
foreach (var cartridgeKvP in cartridgePoolForWeapon)
|
||||||
@@ -760,16 +651,11 @@ public class BotWeaponGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="weaponTemplate">Weapon db template to get cartridges for</param>
|
/// <param name="weaponTemplate">Weapon db template to get cartridges for</param>
|
||||||
/// <returns>List of cartridge tpls</returns>
|
/// <returns>List of cartridge tpls</returns>
|
||||||
protected HashSet<MongoId> GetCompatibleCartridgesFromWeaponTemplate(
|
protected HashSet<MongoId> GetCompatibleCartridgesFromWeaponTemplate(TemplateItem weaponTemplate)
|
||||||
TemplateItem weaponTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
||||||
|
|
||||||
var cartridges = weaponTemplate
|
var cartridges = weaponTemplate.Properties?.Chambers?.FirstOrDefault()?.Props?.Filters?.First().Filter;
|
||||||
.Properties?.Chambers?.FirstOrDefault()
|
|
||||||
?.Props?.Filters?.First()
|
|
||||||
.Filter;
|
|
||||||
if (cartridges is not null)
|
if (cartridges is not null)
|
||||||
{
|
{
|
||||||
return cartridges;
|
return cartridges;
|
||||||
@@ -785,24 +671,19 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponTemplate">Weapon db template to get magazine cartridges for</param>
|
/// <param name="weaponTemplate">Weapon db template to get magazine cartridges for</param>
|
||||||
/// <returns>Hashset of cartridge tpls</returns>
|
/// <returns>Hashset of cartridge tpls</returns>
|
||||||
/// <exception cref="ArgumentNullException">Thrown when weaponTemplate is null.</exception>
|
/// <exception cref="ArgumentNullException">Thrown when weaponTemplate is null.</exception>
|
||||||
protected HashSet<MongoId> GetCompatibleCartridgesFromMagazineTemplate(
|
protected HashSet<MongoId> GetCompatibleCartridgesFromMagazineTemplate(TemplateItem weaponTemplate)
|
||||||
TemplateItem weaponTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
||||||
|
|
||||||
// Get the first magazine's template from the weapon
|
// Get the first magazine's template from the weapon
|
||||||
var magazineSlot = weaponTemplate.Properties.Slots?.FirstOrDefault(slot =>
|
var magazineSlot = weaponTemplate.Properties.Slots?.FirstOrDefault(slot => slot.Name == "mod_magazine");
|
||||||
slot.Name == "mod_magazine"
|
|
||||||
);
|
|
||||||
if (magazineSlot is null)
|
if (magazineSlot is null)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var magazineTemplate = itemHelper.GetItem(
|
var magazineTemplate = itemHelper.GetItem(
|
||||||
magazineSlot.Props?.Filters.FirstOrDefault()?.Filter?.FirstOrDefault()
|
magazineSlot.Props?.Filters.FirstOrDefault()?.Filter?.FirstOrDefault() ?? new MongoId(null)
|
||||||
?? new MongoId(null)
|
|
||||||
);
|
);
|
||||||
if (!magazineTemplate.Key)
|
if (!magazineTemplate.Key)
|
||||||
{
|
{
|
||||||
@@ -811,14 +692,8 @@ public class BotWeaponGenerator(
|
|||||||
|
|
||||||
// Try to get cartridges from slots array first, if none found, try Cartridges array
|
// Try to get cartridges from slots array first, if none found, try Cartridges array
|
||||||
var cartridges =
|
var cartridges =
|
||||||
magazineTemplate
|
magazineTemplate.Value.Properties.Slots.FirstOrDefault()?.Props?.Filters.FirstOrDefault()?.Filter
|
||||||
.Value.Properties.Slots.FirstOrDefault()
|
?? magazineTemplate.Value.Properties.Cartridges.FirstOrDefault()?.Props?.Filters.FirstOrDefault()?.Filter;
|
||||||
?.Props?.Filters.FirstOrDefault()
|
|
||||||
?.Filter
|
|
||||||
?? magazineTemplate
|
|
||||||
.Value.Properties.Cartridges.FirstOrDefault()
|
|
||||||
?.Props?.Filters.FirstOrDefault()
|
|
||||||
?.Filter;
|
|
||||||
|
|
||||||
return cartridges ?? [];
|
return cartridges ?? [];
|
||||||
}
|
}
|
||||||
@@ -838,18 +713,13 @@ public class BotWeaponGenerator(
|
|||||||
if (!string.IsNullOrEmpty(weaponTemplate.Properties.AmmoCaliber))
|
if (!string.IsNullOrEmpty(weaponTemplate.Properties.AmmoCaliber))
|
||||||
// 9x18pmm has a typo, should be Caliber9x18PM
|
// 9x18pmm has a typo, should be Caliber9x18PM
|
||||||
{
|
{
|
||||||
return weaponTemplate.Properties.AmmoCaliber == "Caliber9x18PMM"
|
return weaponTemplate.Properties.AmmoCaliber == "Caliber9x18PMM" ? "Caliber9x18PM" : weaponTemplate.Properties.AmmoCaliber;
|
||||||
? "Caliber9x18PM"
|
|
||||||
: weaponTemplate.Properties.AmmoCaliber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(weaponTemplate.Properties.LinkedWeapon))
|
if (!string.IsNullOrEmpty(weaponTemplate.Properties.LinkedWeapon))
|
||||||
{
|
{
|
||||||
var ammoInChamber = itemHelper.GetItem(
|
var ammoInChamber = itemHelper.GetItem(
|
||||||
weaponTemplate
|
weaponTemplate.Properties.Chambers.First().Props.Filters.First().Filter.FirstOrDefault()
|
||||||
.Properties.Chambers.First()
|
|
||||||
.Props.Filters.First()
|
|
||||||
.Filter.FirstOrDefault()
|
|
||||||
);
|
);
|
||||||
return !ammoInChamber.Key ? null : ammoInChamber.Value.Properties.Caliber;
|
return !ammoInChamber.Key ? null : ammoInChamber.Value.Properties.Caliber;
|
||||||
}
|
}
|
||||||
@@ -863,21 +733,12 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponMods">Weapon with children</param>
|
/// <param name="weaponMods">Weapon with children</param>
|
||||||
/// <param name="magazine">Magazine item</param>
|
/// <param name="magazine">Magazine item</param>
|
||||||
/// <param name="cartridgeTemplate">Cartridge to insert into magazine</param>
|
/// <param name="cartridgeTemplate">Cartridge to insert into magazine</param>
|
||||||
protected void FillExistingMagazines(
|
protected void FillExistingMagazines(List<Item> weaponMods, Item magazine, MongoId cartridgeTemplate)
|
||||||
List<Item> weaponMods,
|
|
||||||
Item magazine,
|
|
||||||
MongoId cartridgeTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var magazineTemplate = itemHelper.GetItem(magazine.Template).Value;
|
var magazineTemplate = itemHelper.GetItem(magazine.Template).Value;
|
||||||
if (magazineTemplate is null)
|
if (magazineTemplate is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("bot-unable_to_find_magazine_item", magazine.Template));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"bot-unable_to_find_magazine_item",
|
|
||||||
magazine.Template
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -894,12 +755,7 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddOrUpdateMagazinesChildWithAmmo(
|
AddOrUpdateMagazinesChildWithAmmo(weaponMods, magazine, cartridgeTemplate, magazineTemplate);
|
||||||
weaponMods,
|
|
||||||
magazine,
|
|
||||||
cartridgeTemplate,
|
|
||||||
magazineTemplate
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,9 +793,7 @@ public class BotWeaponGenerator(
|
|||||||
TemplateItem magazineTemplate
|
TemplateItem magazineTemplate
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var magazineCartridgeChildItem = weaponWithMods.FirstOrDefault(m =>
|
var magazineCartridgeChildItem = weaponWithMods.FirstOrDefault(m => m.ParentId == magazine.Id && m.SlotId == "cartridges");
|
||||||
m.ParentId == magazine.Id && m.SlotId == "cartridges"
|
|
||||||
);
|
|
||||||
if (magazineCartridgeChildItem is not null)
|
if (magazineCartridgeChildItem is not null)
|
||||||
{
|
{
|
||||||
// Delete the existing cartridge object and create fresh below
|
// Delete the existing cartridge object and create fresh below
|
||||||
@@ -950,20 +804,13 @@ public class BotWeaponGenerator(
|
|||||||
List<Item> magazineWithCartridges = [magazine];
|
List<Item> magazineWithCartridges = [magazine];
|
||||||
|
|
||||||
// Add cartridges as children to above mag array
|
// Add cartridges as children to above mag array
|
||||||
itemHelper.FillMagazineWithCartridge(
|
itemHelper.FillMagazineWithCartridge(magazineWithCartridges, magazineTemplate, chosenAmmoTpl, 1);
|
||||||
magazineWithCartridges,
|
|
||||||
magazineTemplate,
|
|
||||||
chosenAmmoTpl,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
// Replace existing magazine with above array of mag + cartridge stacks
|
// Replace existing magazine with above array of mag + cartridge stacks
|
||||||
var magazineIndex = weaponWithMods.FindIndex(i => i.Id == magazine.Id); // magazineWithCartridges
|
var magazineIndex = weaponWithMods.FindIndex(i => i.Id == magazine.Id); // magazineWithCartridges
|
||||||
if (magazineIndex == -1)
|
if (magazineIndex == -1)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error($"Unable to add cartridges: {chosenAmmoTpl} to magazine: {magazine.Id} as none found");
|
||||||
$"Unable to add cartridges: {chosenAmmoTpl} to magazine: {magazine.Id} as none found"
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -980,20 +827,12 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponMods">Weapon mods to find and update camora mod(s) from</param>
|
/// <param name="weaponMods">Weapon mods to find and update camora mod(s) from</param>
|
||||||
/// <param name="magazineId">Magazine id to find and add to</param>
|
/// <param name="magazineId">Magazine id to find and add to</param>
|
||||||
/// <param name="ammoTpl">Ammo template id to hydrate with</param>
|
/// <param name="ammoTpl">Ammo template id to hydrate with</param>
|
||||||
protected void FillCamorasWithAmmo(
|
protected void FillCamorasWithAmmo(IEnumerable<Item> weaponMods, MongoId magazineId, MongoId ammoTpl)
|
||||||
IEnumerable<Item> weaponMods,
|
|
||||||
MongoId magazineId,
|
|
||||||
MongoId ammoTpl
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// for CylinderMagazine we exchange the ammo in the "camoras".
|
// for CylinderMagazine we exchange the ammo in the "camoras".
|
||||||
// This might not be necessary since we already filled the camoras with a random whitelisted and compatible ammo type,
|
// This might not be necessary since we already filled the camoras with a random whitelisted and compatible ammo type,
|
||||||
// but I'm not sure whether this is also used elsewhere
|
// but I'm not sure whether this is also used elsewhere
|
||||||
var camoras = weaponMods
|
var camoras = weaponMods.Where(x => x.ParentId == magazineId && x.SlotId.StartsWith("camora", StringComparison.Ordinal)).ToList();
|
||||||
.Where(x =>
|
|
||||||
x.ParentId == magazineId && x.SlotId.StartsWith("camora", StringComparison.Ordinal)
|
|
||||||
)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (camoras.Count == 0)
|
if (camoras.Count == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,10 +65,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
// Item base type blacklisted
|
// Item base type blacklisted
|
||||||
if (traderConfig.Fence.Blacklist.Count > 0)
|
if (traderConfig.Fence.Blacklist.Count > 0)
|
||||||
{
|
{
|
||||||
if (
|
if (traderConfig.Fence.Blacklist.Contains(itemId) || itemHelper.IsOfBaseclasses(itemId, traderConfig.Fence.Blacklist))
|
||||||
traderConfig.Fence.Blacklist.Contains(itemId)
|
|
||||||
|| itemHelper.IsOfBaseclasses(itemId, traderConfig.Fence.Blacklist)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -131,9 +128,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
// Create barter scheme (price)
|
// Create barter scheme (price)
|
||||||
var barterSchemeToAdd = new BarterScheme
|
var barterSchemeToAdd = new BarterScheme
|
||||||
{
|
{
|
||||||
Count = Math.Round(
|
Count = Math.Round((double)fenceService.GetItemPrice(itemId, itemWithChildrenToAdd)),
|
||||||
(double)fenceService.GetItemPrice(itemId, itemWithChildrenToAdd)
|
|
||||||
),
|
|
||||||
Template = Money.ROUBLES,
|
Template = Money.ROUBLES,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -155,11 +150,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
foreach (var defaultPreset in defaultPresets)
|
foreach (var defaultPreset in defaultPresets)
|
||||||
{
|
{
|
||||||
// Skip presets we've already added
|
// Skip presets we've already added
|
||||||
if (
|
if (baseFenceAssort.Items.Any(item => item.Upd != null && item.Upd.SptPresetId == defaultPreset.Id))
|
||||||
baseFenceAssort.Items.Any(item =>
|
|
||||||
item.Upd != null && item.Upd.SptPresetId == defaultPreset.Id
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -168,9 +159,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
var itemAndChildren = _cloner.Clone(defaultPreset.Items).ReplaceIDs();
|
var itemAndChildren = _cloner.Clone(defaultPreset.Items).ReplaceIDs();
|
||||||
|
|
||||||
// Find root item and add some properties to it
|
// Find root item and add some properties to it
|
||||||
var rootItem = itemAndChildren.FirstOrDefault(item =>
|
var rootItem = itemAndChildren.FirstOrDefault(item => string.IsNullOrEmpty(item.ParentId));
|
||||||
string.IsNullOrEmpty(item.ParentId)
|
|
||||||
);
|
|
||||||
rootItem.ParentId = "hideout";
|
rootItem.ParentId = "hideout";
|
||||||
rootItem.SlotId = "hideout";
|
rootItem.SlotId = "hideout";
|
||||||
rootItem.Upd = new Upd
|
rootItem.Upd = new Upd
|
||||||
@@ -191,11 +180,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
[
|
[
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
new BarterScheme
|
new BarterScheme { Template = Money.ROUBLES, Count = Math.Round(price * itemQualityModifier) },
|
||||||
{
|
|
||||||
Template = Money.ROUBLES,
|
|
||||||
Count = Math.Round(price * itemQualityModifier),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -213,12 +198,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
var ammoPenetrationPower = GetAmmoPenetrationPower(rootItemDb);
|
var ammoPenetrationPower = GetAmmoPenetrationPower(rootItemDb);
|
||||||
if (ammoPenetrationPower == null)
|
if (ammoPenetrationPower == null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("fence-unable_to_get_ammo_penetration_value", rootItemDb.Id));
|
||||||
localisationService.GetText(
|
|
||||||
"fence-unable_to_get_ammo_penetration_value",
|
|
||||||
rootItemDb.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,18 +215,13 @@ public class FenceBaseAssortGenerator(
|
|||||||
if (itemHelper.IsOfBaseclass(rootItemDb.Id, BaseClasses.AMMO_BOX))
|
if (itemHelper.IsOfBaseclass(rootItemDb.Id, BaseClasses.AMMO_BOX))
|
||||||
{
|
{
|
||||||
// Get the cartridge tpl found inside ammo box
|
// Get the cartridge tpl found inside ammo box
|
||||||
var cartridgeTplInBox = rootItemDb
|
var cartridgeTplInBox = rootItemDb.Properties.StackSlots.First().Props.Filters.First().Filter.FirstOrDefault();
|
||||||
.Properties.StackSlots.First()
|
|
||||||
.Props.Filters.First()
|
|
||||||
.Filter.FirstOrDefault();
|
|
||||||
|
|
||||||
// Look up cartridge tpl in db
|
// Look up cartridge tpl in db
|
||||||
var ammoItemDb = itemHelper.GetItem(cartridgeTplInBox);
|
var ammoItemDb = itemHelper.GetItem(cartridgeTplInBox);
|
||||||
if (!ammoItemDb.Key)
|
if (!ammoItemDb.Key)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("fence-ammo_not_found_in_db", cartridgeTplInBox));
|
||||||
localisationService.GetText("fence-ammo_not_found_in_db", cartridgeTplInBox)
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,25 +246,20 @@ public class FenceBaseAssortGenerator(
|
|||||||
protected void AddChildrenToArmorModSlots(List<Item> armor, TemplateItem itemDbDetails)
|
protected void AddChildrenToArmorModSlots(List<Item> armor, TemplateItem itemDbDetails)
|
||||||
{
|
{
|
||||||
// Armor has no mods, make no additions
|
// Armor has no mods, make no additions
|
||||||
var hasMods =
|
var hasMods = itemDbDetails.Properties?.Slots is not null && itemDbDetails.Properties.Slots.Any();
|
||||||
itemDbDetails.Properties?.Slots is not null && itemDbDetails.Properties.Slots.Any();
|
|
||||||
if (!hasMods)
|
if (!hasMods)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for and add required soft inserts to armors
|
// Check for and add required soft inserts to armors
|
||||||
var requiredSlots = itemDbDetails
|
var requiredSlots = itemDbDetails.Properties.Slots.Where(slot => slot.Required ?? false).ToList();
|
||||||
.Properties.Slots.Where(slot => slot.Required ?? false)
|
|
||||||
.ToList();
|
|
||||||
var hasRequiredSlots = requiredSlots.Count > 0;
|
var hasRequiredSlots = requiredSlots.Count > 0;
|
||||||
if (hasRequiredSlots)
|
if (hasRequiredSlots)
|
||||||
{
|
{
|
||||||
foreach (var requiredSlot in requiredSlots)
|
foreach (var requiredSlot in requiredSlots)
|
||||||
{
|
{
|
||||||
var modItemDbDetails = itemHelper
|
var modItemDbDetails = itemHelper.GetItem(requiredSlot.Props.Filters.First().Plate.Value).Value;
|
||||||
.GetItem(requiredSlot.Props.Filters.First().Plate.Value)
|
|
||||||
.Value;
|
|
||||||
var plateTpl = requiredSlot.Props.Filters.First().Plate; // `Plate` property appears to be the 'default' item for slot
|
var plateTpl = requiredSlot.Props.Filters.First().Plate; // `Plate` property appears to be the 'default' item for slot
|
||||||
if (plateTpl is null || plateTpl.Value.IsEmpty())
|
if (plateTpl is null || plateTpl.Value.IsEmpty())
|
||||||
// Some bsg plate properties are empty, skip mod
|
// Some bsg plate properties are empty, skip mod
|
||||||
@@ -318,9 +288,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for and add plate items
|
// Check for and add plate items
|
||||||
var plateSlots = itemDbDetails
|
var plateSlots = itemDbDetails.Properties.Slots.Where(slot => itemHelper.IsRemovablePlateSlot(slot.Name)).ToList();
|
||||||
.Properties.Slots.Where(slot => itemHelper.IsRemovablePlateSlot(slot.Name))
|
|
||||||
.ToList();
|
|
||||||
if (plateSlots.Count > 0)
|
if (plateSlots.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var plateSlot in plateSlots)
|
foreach (var plateSlot in plateSlots)
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ public class LocationLootGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly LocationConfig _locationConfig = _configServer.GetConfig<LocationConfig>();
|
protected readonly LocationConfig _locationConfig = _configServer.GetConfig<LocationConfig>();
|
||||||
protected readonly SeasonalEventConfig _seasonalEventConfig =
|
protected readonly SeasonalEventConfig _seasonalEventConfig = _configServer.GetConfig<SeasonalEventConfig>();
|
||||||
_configServer.GetConfig<SeasonalEventConfig>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate Loot for provided location ()
|
/// Generate Loot for provided location ()
|
||||||
@@ -68,9 +67,7 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create containers with loot
|
// Create containers with loot
|
||||||
result.AddRange(
|
result.AddRange(GenerateStaticContainers(locationId.ToLowerInvariant(), staticAmmoDistClone));
|
||||||
GenerateStaticContainers(locationId.ToLowerInvariant(), staticAmmoDistClone)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add dynamic loot to output loot
|
// Add dynamic loot to output loot
|
||||||
var dynamicSpawnPoints = GenerateDynamicLoot(
|
var dynamicSpawnPoints = GenerateDynamicLoot(
|
||||||
@@ -82,15 +79,8 @@ public class LocationLootGenerator(
|
|||||||
// Merge dynamic spawns into result
|
// Merge dynamic spawns into result
|
||||||
result.AddRange(dynamicSpawnPoints);
|
result.AddRange(dynamicSpawnPoints);
|
||||||
|
|
||||||
_logger.Success(
|
_logger.Success(_serverLocalisationService.GetText("location-dynamic_items_spawned_success", dynamicSpawnPoints.Count));
|
||||||
_serverLocalisationService.GetText(
|
_logger.Success(_serverLocalisationService.GetText("location-generated_success", locationId));
|
||||||
"location-dynamic_items_spawned_success",
|
|
||||||
dynamicSpawnPoints.Count
|
|
||||||
)
|
|
||||||
);
|
|
||||||
_logger.Success(
|
|
||||||
_serverLocalisationService.GetText("location-generated_success", locationId)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Clean up tracker
|
// Clean up tracker
|
||||||
counterTrackerHelper.Clear();
|
counterTrackerHelper.Clear();
|
||||||
@@ -115,40 +105,23 @@ public class LocationLootGenerator(
|
|||||||
var staticWeaponsOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticWeapons);
|
var staticWeaponsOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticWeapons);
|
||||||
if (staticWeaponsOnMapClone is null)
|
if (staticWeaponsOnMapClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("location-unable_to_find_static_weapon_for_map", locationId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-unable_to_find_static_weapon_for_map",
|
|
||||||
locationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add mounted weapons to output loot
|
// Add mounted weapons to output loot
|
||||||
result.AddRange(staticWeaponsOnMapClone);
|
result.AddRange(staticWeaponsOnMapClone);
|
||||||
|
|
||||||
var allStaticContainersOnMapClone = _cloner.Clone(
|
var allStaticContainersOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticContainers);
|
||||||
mapData.StaticContainers.Value.StaticContainers
|
|
||||||
);
|
|
||||||
if (allStaticContainersOnMapClone is null)
|
if (allStaticContainersOnMapClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("location-unable_to_find_static_container_for_map", locationId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-unable_to_find_static_container_for_map",
|
|
||||||
locationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Containers that MUST be added to map (e.g. quest containers)
|
// Containers that MUST be added to map (e.g. quest containers)
|
||||||
var staticForcedOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticForced);
|
var staticForcedOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticForced);
|
||||||
if (staticForcedOnMapClone is null)
|
if (staticForcedOnMapClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("location-unable_to_find_forced_static_data_for_map", locationId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-unable_to_find_forced_static_data_for_map",
|
|
||||||
locationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove christmas items from loot data
|
// Remove christmas items from loot data
|
||||||
@@ -159,9 +132,7 @@ public class LocationLootGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var staticRandomisableContainersOnMap = GetRandomisableContainersOnMap(
|
var staticRandomisableContainersOnMap = GetRandomisableContainersOnMap(allStaticContainersOnMapClone);
|
||||||
allStaticContainersOnMapClone
|
|
||||||
);
|
|
||||||
|
|
||||||
// Keep track of static loot count
|
// Keep track of static loot count
|
||||||
var staticContainerCount = 0;
|
var staticContainerCount = 0;
|
||||||
@@ -174,13 +145,7 @@ public class LocationLootGenerator(
|
|||||||
// Add loot to guaranteed containers and add to result
|
// Add loot to guaranteed containers and add to result
|
||||||
foreach (
|
foreach (
|
||||||
var containerWithLoot in guaranteedContainers.Select(container =>
|
var containerWithLoot in guaranteedContainers.Select(container =>
|
||||||
AddLootToContainer(
|
AddLootToContainer(container, staticForcedOnMapClone, staticLootDist.Value, staticAmmoDist, locationId)
|
||||||
container,
|
|
||||||
staticForcedOnMapClone,
|
|
||||||
staticLootDist.Value,
|
|
||||||
staticAmmoDist,
|
|
||||||
locationId
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -226,21 +191,13 @@ public class LocationLootGenerator(
|
|||||||
// Group containers by their groupId
|
// Group containers by their groupId
|
||||||
if (mapData.Statics is null)
|
if (mapData.Statics is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("location-unable_to_generate_static_loot", locationId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-unable_to_generate_static_loot",
|
|
||||||
locationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each of the container groups, choose from the pool of containers, hydrate container with loot and add to result array
|
// For each of the container groups, choose from the pool of containers, hydrate container with loot and add to result array
|
||||||
var mapping = GetGroupIdToContainerMappings(
|
var mapping = GetGroupIdToContainerMappings(mapData.Statics, staticRandomisableContainersOnMap);
|
||||||
mapData.Statics,
|
|
||||||
staticRandomisableContainersOnMap
|
|
||||||
);
|
|
||||||
foreach (var (key, data) in mapping)
|
foreach (var (key, data) in mapping)
|
||||||
{
|
{
|
||||||
// Count chosen was 0, skip
|
// Count chosen was 0, skip
|
||||||
@@ -253,9 +210,7 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug($"Group: {key} has no containers with < 100 % spawn chance to choose from, skipping");
|
||||||
$"Group: {key} has no containers with < 100 % spawn chance to choose from, skipping"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -271,9 +226,7 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_randomUtil.GetChance100(containerIdsCopy[containerId.Key] * 100))
|
if (_randomUtil.GetChance100(containerIdsCopy[containerId.Key] * 100))
|
||||||
{
|
{
|
||||||
data.ContainerIdsWithProbability[containerId.Key] = containerIdsCopy[
|
data.ContainerIdsWithProbability[containerId.Key] = containerIdsCopy[containerId.Key];
|
||||||
containerId.Key
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,16 +245,14 @@ public class LocationLootGenerator(
|
|||||||
foreach (var chosenContainerId in chosenContainerIds)
|
foreach (var chosenContainerId in chosenContainerIds)
|
||||||
{
|
{
|
||||||
// Look up container object from full list of containers on map
|
// Look up container object from full list of containers on map
|
||||||
var containerObject = staticRandomisableContainersOnMap.FirstOrDefault(
|
var containerObject = staticRandomisableContainersOnMap.FirstOrDefault(staticContainer =>
|
||||||
staticContainer => staticContainer.Template.Id == chosenContainerId
|
staticContainer.Template.Id == chosenContainerId
|
||||||
);
|
);
|
||||||
if (containerObject is null)
|
if (containerObject is null)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug($"Container: {chosenContainerId} not found in staticRandomisableContainersOnMap, this is bad");
|
||||||
$"Container: {chosenContainerId} not found in staticRandomisableContainersOnMap, this is bad"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -323,12 +274,7 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
_logger.Success($"A total of: {staticLootItemCount} static items spawned");
|
_logger.Success($"A total of: {staticLootItemCount} static items spawned");
|
||||||
_logger.Success(
|
_logger.Success(_serverLocalisationService.GetText("location-containers_generated_success", staticContainerCount));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-containers_generated_success",
|
|
||||||
staticContainerCount
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -344,9 +290,7 @@ public class LocationLootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticContainers"></param>
|
/// <param name="staticContainers"></param>
|
||||||
/// <returns>StaticContainerData array</returns>
|
/// <returns>StaticContainerData array</returns>
|
||||||
protected IEnumerable<StaticContainerData> GetRandomisableContainersOnMap(
|
protected IEnumerable<StaticContainerData> GetRandomisableContainersOnMap(IEnumerable<StaticContainerData> staticContainers)
|
||||||
IEnumerable<StaticContainerData> staticContainers
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return staticContainers.Where(staticContainer =>
|
return staticContainers.Where(staticContainer =>
|
||||||
staticContainer.Probability != 1
|
staticContainer.Probability != 1
|
||||||
@@ -362,9 +306,7 @@ public class LocationLootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticContainersOnMap"></param>
|
/// <param name="staticContainersOnMap"></param>
|
||||||
/// <returns>IStaticContainerData array</returns>
|
/// <returns>IStaticContainerData array</returns>
|
||||||
protected IEnumerable<StaticContainerData> GetGuaranteedContainers(
|
protected IEnumerable<StaticContainerData> GetGuaranteedContainers(IEnumerable<StaticContainerData> staticContainersOnMap)
|
||||||
IEnumerable<StaticContainerData> staticContainersOnMap
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return staticContainersOnMap.Where(staticContainer =>
|
return staticContainersOnMap.Where(staticContainer =>
|
||||||
staticContainer.Probability == 1
|
staticContainer.Probability == 1
|
||||||
@@ -382,10 +324,7 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="groupId">Name of the group the containers are being collected for</param>
|
/// <param name="groupId">Name of the group the containers are being collected for</param>
|
||||||
/// <param name="containerData">Containers and probability values for a groupId</param>
|
/// <param name="containerData">Containers and probability values for a groupId</param>
|
||||||
/// <returns>List of chosen container Ids</returns>
|
/// <returns>List of chosen container Ids</returns>
|
||||||
protected List<string> GetContainersByProbability(
|
protected List<string> GetContainersByProbability(string groupId, ContainerGroupCount containerData)
|
||||||
string groupId,
|
|
||||||
ContainerGroupCount containerData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var chosenContainerIds = new List<string>();
|
var chosenContainerIds = new List<string>();
|
||||||
|
|
||||||
@@ -437,16 +376,12 @@ public class LocationLootGenerator(
|
|||||||
(int)
|
(int)
|
||||||
Math.Round(
|
Math.Round(
|
||||||
groupKvP.Value.MinContainers.Value
|
groupKvP.Value.MinContainers.Value
|
||||||
* _locationConfig
|
* _locationConfig.ContainerRandomisationSettings.ContainerGroupMinSizeMultiplier
|
||||||
.ContainerRandomisationSettings
|
|
||||||
.ContainerGroupMinSizeMultiplier
|
|
||||||
),
|
),
|
||||||
(int)
|
(int)
|
||||||
Math.Round(
|
Math.Round(
|
||||||
groupKvP.Value.MaxContainers.Value
|
groupKvP.Value.MaxContainers.Value
|
||||||
* _locationConfig
|
* _locationConfig.ContainerRandomisationSettings.ContainerGroupMaxSizeMultiplier
|
||||||
.ContainerRandomisationSettings
|
|
||||||
.ContainerGroupMaxSizeMultiplier
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@@ -456,29 +391,17 @@ public class LocationLootGenerator(
|
|||||||
// Likely bad BSG data, will be fixed...eventually, example of the groupIds: `NEED_TO_BE_FIXED1`,`NEED_TO_BE_FIXED_SE02`, `NEED_TO_BE_FIXED_NW_01`
|
// Likely bad BSG data, will be fixed...eventually, example of the groupIds: `NEED_TO_BE_FIXED1`,`NEED_TO_BE_FIXED_SE02`, `NEED_TO_BE_FIXED_NW_01`
|
||||||
mapping.Add(
|
mapping.Add(
|
||||||
string.Empty,
|
string.Empty,
|
||||||
new ContainerGroupCount
|
new ContainerGroupCount { ContainerIdsWithProbability = new Dictionary<string, double>(), ChosenCount = -1 }
|
||||||
{
|
|
||||||
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
|
||||||
ChosenCount = -1,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Iterate over all containers and add to group keyed by groupId
|
// Iterate over all containers and add to group keyed by groupId
|
||||||
// Containers without a group go into a group with empty key ""
|
// Containers without a group go into a group with empty key ""
|
||||||
foreach (var container in staticContainersOnMap)
|
foreach (var container in staticContainersOnMap)
|
||||||
{
|
{
|
||||||
if (
|
if (!staticContainerGroupData.Containers.TryGetValue(container.Template.Id, out var groupData))
|
||||||
!staticContainerGroupData.Containers.TryGetValue(
|
|
||||||
container.Template.Id,
|
|
||||||
out var groupData
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_serverLocalisationService.GetText(
|
_serverLocalisationService.GetText("location-unable_to_find_container_in_statics_json", container.Template.Id)
|
||||||
"location-unable_to_find_container_in_statics_json",
|
|
||||||
container.Template.Id
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -498,17 +421,9 @@ public class LocationLootGenerator(
|
|||||||
|
|
||||||
mapping.TryAdd(
|
mapping.TryAdd(
|
||||||
groupData.GroupId,
|
groupData.GroupId,
|
||||||
new ContainerGroupCount
|
new ContainerGroupCount { ChosenCount = 0d, ContainerIdsWithProbability = new Dictionary<string, double>() }
|
||||||
{
|
|
||||||
ChosenCount = 0d,
|
|
||||||
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
mapping[groupData.GroupId]
|
mapping[groupData.GroupId].ContainerIdsWithProbability.TryAdd(container.Template.Id, container.Probability.Value);
|
||||||
.ContainerIdsWithProbability.TryAdd(
|
|
||||||
container.Template.Id,
|
|
||||||
container.Probability.Value
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@@ -543,11 +458,7 @@ public class LocationLootGenerator(
|
|||||||
var containerMap = _itemHelper.GetContainerMapping(containerTpl);
|
var containerMap = _itemHelper.GetContainerMapping(containerTpl);
|
||||||
|
|
||||||
// Choose count of items to add to container
|
// Choose count of items to add to container
|
||||||
var itemCountToAdd = GetWeightedCountOfContainerItems(
|
var itemCountToAdd = GetWeightedCountOfContainerItems(containerTpl, staticLootDist, locationName);
|
||||||
containerTpl,
|
|
||||||
staticLootDist,
|
|
||||||
locationName
|
|
||||||
);
|
|
||||||
if (itemCountToAdd == 0)
|
if (itemCountToAdd == 0)
|
||||||
{
|
{
|
||||||
return containerClone;
|
return containerClone;
|
||||||
@@ -595,10 +506,7 @@ public class LocationLootGenerator(
|
|||||||
: chosenItemWithChildren.Items;
|
: chosenItemWithChildren.Items;
|
||||||
|
|
||||||
// look for open slot to put chosen item into
|
// look for open slot to put chosen item into
|
||||||
var result = containerMap.FindSlotForItem(
|
var result = containerMap.FindSlotForItem(chosenItemWithChildren.Width, chosenItemWithChildren.Height);
|
||||||
chosenItemWithChildren.Width,
|
|
||||||
chosenItemWithChildren.Height
|
|
||||||
);
|
|
||||||
if (!result.Success.GetValueOrDefault(false))
|
if (!result.Success.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
if (failedToFitAttemptCount > _locationConfig.FitLootIntoContainerAttempts)
|
if (failedToFitAttemptCount > _locationConfig.FitLootIntoContainerAttempts)
|
||||||
@@ -628,9 +536,7 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
X = result.X,
|
X = result.X,
|
||||||
Y = result.Y,
|
Y = result.Y,
|
||||||
R = result.Rotation.GetValueOrDefault(false)
|
R = result.Rotation.GetValueOrDefault(false) ? ItemRotation.Vertical : ItemRotation.Horizontal,
|
||||||
? ItemRotation.Vertical
|
|
||||||
: ItemRotation.Horizontal,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add loot to container before returning
|
// Add loot to container before returning
|
||||||
@@ -673,16 +579,11 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
// Add each count of items into array
|
// Add each count of items into array
|
||||||
itemCountArray.Add(
|
itemCountArray.Add(
|
||||||
new ProbabilityObject<int, float?>(
|
new ProbabilityObject<int, float?>(itemCountDistribution.Count.Value, itemCountDistribution.RelativeProbability.Value, null)
|
||||||
itemCountDistribution.Count.Value,
|
|
||||||
itemCountDistribution.RelativeProbability.Value,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)
|
return (int)Math.Round(GetStaticLootMultiplierForLocation(locationName) * itemCountArray.Draw()[0]);
|
||||||
Math.Round(GetStaticLootMultiplierForLocation(locationName) * itemCountArray.Draw()[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -705,12 +606,7 @@ public class LocationLootGenerator(
|
|||||||
var itemContainerDistribution = staticLootDist[containerTypeId]?.ItemDistribution;
|
var itemContainerDistribution = staticLootDist[containerTypeId]?.ItemDistribution;
|
||||||
if (itemContainerDistribution is null)
|
if (itemContainerDistribution is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("location-missing_item_distribution_data", containerTypeId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-missing_item_distribution_data",
|
|
||||||
containerTypeId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return itemDistribution;
|
return itemDistribution;
|
||||||
}
|
}
|
||||||
@@ -729,9 +625,7 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemDistribution.Add(
|
itemDistribution.Add(new ProbabilityObject<MongoId, float?>(icd.Tpl, icd.RelativeProbability.Value, null));
|
||||||
new ProbabilityObject<MongoId, float?>(icd.Tpl, icd.RelativeProbability.Value, null)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return itemDistribution;
|
return itemDistribution;
|
||||||
@@ -780,26 +674,17 @@ public class LocationLootGenerator(
|
|||||||
|
|
||||||
// Build the list of forced loot from both `SpawnpointsForced` and any point marked `IsAlwaysSpawn`
|
// Build the list of forced loot from both `SpawnpointsForced` and any point marked `IsAlwaysSpawn`
|
||||||
dynamicForcedSpawnPoints.AddRange(dynamicLootDist.SpawnpointsForced);
|
dynamicForcedSpawnPoints.AddRange(dynamicLootDist.SpawnpointsForced);
|
||||||
dynamicForcedSpawnPoints.AddRange(
|
dynamicForcedSpawnPoints.AddRange(dynamicLootDist.Spawnpoints.Where(point => point.Template.IsAlwaysSpawn.GetValueOrDefault()));
|
||||||
dynamicLootDist.Spawnpoints.Where(point =>
|
|
||||||
point.Template.IsAlwaysSpawn.GetValueOrDefault()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
loot.AddRange(GetForcedDynamicLoot(dynamicForcedSpawnPoints, locationName, staticAmmoDist));
|
loot.AddRange(GetForcedDynamicLoot(dynamicForcedSpawnPoints, locationName, staticAmmoDist));
|
||||||
|
|
||||||
// Draw from random distribution
|
// Draw from random distribution
|
||||||
var desiredSpawnPointCount = Math.Round(
|
var desiredSpawnPointCount = Math.Round(
|
||||||
GetLooseLootMultiplierForLocation(locationName)
|
GetLooseLootMultiplierForLocation(locationName)
|
||||||
* _randomUtil.GetNormallyDistributedRandomNumber(
|
* _randomUtil.GetNormallyDistributedRandomNumber(dynamicLootDist.SpawnpointCount.Mean, dynamicLootDist.SpawnpointCount.Std)
|
||||||
dynamicLootDist.SpawnpointCount.Mean,
|
|
||||||
dynamicLootDist.SpawnpointCount.Std
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var blacklistedSpawnPoints = _locationConfig.LooseLootBlacklist.GetValueOrDefault(
|
var blacklistedSpawnPoints = _locationConfig.LooseLootBlacklist.GetValueOrDefault(locationName);
|
||||||
locationName
|
|
||||||
);
|
|
||||||
|
|
||||||
// Init empty array to hold spawn points, letting us pick them pseudo-randomly
|
// Init empty array to hold spawn points, letting us pick them pseudo-randomly
|
||||||
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_cloner);
|
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_cloner);
|
||||||
@@ -834,13 +719,7 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
spawnPointArray.Add(
|
spawnPointArray.Add(new ProbabilityObject<string, Spawnpoint>(spawnPoint.Template.Id, spawnPoint.Probability ?? 0, spawnPoint));
|
||||||
new ProbabilityObject<string, Spawnpoint>(
|
|
||||||
spawnPoint.Template.Id,
|
|
||||||
spawnPoint.Probability ?? 0,
|
|
||||||
spawnPoint
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select a number of spawn points to add loot to
|
// Select a number of spawn points to add loot to
|
||||||
@@ -860,10 +739,7 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter out duplicate locationIds // prob can be done better
|
// Filter out duplicate locationIds // prob can be done better
|
||||||
chosenSpawnPoints = chosenSpawnPoints
|
chosenSpawnPoints = chosenSpawnPoints.GroupBy(spawnPoint => spawnPoint.LocationId).Select(group => group.First()).ToList();
|
||||||
.GroupBy(spawnPoint => spawnPoint.LocationId)
|
|
||||||
.Select(group => group.First())
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Do we have enough items in pool to fulfill requirement
|
// Do we have enough items in pool to fulfill requirement
|
||||||
var tooManySpawnPointsRequested = desiredSpawnPointCount - chosenSpawnPoints.Count > 0;
|
var tooManySpawnPointsRequested = desiredSpawnPointCount - chosenSpawnPoints.Count > 0;
|
||||||
@@ -893,29 +769,20 @@ public class LocationLootGenerator(
|
|||||||
// SpawnPoint is invalid, skip it
|
// SpawnPoint is invalid, skip it
|
||||||
if (spawnPoint.Template is null)
|
if (spawnPoint.Template is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("location-missing_dynamic_template", spawnPoint.LocationId));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-missing_dynamic_template",
|
|
||||||
spawnPoint.LocationId
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure no blacklisted lootable items are in pool
|
// Ensure no blacklisted lootable items are in pool
|
||||||
spawnPoint.Template.Items = spawnPoint
|
spawnPoint.Template.Items = spawnPoint
|
||||||
.Template.Items.Where(item =>
|
.Template.Items.Where(item => !_itemFilterService.IsLootableItemBlacklisted(item.Template))
|
||||||
!_itemFilterService.IsLootableItemBlacklisted(item.Template)
|
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Ensure no seasonal items are in pool if not in-season
|
// Ensure no seasonal items are in pool if not in-season
|
||||||
if (!seasonalEventActive)
|
if (!seasonalEventActive)
|
||||||
{
|
{
|
||||||
spawnPoint.Template.Items = spawnPoint.Template.Items.Where(item =>
|
spawnPoint.Template.Items = spawnPoint.Template.Items.Where(item => !seasonalItemTplBlacklist.Contains(item.Template));
|
||||||
!seasonalItemTplBlacklist.Contains(item.Template)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn point has no items after filtering, skip
|
// Spawn point has no items after filtering, skip
|
||||||
@@ -923,21 +790,14 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(_serverLocalisationService.GetText("location-spawnpoint_missing_items", spawnPoint.Template.Id));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-spawnpoint_missing_items",
|
|
||||||
spawnPoint.Template.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an array of allowed IDs after above filtering has occured
|
// Get an array of allowed IDs after above filtering has occured
|
||||||
var validComposedKeys = spawnPoint
|
var validComposedKeys = spawnPoint.Template.Items.Select(item => item.ComposedKey).ToHashSet();
|
||||||
.Template.Items.Select(item => item.ComposedKey)
|
|
||||||
.ToHashSet();
|
|
||||||
|
|
||||||
// Construct container to hold above filtered items, letting us pick an item for the spot
|
// Construct container to hold above filtered items, letting us pick an item for the spot
|
||||||
var itemArray = new ProbabilityObjectArray<string, double?>(_cloner);
|
var itemArray = new ProbabilityObjectArray<string, double?>(_cloner);
|
||||||
@@ -948,32 +808,19 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemArray.Add(
|
itemArray.Add(new ProbabilityObject<string, double?>(itemDist.ComposedKey.Key, itemDist.RelativeProbability ?? 0, null));
|
||||||
new ProbabilityObject<string, double?>(
|
|
||||||
itemDist.ComposedKey.Key,
|
|
||||||
itemDist.RelativeProbability ?? 0,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemArray.Count == 0)
|
if (itemArray.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(_serverLocalisationService.GetText("location-loot_pool_is_empty_skipping", spawnPoint.Template.Id));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-loot_pool_is_empty_skipping",
|
|
||||||
spawnPoint.Template.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a random item from the spawn points possible items
|
// Draw a random item from the spawn points possible items
|
||||||
var chosenComposedKey = itemArray.Draw().FirstOrDefault();
|
var chosenComposedKey = itemArray.Draw().FirstOrDefault();
|
||||||
var chosenItem = spawnPoint.Template.Items.FirstOrDefault(item =>
|
var chosenItem = spawnPoint.Template.Items.FirstOrDefault(item => item.ComposedKey == chosenComposedKey);
|
||||||
item.ComposedKey == chosenComposedKey
|
|
||||||
);
|
|
||||||
if (chosenItem is null)
|
if (chosenItem is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
@@ -982,18 +829,10 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var createItemResult = CreateDynamicLootItem(
|
var createItemResult = CreateDynamicLootItem(chosenItem, spawnPoint.Template.Items, staticAmmoDist);
|
||||||
chosenItem,
|
|
||||||
spawnPoint.Template.Items,
|
|
||||||
staticAmmoDist
|
|
||||||
);
|
|
||||||
|
|
||||||
// If count reaches max, skip adding item to loot
|
// If count reaches max, skip adding item to loot
|
||||||
if (
|
if (counterTrackerHelper.IncrementCount(createItemResult.Items.FirstOrDefault().Template))
|
||||||
counterTrackerHelper.IncrementCount(
|
|
||||||
createItemResult.Items.FirstOrDefault().Template
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1047,14 +886,8 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chosenItem = forcedLootLocation.Template.Items.FirstOrDefault(item =>
|
var chosenItem = forcedLootLocation.Template.Items.FirstOrDefault(item => item.Id == rootItem.Id);
|
||||||
item.Id == rootItem.Id
|
var createItemResult = CreateDynamicLootItem(chosenItem, forcedLootLocation.Template.Items, staticAmmoDist);
|
||||||
);
|
|
||||||
var createItemResult = CreateDynamicLootItem(
|
|
||||||
chosenItem,
|
|
||||||
forcedLootLocation.Template.Items,
|
|
||||||
staticAmmoDist
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update root ID with the above dynamically generated ID
|
// Update root ID with the above dynamically generated ID
|
||||||
forcedLootLocation.Template.Root = createItemResult.Items.FirstOrDefault().Id;
|
forcedLootLocation.Template.Root = createItemResult.Items.FirstOrDefault().Id;
|
||||||
@@ -1065,9 +898,7 @@ public class LocationLootGenerator(
|
|||||||
forcedLootLocation.Template.Items = convertedItems;
|
forcedLootLocation.Template.Items = convertedItems;
|
||||||
|
|
||||||
// Push forced location into array as long as it doesn't exist already
|
// Push forced location into array as long as it doesn't exist already
|
||||||
var existingLocation = result.Any(spawnPoint =>
|
var existingLocation = result.Any(spawnPoint => spawnPoint.Id == locationTemplateToAdd.Id);
|
||||||
spawnPoint.Id == locationTemplateToAdd.Id
|
|
||||||
);
|
|
||||||
if (!existingLocation)
|
if (!existingLocation)
|
||||||
{
|
{
|
||||||
result.Add(locationTemplateToAdd);
|
result.Add(locationTemplateToAdd);
|
||||||
@@ -1116,10 +947,7 @@ public class LocationLootGenerator(
|
|||||||
var stackCount =
|
var stackCount =
|
||||||
itemDbTemplate.Properties.StackMaxSize == 1
|
itemDbTemplate.Properties.StackMaxSize == 1
|
||||||
? 1
|
? 1
|
||||||
: _randomUtil.GetInt(
|
: _randomUtil.GetInt(itemDbTemplate.Properties.StackMinRandom.Value, itemDbTemplate.Properties.StackMaxRandom.Value);
|
||||||
itemDbTemplate.Properties.StackMinRandom.Value,
|
|
||||||
itemDbTemplate.Properties.StackMaxRandom.Value
|
|
||||||
);
|
|
||||||
|
|
||||||
itemWithMods.Add(
|
itemWithMods.Add(
|
||||||
new Item
|
new Item
|
||||||
@@ -1211,19 +1039,13 @@ public class LocationLootGenerator(
|
|||||||
rootItem.ParentId = parentId;
|
rootItem.ParentId = parentId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MONEY) || _itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.AMMO))
|
||||||
_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MONEY)
|
|
||||||
|| _itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.AMMO)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Edge case - some ammos e.g. flares or M406 grenades shouldn't be stacked
|
// Edge case - some ammos e.g. flares or M406 grenades shouldn't be stacked
|
||||||
var stackCount =
|
var stackCount =
|
||||||
itemTemplate.Properties.StackMaxSize == 1
|
itemTemplate.Properties.StackMaxSize == 1
|
||||||
? 1
|
? 1
|
||||||
: _randomUtil.GetInt(
|
: _randomUtil.GetInt(itemTemplate.Properties.StackMinRandom.Value, itemTemplate.Properties.StackMaxRandom.Value);
|
||||||
itemTemplate.Properties.StackMinRandom.Value,
|
|
||||||
itemTemplate.Properties.StackMaxRandom.Value
|
|
||||||
);
|
|
||||||
|
|
||||||
rootItem.Upd = new Upd { StackObjectsCount = stackCount };
|
rootItem.Upd = new Upd { StackObjectsCount = stackCount };
|
||||||
}
|
}
|
||||||
@@ -1262,12 +1084,7 @@ public class LocationLootGenerator(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Item> GetArmorItems(
|
protected List<Item> GetArmorItems(string chosenTpl, Item? rootItem, List<Item> items, TemplateItem armorDbTemplate)
|
||||||
string chosenTpl,
|
|
||||||
Item? rootItem,
|
|
||||||
List<Item> items,
|
|
||||||
TemplateItem armorDbTemplate
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var defaultPreset = _presetHelper.GetDefaultPreset(chosenTpl);
|
var defaultPreset = _presetHelper.GetDefaultPreset(chosenTpl);
|
||||||
if (defaultPreset is not null)
|
if (defaultPreset is not null)
|
||||||
@@ -1282,16 +1099,9 @@ public class LocationLootGenerator(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We make base item in calling method, no need to do it here
|
// We make base item in calling method, no need to do it here
|
||||||
if (
|
if (armorDbTemplate.Properties?.Slots is not null && armorDbTemplate.Properties.Slots.Any())
|
||||||
armorDbTemplate.Properties?.Slots is not null
|
|
||||||
&& armorDbTemplate.Properties.Slots.Any()
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
items = _itemHelper.AddChildSlotItems(
|
items = _itemHelper.AddChildSlotItems(items, armorDbTemplate, _locationConfig.EquipmentLootSettings.ModSpawnChancePercent);
|
||||||
items,
|
|
||||||
armorDbTemplate,
|
|
||||||
_locationConfig.EquipmentLootSettings.ModSpawnChancePercent
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1322,10 +1132,7 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
children = _itemHelper.ReparentItemAndChildren(
|
children = _itemHelper.ReparentItemAndChildren(defaultPreset.Items.FirstOrDefault(), defaultPreset.Items);
|
||||||
defaultPreset.Items.FirstOrDefault(),
|
|
||||||
defaultPreset.Items
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -1361,16 +1168,9 @@ public class LocationLootGenerator(
|
|||||||
var rootItem = items.FirstOrDefault();
|
var rootItem = items.FirstOrDefault();
|
||||||
if (rootItem is null)
|
if (rootItem is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("location-missing_root_item", new { tpl = chosenTpl, parentId }));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-missing_root_item",
|
|
||||||
new { tpl = chosenTpl, parentId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
throw new Exception(
|
throw new Exception(_serverLocalisationService.GetText("location-critical_error_see_log"));
|
||||||
_serverLocalisationService.GetText("location-critical_error_see_log")
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -1382,12 +1182,7 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_serverLocalisationService.GetText("location-unable_to_reparent_item", new { tpl = chosenTpl, parentId }));
|
||||||
_serverLocalisationService.GetText(
|
|
||||||
"location-unable_to_reparent_item",
|
|
||||||
new { tpl = chosenTpl, parentId }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
_logger.Error(e.StackTrace);
|
_logger.Error(e.StackTrace);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
@@ -43,17 +43,12 @@ public class LootGenerator(
|
|||||||
var itemTypeCounts = InitItemLimitCounter(options.ItemLimits);
|
var itemTypeCounts = InitItemLimitCounter(options.ItemLimits);
|
||||||
|
|
||||||
// Handle sealed weapon containers
|
// Handle sealed weapon containers
|
||||||
var sealedWeaponCrateCount = randomUtil.GetInt(
|
var sealedWeaponCrateCount = randomUtil.GetInt(options.WeaponCrateCount.Min, options.WeaponCrateCount.Max);
|
||||||
options.WeaponCrateCount.Min,
|
|
||||||
options.WeaponCrateCount.Max
|
|
||||||
);
|
|
||||||
if (sealedWeaponCrateCount > 0)
|
if (sealedWeaponCrateCount > 0)
|
||||||
{
|
{
|
||||||
// Get list of all sealed containers from db - they're all the same, just for flavor
|
// Get list of all sealed containers from db - they're all the same, just for flavor
|
||||||
var itemsDb = databaseService.GetItems().Values;
|
var itemsDb = databaseService.GetItems().Values;
|
||||||
var sealedWeaponContainerPool = itemsDb.Where(item =>
|
var sealedWeaponContainerPool = itemsDb.Where(item => item.Name.Contains("event_container_airdrop"));
|
||||||
item.Name.Contains("event_container_airdrop")
|
|
||||||
);
|
|
||||||
|
|
||||||
for (var index = 0; index < sealedWeaponCrateCount; index++)
|
for (var index = 0; index < sealedWeaponCrateCount; index++)
|
||||||
{
|
{
|
||||||
@@ -84,20 +79,10 @@ public class LootGenerator(
|
|||||||
// Pool has items we could add as loot, proceed
|
// Pool has items we could add as loot, proceed
|
||||||
if (rewardPoolResults.ItemPool.Any())
|
if (rewardPoolResults.ItemPool.Any())
|
||||||
{
|
{
|
||||||
var randomisedItemCount = randomUtil.GetInt(
|
var randomisedItemCount = randomUtil.GetInt(options.ItemCount.Min, options.ItemCount.Max);
|
||||||
options.ItemCount.Min,
|
|
||||||
options.ItemCount.Max
|
|
||||||
);
|
|
||||||
for (var index = 0; index < randomisedItemCount; index++)
|
for (var index = 0; index < randomisedItemCount; index++)
|
||||||
{
|
{
|
||||||
if (
|
if (!FindAndAddRandomItemToLoot(rewardPoolResults.ItemPool, itemTypeCounts, options, result))
|
||||||
!FindAndAddRandomItemToLoot(
|
|
||||||
rewardPoolResults.ItemPool,
|
|
||||||
itemTypeCounts,
|
|
||||||
options,
|
|
||||||
result
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Failed to add, reduce index so we get another attempt
|
// Failed to add, reduce index so we get another attempt
|
||||||
{
|
{
|
||||||
index--;
|
index--;
|
||||||
@@ -108,10 +93,7 @@ public class LootGenerator(
|
|||||||
var globalDefaultPresets = presetHelper.GetDefaultPresets().Values;
|
var globalDefaultPresets = presetHelper.GetDefaultPresets().Values;
|
||||||
|
|
||||||
// Filter default presets to just weapons
|
// Filter default presets to just weapons
|
||||||
var randomisedWeaponPresetCount = randomUtil.GetInt(
|
var randomisedWeaponPresetCount = randomUtil.GetInt(options.WeaponPresetCount.Min, options.WeaponPresetCount.Max);
|
||||||
options.WeaponPresetCount.Min,
|
|
||||||
options.WeaponPresetCount.Max
|
|
||||||
);
|
|
||||||
if (randomisedWeaponPresetCount > 0)
|
if (randomisedWeaponPresetCount > 0)
|
||||||
{
|
{
|
||||||
var weaponDefaultPresets = globalDefaultPresets.Where(preset =>
|
var weaponDefaultPresets = globalDefaultPresets.Where(preset =>
|
||||||
@@ -122,14 +104,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
for (var index = 0; index < randomisedWeaponPresetCount; index++)
|
for (var index = 0; index < randomisedWeaponPresetCount; index++)
|
||||||
{
|
{
|
||||||
if (
|
if (!FindAndAddRandomPresetToLoot(weaponDefaultPresets, itemTypeCounts, rewardPoolResults.Blacklist, result))
|
||||||
!FindAndAddRandomPresetToLoot(
|
|
||||||
weaponDefaultPresets,
|
|
||||||
itemTypeCounts,
|
|
||||||
rewardPoolResults.Blacklist,
|
|
||||||
result
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Failed to add, reduce index so we get another attempt
|
// Failed to add, reduce index so we get another attempt
|
||||||
{
|
{
|
||||||
index--;
|
index--;
|
||||||
@@ -139,32 +114,18 @@ public class LootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter default presets to just armors and then filter again by protection level
|
// Filter default presets to just armors and then filter again by protection level
|
||||||
var randomisedArmorPresetCount = randomUtil.GetInt(
|
var randomisedArmorPresetCount = randomUtil.GetInt(options.ArmorPresetCount.Min, options.ArmorPresetCount.Max);
|
||||||
options.ArmorPresetCount.Min,
|
|
||||||
options.ArmorPresetCount.Max
|
|
||||||
);
|
|
||||||
if (randomisedArmorPresetCount > 0)
|
if (randomisedArmorPresetCount > 0)
|
||||||
{
|
{
|
||||||
var armorDefaultPresets = globalDefaultPresets.Where(preset =>
|
var armorDefaultPresets = globalDefaultPresets.Where(preset => itemHelper.ArmorItemCanHoldMods(preset.Encyclopedia.Value));
|
||||||
itemHelper.ArmorItemCanHoldMods(preset.Encyclopedia.Value)
|
var levelFilteredArmorPresets = armorDefaultPresets.Where(armor => IsArmorOfDesiredProtectionLevel(armor, options));
|
||||||
);
|
|
||||||
var levelFilteredArmorPresets = armorDefaultPresets.Where(armor =>
|
|
||||||
IsArmorOfDesiredProtectionLevel(armor, options)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add some armors to rewards
|
// Add some armors to rewards
|
||||||
if (levelFilteredArmorPresets.Any())
|
if (levelFilteredArmorPresets.Any())
|
||||||
{
|
{
|
||||||
for (var index = 0; index < randomisedArmorPresetCount; index++)
|
for (var index = 0; index < randomisedArmorPresetCount; index++)
|
||||||
{
|
{
|
||||||
if (
|
if (!FindAndAddRandomPresetToLoot(levelFilteredArmorPresets, itemTypeCounts, rewardPoolResults.Blacklist, result))
|
||||||
!FindAndAddRandomPresetToLoot(
|
|
||||||
levelFilteredArmorPresets,
|
|
||||||
itemTypeCounts,
|
|
||||||
rewardPoolResults.Blacklist,
|
|
||||||
result
|
|
||||||
)
|
|
||||||
)
|
|
||||||
// Failed to add, reduce index so we get another attempt
|
// Failed to add, reduce index so we get another attempt
|
||||||
{
|
{
|
||||||
index--;
|
index--;
|
||||||
@@ -202,10 +163,7 @@ public class LootGenerator(
|
|||||||
for (var i = 0; i < randomisedItemCount; i++)
|
for (var i = 0; i < randomisedItemCount; i++)
|
||||||
{
|
{
|
||||||
// Clone preset and alter Ids to be unique
|
// Clone preset and alter Ids to be unique
|
||||||
var presetWithUniqueIdsClone = cloner
|
var presetWithUniqueIdsClone = cloner.Clone(preset.Items).ReplaceIDs().ToList();
|
||||||
.Clone(preset.Items)
|
|
||||||
.ReplaceIDs()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Add to results
|
// Add to results
|
||||||
result.Add(presetWithUniqueIdsClone);
|
result.Add(presetWithUniqueIdsClone);
|
||||||
@@ -262,9 +220,7 @@ public class LootGenerator(
|
|||||||
var itemTypeBlacklist = itemFilterService.GetItemRewardBaseTypeBlacklist();
|
var itemTypeBlacklist = itemFilterService.GetItemRewardBaseTypeBlacklist();
|
||||||
var itemsMatchingTypeBlacklist = itemsDb
|
var itemsMatchingTypeBlacklist = itemsDb
|
||||||
.Where(templateItem => !string.IsNullOrEmpty(templateItem.Parent)) // Ignore items without parents
|
.Where(templateItem => !string.IsNullOrEmpty(templateItem.Parent)) // Ignore items without parents
|
||||||
.Where(templateItem =>
|
.Where(templateItem => itemHelper.IsOfBaseclasses(templateItem.Parent, itemTypeBlacklist))
|
||||||
itemHelper.IsOfBaseclasses(templateItem.Parent, itemTypeBlacklist)
|
|
||||||
)
|
|
||||||
.Select(templateItem => templateItem.Id);
|
.Select(templateItem => templateItem.Id);
|
||||||
|
|
||||||
itemBlacklist.UnionWith([.. rewardItemBlacklist, .. itemsMatchingTypeBlacklist]);
|
itemBlacklist.UnionWith([.. rewardItemBlacklist, .. itemsMatchingTypeBlacklist]);
|
||||||
@@ -326,11 +282,7 @@ public class LootGenerator(
|
|||||||
var itemTypeCounts = new Dictionary<MongoId, ItemLimit>();
|
var itemTypeCounts = new Dictionary<MongoId, ItemLimit>();
|
||||||
foreach (var itemTypeId in limits)
|
foreach (var itemTypeId in limits)
|
||||||
{
|
{
|
||||||
itemTypeCounts[itemTypeId.Key] = new ItemLimit
|
itemTypeCounts[itemTypeId.Key] = new ItemLimit { Current = 0, Max = limits[itemTypeId.Key] };
|
||||||
{
|
|
||||||
Current = 0,
|
|
||||||
Max = limits[itemTypeId.Key],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return itemTypeCounts;
|
return itemTypeCounts;
|
||||||
@@ -353,10 +305,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
var randomItem = randomUtil.GetArrayValue(items);
|
var randomItem = randomUtil.GetArrayValue(items);
|
||||||
|
|
||||||
var itemLimitCount = itemTypeCounts.TryGetValue(
|
var itemLimitCount = itemTypeCounts.TryGetValue(randomItem.Parent, out var randomItemLimitCount);
|
||||||
randomItem.Parent,
|
|
||||||
out var randomItemLimitCount
|
|
||||||
);
|
|
||||||
if (!itemLimitCount && randomItemLimitCount?.Current > randomItemLimitCount?.Max)
|
if (!itemLimitCount && randomItemLimitCount?.Current > randomItemLimitCount?.Max)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -444,12 +393,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("loot-chosen_preset_missing_encyclopedia_value", chosenPreset?.Id));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"loot-chosen_preset_missing_encyclopedia_value",
|
|
||||||
chosenPreset?.Id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -461,9 +405,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"$Unable to find preset with tpl: {chosenPreset.Encyclopedia}, skipping");
|
||||||
$"$Unable to find preset with tpl: {chosenPreset.Encyclopedia}, skipping"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -478,21 +420,13 @@ public class LootGenerator(
|
|||||||
// Some custom mod items lack a parent property
|
// Some custom mod items lack a parent property
|
||||||
if (itemDbDetails.Value?.Parent is null)
|
if (itemDbDetails.Value?.Parent is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("loot-item_missing_parentid", itemDbDetails.Value?.Name));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"loot-item_missing_parentid",
|
|
||||||
itemDbDetails.Value?.Name
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check chosen preset hasn't exceeded spawn limit
|
// Check chosen preset hasn't exceeded spawn limit
|
||||||
var hasItemLimitCount = itemTypeCounts.TryGetValue(
|
var hasItemLimitCount = itemTypeCounts.TryGetValue(itemDbDetails.Value.Parent, out var itemLimitCount);
|
||||||
itemDbDetails.Value.Parent,
|
|
||||||
out var itemLimitCount
|
|
||||||
);
|
|
||||||
if (!hasItemLimitCount && itemLimitCount?.Current > itemLimitCount?.Max)
|
if (!hasItemLimitCount && itemLimitCount?.Current > itemLimitCount?.Max)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -521,27 +455,18 @@ public class LootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="containerSettings">sealed weapon container settings</param>
|
/// <param name="containerSettings">sealed weapon container settings</param>
|
||||||
/// <returns>List of items with children lists</returns>
|
/// <returns>List of items with children lists</returns>
|
||||||
public List<List<Item>> GetSealedWeaponCaseLoot(
|
public List<List<Item>> GetSealedWeaponCaseLoot(SealedAirdropContainerSettings containerSettings)
|
||||||
SealedAirdropContainerSettings containerSettings
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
List<List<Item>> itemsToReturn = [];
|
List<List<Item>> itemsToReturn = [];
|
||||||
|
|
||||||
// Choose a weapon to give to the player (weighted)
|
// Choose a weapon to give to the player (weighted)
|
||||||
var chosenWeaponTpl = weightedRandomHelper.GetWeightedValue(
|
var chosenWeaponTpl = weightedRandomHelper.GetWeightedValue(containerSettings.WeaponRewardWeight);
|
||||||
containerSettings.WeaponRewardWeight
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get itemDb details of weapon
|
// Get itemDb details of weapon
|
||||||
var weaponDetailsDb = itemHelper.GetItem(chosenWeaponTpl);
|
var weaponDetailsDb = itemHelper.GetItem(chosenWeaponTpl);
|
||||||
if (!weaponDetailsDb.Key)
|
if (!weaponDetailsDb.Key)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("loot-non_item_picked_as_sealed_weapon_crate_reward", chosenWeaponTpl));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"loot-non_item_picked_as_sealed_weapon_crate_reward",
|
|
||||||
chosenWeaponTpl
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return itemsToReturn;
|
return itemsToReturn;
|
||||||
}
|
}
|
||||||
@@ -554,12 +479,7 @@ public class LootGenerator(
|
|||||||
// No default preset found for weapon, choose a random one
|
// No default preset found for weapon, choose a random one
|
||||||
if (chosenWeaponPreset is null)
|
if (chosenWeaponPreset is null)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("loot-default_preset_not_found_using_random", chosenWeaponTpl));
|
||||||
serverLocalisationService.GetText(
|
|
||||||
"loot-default_preset_not_found_using_random",
|
|
||||||
chosenWeaponTpl
|
|
||||||
)
|
|
||||||
);
|
|
||||||
chosenWeaponPreset = randomUtil.GetArrayValue(presetHelper.GetPresets(chosenWeaponTpl));
|
chosenWeaponPreset = randomUtil.GetArrayValue(presetHelper.GetPresets(chosenWeaponTpl));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,18 +492,10 @@ public class LootGenerator(
|
|||||||
|
|
||||||
// Get a random collection of weapon mods related to chosen weapon and add them to result array
|
// Get a random collection of weapon mods related to chosen weapon and add them to result array
|
||||||
var linkedItemsToWeapon = ragfairLinkedItemService.GetLinkedDbItems(chosenWeaponTpl);
|
var linkedItemsToWeapon = ragfairLinkedItemService.GetLinkedDbItems(chosenWeaponTpl);
|
||||||
itemsToReturn.AddRange(
|
itemsToReturn.AddRange(GetSealedContainerWeaponModRewards(containerSettings, linkedItemsToWeapon, chosenWeaponPreset));
|
||||||
GetSealedContainerWeaponModRewards(
|
|
||||||
containerSettings,
|
|
||||||
linkedItemsToWeapon,
|
|
||||||
chosenWeaponPreset
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handle non-weapon mod reward types
|
// Handle non-weapon mod reward types
|
||||||
itemsToReturn.AddRange(
|
itemsToReturn.AddRange(GetSealedContainerNonWeaponModRewards(containerSettings, weaponDetailsDb.Value));
|
||||||
GetSealedContainerNonWeaponModRewards(containerSettings, weaponDetailsDb.Value)
|
|
||||||
);
|
|
||||||
|
|
||||||
return itemsToReturn;
|
return itemsToReturn;
|
||||||
}
|
}
|
||||||
@@ -621,9 +533,7 @@ public class LootGenerator(
|
|||||||
|
|
||||||
// Need to find boxes that matches weapons caliber
|
// Need to find boxes that matches weapons caliber
|
||||||
var weaponCaliber = weaponDetailsDb.Properties.AmmoCaliber;
|
var weaponCaliber = weaponDetailsDb.Properties.AmmoCaliber;
|
||||||
var ammoBoxesMatchingCaliber = ammoBoxesDetails.Where(x =>
|
var ammoBoxesMatchingCaliber = ammoBoxesDetails.Where(x => x.Properties.AmmoCaliber == weaponCaliber);
|
||||||
x.Properties.AmmoCaliber == weaponCaliber
|
|
||||||
);
|
|
||||||
if (!ammoBoxesMatchingCaliber.Any())
|
if (!ammoBoxesMatchingCaliber.Any())
|
||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
@@ -718,9 +628,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"No items found to fulfil reward type: {rewardKey} for weapon: {chosenWeaponPreset.Name}, skipping type");
|
||||||
$"No items found to fulfil reward type: {rewardKey} for weapon: {chosenWeaponPreset.Name}, skipping type"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -784,17 +692,13 @@ public class LootGenerator(
|
|||||||
/// <returns>Single tpl</returns>
|
/// <returns>Single tpl</returns>
|
||||||
protected MongoId PickRewardItem(RewardDetails rewardContainerDetails)
|
protected MongoId PickRewardItem(RewardDetails rewardContainerDetails)
|
||||||
{
|
{
|
||||||
if (
|
if (rewardContainerDetails.RewardTplPool is not null && rewardContainerDetails.RewardTplPool.Count > 0)
|
||||||
rewardContainerDetails.RewardTplPool is not null
|
|
||||||
&& rewardContainerDetails.RewardTplPool.Count > 0
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return weightedRandomHelper.GetWeightedValue(rewardContainerDetails.RewardTplPool);
|
return weightedRandomHelper.GetWeightedValue(rewardContainerDetails.RewardTplPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomUtil.GetArrayValue(
|
return randomUtil.GetArrayValue(
|
||||||
GetItemRewardPool([], rewardContainerDetails.RewardTypePool, true, true, false)
|
GetItemRewardPool([], rewardContainerDetails.RewardTypePool, true, true, false).ItemPool.Select(item => item.Id)
|
||||||
.ItemPool.Select(item => item.Id)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,13 +58,7 @@ public class PMCLootGenerator(
|
|||||||
var pocketPriceOverrides = GetPMCPriceOverrides(pmcRole, "pocket");
|
var pocketPriceOverrides = GetPMCPriceOverrides(pmcRole, "pocket");
|
||||||
|
|
||||||
// Generate loot and cache - Also pass check to ensure only 1x2 items are allowed (Unheard bots have big pockets, hence the need for 1x2)
|
// Generate loot and cache - Also pass check to ensure only 1x2 items are allowed (Unheard bots have big pockets, hence the need for 1x2)
|
||||||
var pool = GenerateLootPool(
|
var pool = GenerateLootPool(pmcRole, allowedItemTypeWhitelist, blacklist, pocketPriceOverrides, ItemFitsInto1By2Slot);
|
||||||
pmcRole,
|
|
||||||
allowedItemTypeWhitelist,
|
|
||||||
blacklist,
|
|
||||||
pocketPriceOverrides,
|
|
||||||
ItemFitsInto1By2Slot
|
|
||||||
);
|
|
||||||
_pocketLootPool.TryAdd(pmcRole, pool);
|
_pocketLootPool.TryAdd(pmcRole, pool);
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
@@ -97,13 +91,7 @@ public class PMCLootGenerator(
|
|||||||
var vestPriceOverrides = GetPMCPriceOverrides(pmcRole, "vest");
|
var vestPriceOverrides = GetPMCPriceOverrides(pmcRole, "vest");
|
||||||
|
|
||||||
// Generate loot and cache - Also pass check to ensure items up to 2x2 are allowed, some vests have big slots
|
// Generate loot and cache - Also pass check to ensure items up to 2x2 are allowed, some vests have big slots
|
||||||
var pool = GenerateLootPool(
|
var pool = GenerateLootPool(pmcRole, allowedItemTypeWhitelist, blacklist, vestPriceOverrides, ItemFitsInto2By2Slot);
|
||||||
pmcRole,
|
|
||||||
allowedItemTypeWhitelist,
|
|
||||||
blacklist,
|
|
||||||
vestPriceOverrides,
|
|
||||||
ItemFitsInto2By2Slot
|
|
||||||
);
|
|
||||||
_vestLootPool.TryAdd(pmcRole, pool);
|
_vestLootPool.TryAdd(pmcRole, pool);
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
@@ -133,13 +121,7 @@ public class PMCLootGenerator(
|
|||||||
var backpackPriceOverrides = GetPMCPriceOverrides(pmcRole, "vest");
|
var backpackPriceOverrides = GetPMCPriceOverrides(pmcRole, "vest");
|
||||||
|
|
||||||
// Generate loot and cache
|
// Generate loot and cache
|
||||||
var pool = GenerateLootPool(
|
var pool = GenerateLootPool(pmcRole, allowedItemTypeWhitelist, blacklist, backpackPriceOverrides, null);
|
||||||
pmcRole,
|
|
||||||
allowedItemTypeWhitelist,
|
|
||||||
blacklist,
|
|
||||||
backpackPriceOverrides,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
_backpackLootPool.TryAdd(pmcRole, pool);
|
_backpackLootPool.TryAdd(pmcRole, pool);
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
@@ -225,9 +207,7 @@ public class PMCLootGenerator(
|
|||||||
/// <returns>Dictionary of overrides</returns>
|
/// <returns>Dictionary of overrides</returns>
|
||||||
protected Dictionary<MongoId, double> GetPMCPriceOverrides(string pmcRole, string slot)
|
protected Dictionary<MongoId, double> GetPMCPriceOverrides(string pmcRole, string slot)
|
||||||
{
|
{
|
||||||
var pmcType = string.Equals(pmcRole, "pmcbear", StringComparison.OrdinalIgnoreCase)
|
var pmcType = string.Equals(pmcRole, "pmcbear", StringComparison.OrdinalIgnoreCase) ? "bear" : "usec";
|
||||||
? "bear"
|
|
||||||
: "usec";
|
|
||||||
|
|
||||||
// the usec/bear.json item prices act as overrides we apply over what we dynamically generate
|
// the usec/bear.json item prices act as overrides we apply over what we dynamically generate
|
||||||
if (databaseService.GetBots().Types.TryGetValue(pmcType, out var priceOverrides))
|
if (databaseService.GetBots().Types.TryGetValue(pmcType, out var priceOverrides))
|
||||||
@@ -253,15 +233,9 @@ public class PMCLootGenerator(
|
|||||||
/// <param name="tpl">Item tpl to get price of</param>
|
/// <param name="tpl">Item tpl to get price of</param>
|
||||||
/// <param name="pmcPriceOverrides"></param>
|
/// <param name="pmcPriceOverrides"></param>
|
||||||
/// <returns>Rouble price</returns>
|
/// <returns>Rouble price</returns>
|
||||||
protected double GetItemPrice(
|
protected double GetItemPrice(MongoId tpl, Dictionary<MongoId, double>? pmcPriceOverrides = null)
|
||||||
MongoId tpl,
|
|
||||||
Dictionary<MongoId, double>? pmcPriceOverrides = null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (
|
if (pmcPriceOverrides is not null && pmcPriceOverrides.TryGetValue(tpl, out var overridePrice))
|
||||||
pmcPriceOverrides is not null
|
|
||||||
&& pmcPriceOverrides.TryGetValue(tpl, out var overridePrice)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// There's a price override for this item, use override instead of default price
|
// There's a price override for this item, use override instead of default price
|
||||||
return overridePrice;
|
return overridePrice;
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ public class PlayerScavGenerator(
|
|||||||
TimeUtil timeUtil
|
TimeUtil timeUtil
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly PlayerScavConfig _playerScavConfig =
|
protected readonly PlayerScavConfig _playerScavConfig = configServer.GetConfig<PlayerScavConfig>();
|
||||||
configServer.GetConfig<PlayerScavConfig>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update a player profile to include a new player scav profile
|
/// Update a player profile to include a new player scav profile
|
||||||
@@ -62,9 +61,7 @@ public class PlayerScavGenerator(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(serverLocalisationService.GetText("scav-missing_karma_settings", scavKarmaLevel));
|
||||||
serverLocalisationService.GetText("scav-missing_karma_settings", scavKarmaLevel)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
@@ -110,13 +107,9 @@ public class PlayerScavGenerator(
|
|||||||
scavData.Info.Level = GetScavLevel(existingScavDataClone);
|
scavData.Info.Level = GetScavLevel(existingScavDataClone);
|
||||||
scavData.Info.Experience = GetScavExperience(existingScavDataClone);
|
scavData.Info.Experience = GetScavExperience(existingScavDataClone);
|
||||||
scavData.Quests = existingScavDataClone.Quests ?? [];
|
scavData.Quests = existingScavDataClone.Quests ?? [];
|
||||||
scavData.TaskConditionCounters =
|
scavData.TaskConditionCounters = existingScavDataClone.TaskConditionCounters ?? new Dictionary<MongoId, TaskConditionCounter>();
|
||||||
existingScavDataClone.TaskConditionCounters
|
|
||||||
?? new Dictionary<MongoId, TaskConditionCounter>();
|
|
||||||
scavData.Notes = existingScavDataClone.Notes ?? new Notes { DataNotes = [] };
|
scavData.Notes = existingScavDataClone.Notes ?? new Notes { DataNotes = [] };
|
||||||
scavData.WishList =
|
scavData.WishList = existingScavDataClone.WishList ?? new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
||||||
existingScavDataClone.WishList
|
|
||||||
?? new DictionaryOrList<MongoId, int>(new Dictionary<MongoId, int>(), []);
|
|
||||||
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new Dictionary<MongoId, bool>();
|
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new Dictionary<MongoId, bool>();
|
||||||
|
|
||||||
// Add additional items to player scav as loot
|
// Add additional items to player scav as loot
|
||||||
@@ -161,9 +154,7 @@ public class PlayerScavGenerator(
|
|||||||
var itemResult = itemHelper.GetItem(tpl.Key);
|
var itemResult = itemHelper.GetItem(tpl.Key);
|
||||||
if (!itemResult.Key)
|
if (!itemResult.Key)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(serverLocalisationService.GetText("scav-unable_to_add_item_to_player_scav", tpl));
|
||||||
serverLocalisationService.GetText("scav-unable_to_add_item_to_player_scav", tpl)
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,10 +165,7 @@ public class PlayerScavGenerator(
|
|||||||
{
|
{
|
||||||
Id = new MongoId(),
|
Id = new MongoId(),
|
||||||
Template = itemTemplate.Id,
|
Template = itemTemplate.Id,
|
||||||
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(
|
Upd = botGeneratorHelper.GenerateExtraPropertiesForItem(itemTemplate, "assault"),
|
||||||
itemTemplate,
|
|
||||||
"assault"
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -229,22 +217,13 @@ public class PlayerScavGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="karmaSettings">Values to modify the bot template with</param>
|
/// <param name="karmaSettings">Values to modify the bot template with</param>
|
||||||
/// <param name="baseBotNode">bot template to modify according to karma level settings</param>
|
/// <param name="baseBotNode">bot template to modify according to karma level settings</param>
|
||||||
protected void AdjustBotTemplateWithKarmaSpecificSettings(
|
protected void AdjustBotTemplateWithKarmaSpecificSettings(KarmaLevel karmaSettings, BotType baseBotNode)
|
||||||
KarmaLevel karmaSettings,
|
|
||||||
BotType baseBotNode
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Adjust equipment chance values
|
// Adjust equipment chance values
|
||||||
AdjustEquipmentWeights(
|
AdjustEquipmentWeights(karmaSettings.Modifiers.Equipment, baseBotNode.BotChances.EquipmentChances);
|
||||||
karmaSettings.Modifiers.Equipment,
|
|
||||||
baseBotNode.BotChances.EquipmentChances
|
|
||||||
);
|
|
||||||
|
|
||||||
// Adjust mod chance values
|
// Adjust mod chance values
|
||||||
AdjustWeaponModWeights(
|
AdjustWeaponModWeights(karmaSettings.Modifiers.Mod, baseBotNode.BotChances.WeaponModsChances);
|
||||||
karmaSettings.Modifiers.Mod,
|
|
||||||
baseBotNode.BotChances.WeaponModsChances
|
|
||||||
);
|
|
||||||
|
|
||||||
// Adjust item spawn quantity values
|
// Adjust item spawn quantity values
|
||||||
AdjustItemWeights(karmaSettings.ItemLimits, baseBotNode.BotGeneration.Items);
|
AdjustItemWeights(karmaSettings.ItemLimits, baseBotNode.BotGeneration.Items);
|
||||||
@@ -281,10 +260,7 @@ public class PlayerScavGenerator(
|
|||||||
/// <param name="key">e.g. "healing" / "looseLoot"</param>
|
/// <param name="key">e.g. "healing" / "looseLoot"</param>
|
||||||
/// <param name="botItemWeights"></param>
|
/// <param name="botItemWeights"></param>
|
||||||
/// <returns>GenerationData</returns>
|
/// <returns>GenerationData</returns>
|
||||||
protected GenerationData? GetKarmaLimitValuesByKey(
|
protected GenerationData? GetKarmaLimitValuesByKey(string key, GenerationWeightingItems botItemWeights)
|
||||||
string key,
|
|
||||||
GenerationWeightingItems botItemWeights
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
@@ -318,10 +294,7 @@ public class PlayerScavGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void AdjustWeaponModWeights(
|
protected static void AdjustWeaponModWeights(Dictionary<string, double> modChangesToApply, Dictionary<string, double> weaponModChances)
|
||||||
Dictionary<string, double> modChangesToApply,
|
|
||||||
Dictionary<string, double> weaponModChances
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var (modSlot, weight) in modChangesToApply)
|
foreach (var (modSlot, weight) in modChangesToApply)
|
||||||
{
|
{
|
||||||
@@ -416,26 +389,16 @@ public class PlayerScavGenerator(
|
|||||||
protected PmcData SetScavCooldownTimer(PmcData scavData, PmcData pmcData)
|
protected PmcData SetScavCooldownTimer(PmcData scavData, PmcData pmcData)
|
||||||
{
|
{
|
||||||
// Get sum of all scav cooldown reduction timer bonuses
|
// Get sum of all scav cooldown reduction timer bonuses
|
||||||
var modifier =
|
var modifier = 1d + pmcData.Bonuses.Where(x => x.Type == BonusType.ScavCooldownTimer).Sum(bonus => (bonus?.Value ?? 1) / 100);
|
||||||
1d
|
|
||||||
+ pmcData
|
|
||||||
.Bonuses.Where(x => x.Type == BonusType.ScavCooldownTimer)
|
|
||||||
.Sum(bonus => (bonus?.Value ?? 1) / 100);
|
|
||||||
|
|
||||||
var fenceInfo = fenceService.GetFenceInfo(pmcData);
|
var fenceInfo = fenceService.GetFenceInfo(pmcData);
|
||||||
modifier *= fenceInfo.SavageCooldownModifier;
|
modifier *= fenceInfo.SavageCooldownModifier;
|
||||||
|
|
||||||
// Make sure to apply ScavCooldownTimer bonus from Hideout if the player has it.
|
// Make sure to apply ScavCooldownTimer bonus from Hideout if the player has it.
|
||||||
var scavLockDuration =
|
var scavLockDuration = databaseService.GetGlobals().Configuration.SavagePlayCooldown * modifier;
|
||||||
databaseService.GetGlobals().Configuration.SavagePlayCooldown * modifier;
|
|
||||||
|
|
||||||
var fullProfile = profileHelper.GetFullProfile(pmcData.SessionId.Value);
|
var fullProfile = profileHelper.GetFullProfile(pmcData.SessionId.Value);
|
||||||
if (
|
if (fullProfile?.ProfileInfo?.Edition?.StartsWith(AccountTypes.SPT_DEVELOPER, StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
fullProfile?.ProfileInfo?.Edition?.StartsWith(
|
|
||||||
AccountTypes.SPT_DEVELOPER,
|
|
||||||
StringComparison.OrdinalIgnoreCase
|
|
||||||
) ?? false
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Force lock duration to 10seconds for dev profiles
|
// Force lock duration to 10seconds for dev profiles
|
||||||
scavLockDuration = 10;
|
scavLockDuration = 10;
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Generators;
|
namespace SPTarkov.Server.Core.Generators;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class PmcWaveGenerator(
|
public class PmcWaveGenerator(ISptLogger<PmcWaveGenerator> logger, DatabaseService databaseService, ConfigServer configServer)
|
||||||
ISptLogger<PmcWaveGenerator> logger,
|
|
||||||
DatabaseService databaseService,
|
|
||||||
ConfigServer configServer
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
||||||
|
|
||||||
@@ -58,12 +54,7 @@ public class PmcWaveGenerator(
|
|||||||
/// <param name="location"> Location Object </param>
|
/// <param name="location"> Location Object </param>
|
||||||
public void ApplyWaveChangesToMap(LocationBase location)
|
public void ApplyWaveChangesToMap(LocationBase location)
|
||||||
{
|
{
|
||||||
if (
|
if (!_pmcConfig.CustomPmcWaves.TryGetValue(location.Id.ToLowerInvariant(), out var pmcWavesToAdd))
|
||||||
!_pmcConfig.CustomPmcWaves.TryGetValue(
|
|
||||||
location.Id.ToLowerInvariant(),
|
|
||||||
out var pmcWavesToAdd
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,11 +55,7 @@ public class RagfairAssortGenerator(
|
|||||||
IEnumerable<List<Item>> results = [];
|
IEnumerable<List<Item>> results = [];
|
||||||
|
|
||||||
// Get cloned items from db
|
// Get cloned items from db
|
||||||
var dbItems = databaseService
|
var dbItems = databaseService.GetItems().Where(item => !string.Equals(item.Value.Type, "Node", StringComparison.OrdinalIgnoreCase));
|
||||||
.GetItems()
|
|
||||||
.Where(item =>
|
|
||||||
!string.Equals(item.Value.Type, "Node", StringComparison.OrdinalIgnoreCase)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Store processed preset tpls so we don't add them when processing non-preset items
|
// Store processed preset tpls so we don't add them when processing non-preset items
|
||||||
HashSet<MongoId> processedArmorItems = [];
|
HashSet<MongoId> processedArmorItems = [];
|
||||||
@@ -96,11 +92,7 @@ public class RagfairAssortGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip seasonal items when not in-season
|
// Skip seasonal items when not in-season
|
||||||
if (
|
if (RagfairConfig.Dynamic.RemoveSeasonalItemsWhenNotInEvent && !seasonalEventActive && seasonalItemTplBlacklist.Contains(id))
|
||||||
RagfairConfig.Dynamic.RemoveSeasonalItemsWhenNotInEvent
|
|
||||||
&& !seasonalEventActive
|
|
||||||
&& seasonalItemTplBlacklist.Contains(id)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,21 +101,13 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
// Hydrate ammo boxes with cartridges + ensure only 1 item is present (ammo box)
|
// Hydrate ammo boxes with cartridges + ensure only 1 item is present (ammo box)
|
||||||
// On offer refresh don't re-add cartridges to ammo box that already has cartridges
|
// On offer refresh don't re-add cartridges to ammo box that already has cartridges
|
||||||
if (
|
if (itemsClone.Count == 1 && itemHelper.IsOfBaseclass(itemsClone[0].Template, BaseClasses.AMMO_BOX))
|
||||||
itemsClone.Count == 1
|
|
||||||
&& itemHelper.IsOfBaseclass(itemsClone[0].Template, BaseClasses.AMMO_BOX)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
itemHelper.AddCartridgesToAmmoBox(
|
itemHelper.AddCartridgesToAmmoBox(itemsClone, itemHelper.GetItem(rootItem.Template).Value);
|
||||||
itemsClone,
|
|
||||||
itemHelper.GetItem(rootItem.Template).Value
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var roubleListingPrice = Math.Round(ConvertOfferRequirementsIntoRoubles(offerRequirements));
|
var roubleListingPrice = Math.Round(ConvertOfferRequirementsIntoRoubles(offerRequirements));
|
||||||
var singleItemListingPrice = details.SellInOnePiece
|
var singleItemListingPrice = details.SellInOnePiece ? roubleListingPrice / details.Quantity : roubleListingPrice;
|
||||||
? roubleListingPrice / details.Quantity
|
|
||||||
: roubleListingPrice;
|
|
||||||
|
|
||||||
var offer = new RagfairOffer
|
var offer = new RagfairOffer
|
||||||
{
|
{
|
||||||
@@ -124,10 +116,7 @@ public class RagfairOfferGenerator(
|
|||||||
User =
|
User =
|
||||||
details.Creator == OfferCreator.Player
|
details.Creator == OfferCreator.Player
|
||||||
? CreatePlayerUserDataForFleaOffer(details.UserId)
|
? CreatePlayerUserDataForFleaOffer(details.UserId)
|
||||||
: CreateUserDataForFleaOffer(
|
: CreateUserDataForFleaOffer(details.UserId, details.Creator == OfferCreator.Trader),
|
||||||
details.UserId,
|
|
||||||
details.Creator == OfferCreator.Trader
|
|
||||||
),
|
|
||||||
Root = rootItem.Id,
|
Root = rootItem.Id,
|
||||||
Items = itemsClone,
|
Items = itemsClone,
|
||||||
ItemsCost = Math.Round(handbookHelper.GetTemplatePrice(rootItem.Template)), // Handbook price
|
ItemsCost = Math.Round(handbookHelper.GetTemplatePrice(rootItem.Template)), // Handbook price
|
||||||
@@ -167,10 +156,7 @@ public class RagfairOfferGenerator(
|
|||||||
Id = userId,
|
Id = userId,
|
||||||
MemberType = MemberCategory.Default,
|
MemberType = MemberCategory.Default,
|
||||||
Nickname = botHelper.GetPmcNicknameOfMaxLength(botConfig.BotNameLengthLimit),
|
Nickname = botHelper.GetPmcNicknameOfMaxLength(botConfig.BotNameLengthLimit),
|
||||||
Rating = randomUtil.GetDouble(
|
Rating = randomUtil.GetDouble(ragfairConfig.Dynamic.Rating.Min, ragfairConfig.Dynamic.Rating.Max),
|
||||||
ragfairConfig.Dynamic.Rating.Min,
|
|
||||||
ragfairConfig.Dynamic.Rating.Max
|
|
||||||
),
|
|
||||||
IsRatingGrowing = randomUtil.GetBool(),
|
IsRatingGrowing = randomUtil.GetBool(),
|
||||||
Avatar = null,
|
Avatar = null,
|
||||||
Aid = hashUtil.GenerateAccountId(),
|
Aid = hashUtil.GenerateAccountId(),
|
||||||
@@ -203,17 +189,14 @@ public class RagfairOfferGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="offerRequirements"> barter requirements for offer </param>
|
/// <param name="offerRequirements"> barter requirements for offer </param>
|
||||||
/// <returns> rouble cost of offer </returns>
|
/// <returns> rouble cost of offer </returns>
|
||||||
protected double ConvertOfferRequirementsIntoRoubles(
|
protected double ConvertOfferRequirementsIntoRoubles(IEnumerable<OfferRequirement> offerRequirements)
|
||||||
IEnumerable<OfferRequirement> offerRequirements
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var roublePrice = 0d;
|
var roublePrice = 0d;
|
||||||
foreach (var requirement in offerRequirements)
|
foreach (var requirement in offerRequirements)
|
||||||
{
|
{
|
||||||
roublePrice += paymentHelper.IsMoneyTpl(requirement.TemplateId)
|
roublePrice += paymentHelper.IsMoneyTpl(requirement.TemplateId)
|
||||||
? Math.Round(CalculateRoublePrice(requirement.Count.Value, requirement.TemplateId))
|
? Math.Round(CalculateRoublePrice(requirement.Count.Value, requirement.TemplateId))
|
||||||
: ragfairPriceService.GetFleaPriceForItem(requirement.TemplateId)
|
: ragfairPriceService.GetFleaPriceForItem(requirement.TemplateId) * requirement.Count.Value; // Get flea price for barter offer items
|
||||||
* requirement.Count.Value; // Get flea price for barter offer items
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return roublePrice;
|
return roublePrice;
|
||||||
@@ -271,10 +254,7 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generated pmc offer
|
// Generated pmc offer
|
||||||
return randomUtil.GetDouble(
|
return randomUtil.GetDouble(ragfairConfig.Dynamic.Rating.Min, ragfairConfig.Dynamic.Rating.Max);
|
||||||
ragfairConfig.Dynamic.Rating.Min,
|
|
||||||
ragfairConfig.Dynamic.Rating.Max
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -289,13 +269,8 @@ public class RagfairOfferGenerator(
|
|||||||
if (creatorType == OfferCreator.Player)
|
if (creatorType == OfferCreator.Player)
|
||||||
{
|
{
|
||||||
// Player offer = current time + offerDurationTimeInHour;
|
// Player offer = current time + offerDurationTimeInHour;
|
||||||
var offerDurationTimeHours = databaseService
|
var offerDurationTimeHours = databaseService.GetGlobals().Configuration.RagFair.OfferDurationTimeInHour;
|
||||||
.GetGlobals()
|
return (long)(timeUtil.GetTimeStamp() + Math.Round((double)offerDurationTimeHours * TimeUtil.OneHourAsSeconds));
|
||||||
.Configuration.RagFair.OfferDurationTimeInHour;
|
|
||||||
return (long)(
|
|
||||||
timeUtil.GetTimeStamp()
|
|
||||||
+ Math.Round((double)offerDurationTimeHours * TimeUtil.OneHourAsSeconds)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creatorType == OfferCreator.Trader)
|
if (creatorType == OfferCreator.Trader)
|
||||||
@@ -304,10 +279,7 @@ public class RagfairOfferGenerator(
|
|||||||
return (long)databaseService.GetTrader(userID).Base.NextResupply;
|
return (long)databaseService.GetTrader(userID).Base.NextResupply;
|
||||||
}
|
}
|
||||||
|
|
||||||
var randomSpread = randomUtil.GetDouble(
|
var randomSpread = randomUtil.GetDouble(ragfairConfig.Dynamic.EndTimeSeconds.Min, ragfairConfig.Dynamic.EndTimeSeconds.Max);
|
||||||
ragfairConfig.Dynamic.EndTimeSeconds.Min,
|
|
||||||
ragfairConfig.Dynamic.EndTimeSeconds.Max
|
|
||||||
);
|
|
||||||
|
|
||||||
// Fake-player offer
|
// Fake-player offer
|
||||||
return (long)Math.Round(time + randomSpread);
|
return (long)Math.Round(time + randomSpread);
|
||||||
@@ -323,15 +295,11 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
// get assort items from param if they exist, otherwise grab freshly generated assorts
|
// get assort items from param if they exist, otherwise grab freshly generated assorts
|
||||||
var assortItemsToProcess = replacingExpiredOffers
|
var assortItemsToProcess = replacingExpiredOffers ? expiredOffers ?? [] : ragfairAssortGenerator.GetAssortItems();
|
||||||
? expiredOffers ?? []
|
|
||||||
: ragfairAssortGenerator.GetAssortItems();
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0)
|
if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0)
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count()} items");
|
||||||
$"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count()} items"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
@@ -341,11 +309,7 @@ public class RagfairOfferGenerator(
|
|||||||
tasks.Add(
|
tasks.Add(
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
CreateOffersFromAssort(
|
CreateOffersFromAssort(assortItemWithChildren, replacingExpiredOffers, ragfairConfig.Dynamic);
|
||||||
assortItemWithChildren,
|
|
||||||
replacingExpiredOffers,
|
|
||||||
ragfairConfig.Dynamic
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -364,11 +328,7 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="assortItemWithChildren"> Item with its children to process into offers </param>
|
/// <param name="assortItemWithChildren"> Item with its children to process into offers </param>
|
||||||
/// <param name="isExpiredOffer"> Is an expired offer </param>
|
/// <param name="isExpiredOffer"> Is an expired offer </param>
|
||||||
/// <param name="config"> Ragfair dynamic config </param>
|
/// <param name="config"> Ragfair dynamic config </param>
|
||||||
protected void CreateOffersFromAssort(
|
protected void CreateOffersFromAssort(List<Item> assortItemWithChildren, bool isExpiredOffer, Dynamic config)
|
||||||
List<Item> assortItemWithChildren,
|
|
||||||
bool isExpiredOffer,
|
|
||||||
Dynamic config
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var rootItem = assortItemWithChildren.FirstOrDefault();
|
var rootItem = assortItemWithChildren.FirstOrDefault();
|
||||||
var itemToSellDetails = itemHelper.GetItem(rootItem.Template);
|
var itemToSellDetails = itemHelper.GetItem(rootItem.Template);
|
||||||
@@ -380,22 +340,15 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Armor presets can hold plates above the allowed flea level, remove if necessary
|
// Armor presets can hold plates above the allowed flea level, remove if necessary
|
||||||
var isPreset =
|
var isPreset = rootItem?.Upd?.SptPresetId is not null && presetHelper.IsPreset(rootItem.Upd.SptPresetId.Value);
|
||||||
rootItem?.Upd?.SptPresetId is not null
|
|
||||||
&& presetHelper.IsPreset(rootItem.Upd.SptPresetId.Value);
|
|
||||||
if (!isExpiredOffer && isPreset && ragfairConfig.Dynamic.Blacklist.EnableBsgList)
|
if (!isExpiredOffer && isPreset && ragfairConfig.Dynamic.Blacklist.EnableBsgList)
|
||||||
{
|
{
|
||||||
RemoveBannedPlatesFromPreset(
|
RemoveBannedPlatesFromPreset(assortItemWithChildren, ragfairConfig.Dynamic.Blacklist.ArmorPlate);
|
||||||
assortItemWithChildren,
|
|
||||||
ragfairConfig.Dynamic.Blacklist.ArmorPlate
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get number of offers to create
|
// Get number of offers to create
|
||||||
// Limit to 1 offer when processing expired - like-for-like replacement
|
// Limit to 1 offer when processing expired - like-for-like replacement
|
||||||
var offerCount = isExpiredOffer
|
var offerCount = isExpiredOffer ? 1 : ragfairServerHelper.GetOfferCountByBaseType(itemToSellDetails.Value.Parent);
|
||||||
? 1
|
|
||||||
: ragfairServerHelper.GetOfferCountByBaseType(itemToSellDetails.Value.Parent);
|
|
||||||
|
|
||||||
for (var index = 0; index < offerCount; index++)
|
for (var index = 0; index < offerCount; index++)
|
||||||
{
|
{
|
||||||
@@ -424,10 +377,7 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="presetWithChildren"> Preset to check for plates </param>
|
/// <param name="presetWithChildren"> Preset to check for plates </param>
|
||||||
/// <param name="plateSettings"> Settings </param>
|
/// <param name="plateSettings"> Settings </param>
|
||||||
/// <returns> True if plates removed </returns>
|
/// <returns> True if plates removed </returns>
|
||||||
protected bool RemoveBannedPlatesFromPreset(
|
protected bool RemoveBannedPlatesFromPreset(List<Item> presetWithChildren, ArmorPlateBlacklistSettings plateSettings)
|
||||||
List<Item> presetWithChildren,
|
|
||||||
ArmorPlateBlacklistSettings plateSettings
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!itemHelper.ArmorItemCanHoldMods(presetWithChildren[0].Template))
|
if (!itemHelper.ArmorItemCanHoldMods(presetWithChildren[0].Template))
|
||||||
// Cant hold armor inserts, skip
|
// Cant hold armor inserts, skip
|
||||||
@@ -436,9 +386,7 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var plateSlots = presetWithChildren
|
var plateSlots = presetWithChildren
|
||||||
.Where(item =>
|
.Where(item => itemHelper.GetRemovablePlateSlotIds().Contains(item.SlotId?.ToLowerInvariant()))
|
||||||
itemHelper.GetRemovablePlateSlotIds().Contains(item.SlotId?.ToLowerInvariant())
|
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
if (plateSlots.Count == 0)
|
if (plateSlots.Count == 0)
|
||||||
// Has no plate slots e.g. "front_plate", exit
|
// Has no plate slots e.g. "front_plate", exit
|
||||||
@@ -487,10 +435,7 @@ public class RagfairOfferGenerator(
|
|||||||
var rootItem = itemWithChildren.FirstOrDefault();
|
var rootItem = itemWithChildren.FirstOrDefault();
|
||||||
|
|
||||||
// Get randomised amount to list on flea
|
// Get randomised amount to list on flea
|
||||||
var desiredStackSize = ragfairServerHelper.CalculateDynamicStackCount(
|
var desiredStackSize = ragfairServerHelper.CalculateDynamicStackCount(rootItem.Template, isPreset);
|
||||||
rootItem.Template,
|
|
||||||
isPreset
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset stack count to 1 from whatever it was prior
|
// Reset stack count to 1 from whatever it was prior
|
||||||
rootItem.Upd.StackObjectsCount = 1;
|
rootItem.Upd.StackObjectsCount = 1;
|
||||||
@@ -506,36 +451,21 @@ public class RagfairOfferGenerator(
|
|||||||
!isBarterOffer
|
!isBarterOffer
|
||||||
&& randomUtil.GetChance100(ragfairConfig.Dynamic.Pack.ChancePercent)
|
&& randomUtil.GetChance100(ragfairConfig.Dynamic.Pack.ChancePercent)
|
||||||
&& itemWithChildren.Count == 1
|
&& itemWithChildren.Count == 1
|
||||||
&& itemHelper.IsOfBaseclasses(
|
&& itemHelper.IsOfBaseclasses(rootItem.Template, ragfairConfig.Dynamic.Pack.ItemTypeWhitelist);
|
||||||
rootItem.Template,
|
|
||||||
ragfairConfig.Dynamic.Pack.ItemTypeWhitelist
|
|
||||||
);
|
|
||||||
|
|
||||||
List<BarterScheme> barterScheme;
|
List<BarterScheme> barterScheme;
|
||||||
if (isPackOffer)
|
if (isPackOffer)
|
||||||
{
|
{
|
||||||
// Set pack size
|
// Set pack size
|
||||||
desiredStackSize = randomUtil.GetInt(
|
desiredStackSize = randomUtil.GetInt(ragfairConfig.Dynamic.Pack.ItemCountMin, ragfairConfig.Dynamic.Pack.ItemCountMax);
|
||||||
ragfairConfig.Dynamic.Pack.ItemCountMin,
|
|
||||||
ragfairConfig.Dynamic.Pack.ItemCountMax
|
|
||||||
);
|
|
||||||
|
|
||||||
// Don't randomise pack items
|
// Don't randomise pack items
|
||||||
barterScheme = CreateCurrencyBarterScheme(
|
barterScheme = CreateCurrencyBarterScheme(itemWithChildren, isPackOffer, desiredStackSize);
|
||||||
itemWithChildren,
|
|
||||||
isPackOffer,
|
|
||||||
desiredStackSize
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (isBarterOffer)
|
else if (isBarterOffer)
|
||||||
{
|
{
|
||||||
// Apply randomised properties
|
// Apply randomised properties
|
||||||
RandomiseOfferItemUpdProperties(
|
RandomiseOfferItemUpdProperties(sellerId, itemWithChildren, itemToSellDetails, offerCreator);
|
||||||
sellerId,
|
|
||||||
itemWithChildren,
|
|
||||||
itemToSellDetails,
|
|
||||||
offerCreator
|
|
||||||
);
|
|
||||||
barterScheme = CreateBarterBarterScheme(itemWithChildren, ragfairConfig.Dynamic.Barter);
|
barterScheme = CreateBarterBarterScheme(itemWithChildren, ragfairConfig.Dynamic.Barter);
|
||||||
if (ragfairConfig.Dynamic.Barter.MakeSingleStackOnly)
|
if (ragfairConfig.Dynamic.Barter.MakeSingleStackOnly)
|
||||||
{
|
{
|
||||||
@@ -550,12 +480,7 @@ public class RagfairOfferGenerator(
|
|||||||
{
|
{
|
||||||
// Not barter or pack offer
|
// Not barter or pack offer
|
||||||
// Apply randomised properties
|
// Apply randomised properties
|
||||||
RandomiseOfferItemUpdProperties(
|
RandomiseOfferItemUpdProperties(sellerId, itemWithChildren, itemToSellDetails, offerCreator);
|
||||||
sellerId,
|
|
||||||
itemWithChildren,
|
|
||||||
itemToSellDetails,
|
|
||||||
offerCreator
|
|
||||||
);
|
|
||||||
barterScheme = CreateCurrencyBarterScheme(itemWithChildren, isPackOffer);
|
barterScheme = CreateCurrencyBarterScheme(itemWithChildren, isPackOffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -593,9 +518,7 @@ public class RagfairOfferGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Latest first, to ensure we don't move later items off by 1 each time we remove an item below it
|
// Latest first, to ensure we don't move later items off by 1 each time we remove an item below it
|
||||||
var indexesToRemove = offerItemPlatesToRemove
|
var indexesToRemove = offerItemPlatesToRemove.Select(plateItem => itemWithChildren.IndexOf(plateItem)).ToHashSet();
|
||||||
.Select(plateItem => itemWithChildren.IndexOf(plateItem))
|
|
||||||
.ToHashSet();
|
|
||||||
foreach (var index in indexesToRemove.OrderByDescending(x => x))
|
foreach (var index in indexesToRemove.OrderByDescending(x => x))
|
||||||
{
|
{
|
||||||
itemWithChildren.RemoveAt(index);
|
itemWithChildren.RemoveAt(index);
|
||||||
@@ -618,19 +541,12 @@ public class RagfairOfferGenerator(
|
|||||||
// Trader assorts / assort items are missing
|
// Trader assorts / assort items are missing
|
||||||
if (assortsClone?.Items?.Count is null or 0)
|
if (assortsClone?.Items?.Count is null or 0)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("ragfair-no_trader_assorts_cant_generate_flea_offers", trader.Base.Nickname));
|
||||||
localisationService.GetText(
|
|
||||||
"ragfair-no_trader_assorts_cant_generate_flea_offers",
|
|
||||||
trader.Base.Nickname
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var blacklist = ragfairConfig.Dynamic.Blacklist;
|
var blacklist = ragfairConfig.Dynamic.Blacklist;
|
||||||
var childAssortItems = assortsClone
|
var childAssortItems = assortsClone.Items.Where(x => !string.Equals(x.ParentId, "hideout", StringComparison.Ordinal)).ToList();
|
||||||
.Items.Where(x => !string.Equals(x.ParentId, "hideout", StringComparison.Ordinal))
|
|
||||||
.ToList();
|
|
||||||
foreach (var item in assortsClone.Items)
|
foreach (var item in assortsClone.Items)
|
||||||
{
|
{
|
||||||
// We only want to process 'base/root' items, no children
|
// We only want to process 'base/root' items, no children
|
||||||
@@ -646,17 +562,12 @@ public class RagfairOfferGenerator(
|
|||||||
var itemDetails = itemHelper.GetItem(item.Template);
|
var itemDetails = itemHelper.GetItem(item.Template);
|
||||||
if (!itemDetails.Key)
|
if (!itemDetails.Key)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("ragfair-tpl_not_a_valid_item", item.Template));
|
||||||
localisationService.GetText("ragfair-tpl_not_a_valid_item", item.Template)
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't include items that BSG has blacklisted from flea
|
// Don't include items that BSG has blacklisted from flea
|
||||||
if (
|
if (blacklist.EnableBsgList && !(itemDetails.Value?.Properties?.CanSellOnRagfair ?? false))
|
||||||
blacklist.EnableBsgList
|
|
||||||
&& !(itemDetails.Value?.Properties?.CanSellOnRagfair ?? false)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -731,11 +642,7 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Roll random chance to randomise item condition
|
// Roll random chance to randomise item condition
|
||||||
if (
|
if (randomUtil.GetChance100(ragfairConfig.Dynamic.Condition[parentId.Value].ConditionChance * 100))
|
||||||
randomUtil.GetChance100(
|
|
||||||
ragfairConfig.Dynamic.Condition[parentId.Value].ConditionChance * 100
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
RandomiseItemCondition(parentId.Value, itemWithMods, itemDetails);
|
RandomiseItemCondition(parentId.Value, itemWithMods, itemDetails);
|
||||||
}
|
}
|
||||||
@@ -768,39 +675,25 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="conditionSettingsId"> Also the parentID of item being altered </param>
|
/// <param name="conditionSettingsId"> Also the parentID of item being altered </param>
|
||||||
/// <param name="itemWithMods"> Item to adjust condition details of </param>
|
/// <param name="itemWithMods"> Item to adjust condition details of </param>
|
||||||
/// <param name="itemDetails"> DB Item details of first item in list </param>
|
/// <param name="itemDetails"> DB Item details of first item in list </param>
|
||||||
protected void RandomiseItemCondition(
|
protected void RandomiseItemCondition(MongoId conditionSettingsId, IEnumerable<Item> itemWithMods, TemplateItem itemDetails)
|
||||||
MongoId conditionSettingsId,
|
|
||||||
IEnumerable<Item> itemWithMods,
|
|
||||||
TemplateItem itemDetails
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var rootItem = itemWithMods.First();
|
var rootItem = itemWithMods.First();
|
||||||
|
|
||||||
var itemConditionValues = ragfairConfig.Dynamic.Condition[conditionSettingsId];
|
var itemConditionValues = ragfairConfig.Dynamic.Condition[conditionSettingsId];
|
||||||
var maxMultiplier = randomUtil.GetDouble(
|
var maxMultiplier = randomUtil.GetDouble(itemConditionValues.Max.Min, itemConditionValues.Max.Min);
|
||||||
itemConditionValues.Max.Min,
|
var currentMultiplier = randomUtil.GetDouble(itemConditionValues.Current.Min, itemConditionValues.Current.Max);
|
||||||
itemConditionValues.Max.Min
|
|
||||||
);
|
|
||||||
var currentMultiplier = randomUtil.GetDouble(
|
|
||||||
itemConditionValues.Current.Min,
|
|
||||||
itemConditionValues.Current.Max
|
|
||||||
);
|
|
||||||
|
|
||||||
// Randomise armor + plates + armor related things
|
// Randomise armor + plates + armor related things
|
||||||
if (
|
if (
|
||||||
itemHelper.ArmorItemCanHoldMods(rootItem.Template)
|
itemHelper.ArmorItemCanHoldMods(rootItem.Template)
|
||||||
|| itemHelper.IsOfBaseclasses(
|
|| itemHelper.IsOfBaseclasses(rootItem.Template, [BaseClasses.ARMOR_PLATE, BaseClasses.ARMORED_EQUIPMENT])
|
||||||
rootItem.Template,
|
|
||||||
[BaseClasses.ARMOR_PLATE, BaseClasses.ARMORED_EQUIPMENT]
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
RandomiseArmorDurabilityValues(itemWithMods, currentMultiplier, maxMultiplier);
|
RandomiseArmorDurabilityValues(itemWithMods, currentMultiplier, maxMultiplier);
|
||||||
|
|
||||||
// Add hits to visor
|
// Add hits to visor
|
||||||
var visorMod = itemWithMods.FirstOrDefault(item =>
|
var visorMod = itemWithMods.FirstOrDefault(item =>
|
||||||
item.ParentId == BaseClasses.ARMORED_EQUIPMENT.ToString()
|
item.ParentId == BaseClasses.ARMORED_EQUIPMENT.ToString() && item.SlotId == "mod_equipment_000"
|
||||||
&& item.SlotId == "mod_equipment_000"
|
|
||||||
);
|
);
|
||||||
if (randomUtil.GetChance100(25) && visorMod != null)
|
if (randomUtil.GetChance100(25) && visorMod != null)
|
||||||
{
|
{
|
||||||
@@ -815,12 +708,7 @@ public class RagfairOfferGenerator(
|
|||||||
// Randomise Weapons
|
// Randomise Weapons
|
||||||
if (itemHelper.IsOfBaseclass(itemDetails.Id, BaseClasses.WEAPON))
|
if (itemHelper.IsOfBaseclass(itemDetails.Id, BaseClasses.WEAPON))
|
||||||
{
|
{
|
||||||
RandomiseWeaponDurability(
|
RandomiseWeaponDurability(itemWithMods.First(), itemDetails, maxMultiplier, currentMultiplier);
|
||||||
itemWithMods.First(),
|
|
||||||
itemDetails,
|
|
||||||
maxMultiplier,
|
|
||||||
currentMultiplier
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -836,8 +724,7 @@ public class RagfairOfferGenerator(
|
|||||||
if (rootItem.Upd?.Key != null && itemDetails.Properties.MaximumNumberOfUsage > 1)
|
if (rootItem.Upd?.Key != null && itemDetails.Properties.MaximumNumberOfUsage > 1)
|
||||||
{
|
{
|
||||||
// Randomize key uses
|
// Randomize key uses
|
||||||
rootItem.Upd.Key.NumberOfUsages = (int?)
|
rootItem.Upd.Key.NumberOfUsages = (int?)Math.Round(itemDetails.Properties.MaximumNumberOfUsage.Value * (1 - maxMultiplier));
|
||||||
Math.Round(itemDetails.Properties.MaximumNumberOfUsage.Value * (1 - maxMultiplier));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,9 +740,7 @@ public class RagfairOfferGenerator(
|
|||||||
if (rootItem.Upd?.RepairKit != null)
|
if (rootItem.Upd?.RepairKit != null)
|
||||||
{
|
{
|
||||||
// randomize repair kit (armor/weapon) uses
|
// randomize repair kit (armor/weapon) uses
|
||||||
var resource = Math.Round(
|
var resource = Math.Round((double)itemDetails.Properties.MaxRepairResource * maxMultiplier);
|
||||||
(double)itemDetails.Properties.MaxRepairResource * maxMultiplier
|
|
||||||
);
|
|
||||||
rootItem.Upd.RepairKit.Resource = resource == 0D ? 1D : resource;
|
rootItem.Upd.RepairKit.Resource = resource == 0D ? 1D : resource;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -865,11 +750,7 @@ public class RagfairOfferGenerator(
|
|||||||
{
|
{
|
||||||
var totalCapacity = itemDetails.Properties.MaxResource;
|
var totalCapacity = itemDetails.Properties.MaxResource;
|
||||||
var remainingFuel = Math.Round((double)totalCapacity * maxMultiplier);
|
var remainingFuel = Math.Round((double)totalCapacity * maxMultiplier);
|
||||||
rootItem.Upd.Resource = new UpdResource
|
rootItem.Upd.Resource = new UpdResource { UnitsConsumed = totalCapacity - remainingFuel, Value = remainingFuel };
|
||||||
{
|
|
||||||
UnitsConsumed = totalCapacity - remainingFuel,
|
|
||||||
Value = remainingFuel,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -880,29 +761,18 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="itemDbDetails"> Item details from DB </param>
|
/// <param name="itemDbDetails"> Item details from DB </param>
|
||||||
/// <param name="maxMultiplier"> Value to multiply max durability by </param>
|
/// <param name="maxMultiplier"> Value to multiply max durability by </param>
|
||||||
/// <param name="currentMultiplier"> Value to multiply current durability by </param>
|
/// <param name="currentMultiplier"> Value to multiply current durability by </param>
|
||||||
protected void RandomiseWeaponDurability(
|
protected void RandomiseWeaponDurability(Item item, TemplateItem itemDbDetails, double maxMultiplier, double currentMultiplier)
|
||||||
Item item,
|
|
||||||
TemplateItem itemDbDetails,
|
|
||||||
double maxMultiplier,
|
|
||||||
double currentMultiplier
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Max
|
// Max
|
||||||
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
||||||
var lowestMaxDurability = randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
var lowestMaxDurability = randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
||||||
var chosenMaxDurability = Math.Round(
|
var chosenMaxDurability = Math.Round(randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability));
|
||||||
randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Current
|
// Current
|
||||||
var lowestCurrentDurability =
|
var lowestCurrentDurability = randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
||||||
randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
var chosenCurrentDurability = Math.Round(randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability));
|
||||||
var chosenCurrentDurability = Math.Round(
|
|
||||||
randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability)
|
|
||||||
);
|
|
||||||
|
|
||||||
item.Upd.Repairable.Durability =
|
item.Upd.Repairable.Durability = chosenCurrentDurability == 0 ? 1D : chosenCurrentDurability; // Never var value become 0
|
||||||
chosenCurrentDurability == 0 ? 1D : chosenCurrentDurability; // Never var value become 0
|
|
||||||
item.Upd.Repairable.MaxDurability = chosenMaxDurability;
|
item.Upd.Repairable.MaxDurability = chosenMaxDurability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -912,11 +782,7 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="armorWithMods"> Armor item with its child mods </param>
|
/// <param name="armorWithMods"> Armor item with its child mods </param>
|
||||||
/// <param name="currentMultiplier"> Chosen multiplier to use for current durability value </param>
|
/// <param name="currentMultiplier"> Chosen multiplier to use for current durability value </param>
|
||||||
/// <param name="maxMultiplier"> Chosen multiplier to use for max durability value </param>
|
/// <param name="maxMultiplier"> Chosen multiplier to use for max durability value </param>
|
||||||
protected void RandomiseArmorDurabilityValues(
|
protected void RandomiseArmorDurabilityValues(IEnumerable<Item> armorWithMods, double currentMultiplier, double maxMultiplier)
|
||||||
IEnumerable<Item> armorWithMods,
|
|
||||||
double currentMultiplier,
|
|
||||||
double maxMultiplier
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
foreach (var armorItem in armorWithMods)
|
foreach (var armorItem in armorWithMods)
|
||||||
{
|
{
|
||||||
@@ -926,17 +792,11 @@ public class RagfairOfferGenerator(
|
|||||||
itemHelper.AddUpdObjectToItem(armorItem);
|
itemHelper.AddUpdObjectToItem(armorItem);
|
||||||
|
|
||||||
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
||||||
var lowestMaxDurability =
|
var lowestMaxDurability = randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
||||||
randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
var chosenMaxDurability = Math.Round(randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability));
|
||||||
var chosenMaxDurability = Math.Round(
|
|
||||||
randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability)
|
|
||||||
);
|
|
||||||
|
|
||||||
var lowestCurrentDurability =
|
var lowestCurrentDurability = randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
||||||
randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
var chosenCurrentDurability = Math.Round(randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability));
|
||||||
var chosenCurrentDurability = Math.Round(
|
|
||||||
randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability)
|
|
||||||
);
|
|
||||||
|
|
||||||
armorItem.Upd.Repairable = new UpdRepairable
|
armorItem.Upd.Repairable = new UpdRepairable
|
||||||
{
|
{
|
||||||
@@ -964,11 +824,7 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
if (isRepairable && props.Durability > 0)
|
if (isRepairable && props.Durability > 0)
|
||||||
{
|
{
|
||||||
item.Upd.Repairable = new UpdRepairable
|
item.Upd.Repairable = new UpdRepairable { Durability = props.Durability, MaxDurability = props.Durability };
|
||||||
{
|
|
||||||
Durability = props.Durability,
|
|
||||||
MaxDurability = props.Durability,
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1007,17 +863,10 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="offerItems"> Items for sale in offer </param>
|
/// <param name="offerItems"> Items for sale in offer </param>
|
||||||
/// <param name="barterConfig"> Barter config from ragfairConfig.Dynamic.barter </param>
|
/// <param name="barterConfig"> Barter config from ragfairConfig.Dynamic.barter </param>
|
||||||
/// <returns> Barter scheme </returns>
|
/// <returns> Barter scheme </returns>
|
||||||
protected List<BarterScheme> CreateBarterBarterScheme(
|
protected List<BarterScheme> CreateBarterBarterScheme(IEnumerable<Item> offerItems, BarterDetails barterConfig)
|
||||||
IEnumerable<Item> offerItems,
|
|
||||||
BarterDetails barterConfig
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get flea price of item being sold
|
// Get flea price of item being sold
|
||||||
var priceOfOfferItem = ragfairPriceService.GetDynamicOfferPriceForOffer(
|
var priceOfOfferItem = ragfairPriceService.GetDynamicOfferPriceForOffer(offerItems, Money.ROUBLES, false);
|
||||||
offerItems,
|
|
||||||
Money.ROUBLES,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
// Don't make items under a designated rouble value into barter offers
|
// Don't make items under a designated rouble value into barter offers
|
||||||
if (priceOfOfferItem < barterConfig.MinRoubleCostToBecomeBarter)
|
if (priceOfOfferItem < barterConfig.MinRoubleCostToBecomeBarter)
|
||||||
@@ -1026,17 +875,13 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a randomised number of barter items to list offer for
|
// Get a randomised number of barter items to list offer for
|
||||||
var barterItemCount = randomUtil.GetInt(
|
var barterItemCount = randomUtil.GetInt(barterConfig.ItemCountMin, barterConfig.ItemCountMax);
|
||||||
barterConfig.ItemCountMin,
|
|
||||||
barterConfig.ItemCountMax
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get desired cost of individual item offer will be listed for e.g. offer = 15k, item count = 3, desired item cost = 5k
|
// Get desired cost of individual item offer will be listed for e.g. offer = 15k, item count = 3, desired item cost = 5k
|
||||||
var desiredItemCostRouble = Math.Round(priceOfOfferItem / barterItemCount);
|
var desiredItemCostRouble = Math.Round(priceOfOfferItem / barterItemCount);
|
||||||
|
|
||||||
// Rouble amount to go above/below when looking for an item (Wiggle cost of item a little)
|
// Rouble amount to go above/below when looking for an item (Wiggle cost of item a little)
|
||||||
var offerCostVarianceRoubles =
|
var offerCostVarianceRoubles = desiredItemCostRouble * barterConfig.PriceRangeVariancePercent / 100;
|
||||||
desiredItemCostRouble * barterConfig.PriceRangeVariancePercent / 100;
|
|
||||||
|
|
||||||
// Dict of items and their flea price (cached on first use)
|
// Dict of items and their flea price (cached on first use)
|
||||||
var itemFleaPrices = GetFleaPricesAsArray();
|
var itemFleaPrices = GetFleaPricesAsArray();
|
||||||
@@ -1047,9 +892,7 @@ public class RagfairOfferGenerator(
|
|||||||
var rootOfferItem = offerItems.FirstOrDefault();
|
var rootOfferItem = offerItems.FirstOrDefault();
|
||||||
|
|
||||||
var itemsInsidePriceBounds = itemFleaPrices.Where(itemAndPrice =>
|
var itemsInsidePriceBounds = itemFleaPrices.Where(itemAndPrice =>
|
||||||
itemAndPrice.Price >= min
|
itemAndPrice.Price >= min && itemAndPrice.Price <= max && itemAndPrice.Tpl != rootOfferItem.Template // Don't allow the item being sold to be chosen
|
||||||
&& itemAndPrice.Price <= max
|
|
||||||
&& itemAndPrice.Tpl != rootOfferItem.Template // Don't allow the item being sold to be chosen
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// No items on flea have a matching price, fall back to currency
|
// No items on flea have a matching price, fall back to currency
|
||||||
@@ -1096,19 +939,10 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="isPackOffer"> Is the barter scheme being created for a pack offer </param>
|
/// <param name="isPackOffer"> Is the barter scheme being created for a pack offer </param>
|
||||||
/// <param name="multiplier"> What to multiply the resulting price by </param>
|
/// <param name="multiplier"> What to multiply the resulting price by </param>
|
||||||
/// <returns> Barter scheme for offer </returns>
|
/// <returns> Barter scheme for offer </returns>
|
||||||
protected List<BarterScheme> CreateCurrencyBarterScheme(
|
protected List<BarterScheme> CreateCurrencyBarterScheme(IEnumerable<Item> offerWithChildren, bool isPackOffer, double multiplier = 1)
|
||||||
IEnumerable<Item> offerWithChildren,
|
|
||||||
bool isPackOffer,
|
|
||||||
double multiplier = 1
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var currency = ragfairServerHelper.GetDynamicOfferCurrency();
|
var currency = ragfairServerHelper.GetDynamicOfferCurrency();
|
||||||
var price =
|
var price = ragfairPriceService.GetDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer) * multiplier;
|
||||||
ragfairPriceService.GetDynamicOfferPriceForOffer(
|
|
||||||
offerWithChildren,
|
|
||||||
currency,
|
|
||||||
isPackOffer
|
|
||||||
) * multiplier;
|
|
||||||
|
|
||||||
return [new BarterScheme { Count = price, Template = currency }];
|
return [new BarterScheme { Count = price, Template = currency }];
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-83
@@ -60,25 +60,15 @@ public class CompletionQuestGenerator(
|
|||||||
|
|
||||||
if (quest is null)
|
if (quest is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error("Quest template null when attempting to create completion operational task.");
|
||||||
"Quest template null when attempting to create completion operational task."
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter the items.json items to items the player must retrieve to complete quest: shouldn't be a quest item or "non-existent"
|
// Filter the items.json items to items the player must retrieve to complete quest: shouldn't be a quest item or "non-existent"
|
||||||
var itemsToRetrievePool = GetItemsToRetrievePool(
|
var itemsToRetrievePool = GetItemsToRetrievePool(completionConfig, repeatableConfig.RewardBlacklist);
|
||||||
completionConfig,
|
|
||||||
repeatableConfig.RewardBlacklist
|
|
||||||
);
|
|
||||||
|
|
||||||
// Filter items within our budget
|
// Filter items within our budget
|
||||||
var (hashSet, budget) = GetItemsWithinBudget(
|
var (hashSet, budget) = GetItemsWithinBudget(pmcLevel, levelsConfig, roublesConfig, itemsToRetrievePool);
|
||||||
pmcLevel,
|
|
||||||
levelsConfig,
|
|
||||||
roublesConfig,
|
|
||||||
itemsToRetrievePool
|
|
||||||
);
|
|
||||||
itemsToRetrievePool = hashSet;
|
itemsToRetrievePool = hashSet;
|
||||||
|
|
||||||
// We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as
|
// We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as
|
||||||
@@ -96,22 +86,12 @@ public class CompletionQuestGenerator(
|
|||||||
// Filtering too harsh
|
// Filtering too harsh
|
||||||
if (itemsToRetrievePool.Count == 0)
|
if (itemsToRetrievePool.Count == 0)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-completion_quest_whitelist_too_small_or_blacklist_too_restrictive"));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-completion_quest_whitelist_too_small_or_blacklist_too_restrictive"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedItems = GenerateAvailableForFinish(
|
var selectedItems = GenerateAvailableForFinish(quest, completionConfig, repeatableConfig, itemsToRetrievePool.ToList(), budget);
|
||||||
quest,
|
|
||||||
completionConfig,
|
|
||||||
repeatableConfig,
|
|
||||||
itemsToRetrievePool.ToList(),
|
|
||||||
budget
|
|
||||||
);
|
|
||||||
|
|
||||||
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(
|
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(
|
||||||
pmcLevel,
|
pmcLevel,
|
||||||
@@ -131,10 +111,7 @@ public class CompletionQuestGenerator(
|
|||||||
/// <param name="completionConfig">Completion quest type config</param>
|
/// <param name="completionConfig">Completion quest type config</param>
|
||||||
/// <param name="itemTplBlacklist">Item tpls to not add to pool</param>
|
/// <param name="itemTplBlacklist">Item tpls to not add to pool</param>
|
||||||
/// <returns>Set of item tpls</returns>
|
/// <returns>Set of item tpls</returns>
|
||||||
protected HashSet<MongoId> GetItemsToRetrievePool(
|
protected HashSet<MongoId> GetItemsToRetrievePool(Completion completionConfig, HashSet<MongoId> itemTplBlacklist)
|
||||||
Completion completionConfig,
|
|
||||||
HashSet<MongoId> itemTplBlacklist
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get seasonal items that should not be added to pool as seasonal event is not active
|
// Get seasonal items that should not be added to pool as seasonal event is not active
|
||||||
var seasonalItems = seasonalEventService.GetInactiveSeasonalEventItems();
|
var seasonalItems = seasonalEventService.GetInactiveSeasonalEventItems();
|
||||||
@@ -184,19 +161,12 @@ public class CompletionQuestGenerator(
|
|||||||
{
|
{
|
||||||
// Be fair, don't value the items be more expensive than the reward
|
// Be fair, don't value the items be more expensive than the reward
|
||||||
var multiplier = randomUtil.GetDouble(0.5, 1);
|
var multiplier = randomUtil.GetDouble(0.5, 1);
|
||||||
var roublesBudget = Math.Floor(
|
var roublesBudget = Math.Floor(mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) * multiplier);
|
||||||
mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) * multiplier
|
|
||||||
);
|
|
||||||
|
|
||||||
// Make sure there is always a 5000 rouble budget available for selection
|
// Make sure there is always a 5000 rouble budget available for selection
|
||||||
roublesBudget = Math.Max(roublesBudget, 5000d);
|
roublesBudget = Math.Max(roublesBudget, 5000d);
|
||||||
|
|
||||||
return (
|
return (itemsToRetrievePool.Where(itemTpl => itemHelper.GetItemPrice(itemTpl) < roublesBudget).ToHashSet(), roublesBudget);
|
||||||
itemsToRetrievePool
|
|
||||||
.Where(itemTpl => itemHelper.GetItemPrice(itemTpl) < roublesBudget)
|
|
||||||
.ToHashSet(),
|
|
||||||
roublesBudget
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -205,14 +175,9 @@ public class CompletionQuestGenerator(
|
|||||||
/// <param name="itemSelection">Item selection to filter</param>
|
/// <param name="itemSelection">Item selection to filter</param>
|
||||||
/// <param name="pmcLevel">Level of pmc</param>
|
/// <param name="pmcLevel">Level of pmc</param>
|
||||||
/// <returns>Filtered selection, or original if null or empty</returns>
|
/// <returns>Filtered selection, or original if null or empty</returns>
|
||||||
protected HashSet<MongoId> GetWhitelistedItemSelection(
|
protected HashSet<MongoId> GetWhitelistedItemSelection(HashSet<MongoId> itemSelection, int pmcLevel)
|
||||||
HashSet<MongoId> itemSelection,
|
|
||||||
int pmcLevel
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var itemWhitelist = databaseService
|
var itemWhitelist = databaseService.GetTemplates().RepeatableQuests?.Data?.Completion?.ItemsWhitelist;
|
||||||
.GetTemplates()
|
|
||||||
.RepeatableQuests?.Data?.Completion?.ItemsWhitelist;
|
|
||||||
|
|
||||||
// Whitelist doesn't exist or is empty, return original
|
// Whitelist doesn't exist or is empty, return original
|
||||||
if (itemWhitelist is null || itemWhitelist.Count == 0)
|
if (itemWhitelist is null || itemWhitelist.Count == 0)
|
||||||
@@ -221,17 +186,13 @@ public class CompletionQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter and concatenate items according to current player level
|
// Filter and concatenate items according to current player level
|
||||||
var itemIdsWhitelisted = itemWhitelist
|
var itemIdsWhitelisted = itemWhitelist.Where(p => p.MinPlayerLevel <= pmcLevel).SelectMany(x => x.ItemIds).ToHashSet(); //.Aggregate((a, p) => a.Concat(p.ItemIds), []);
|
||||||
.Where(p => p.MinPlayerLevel <= pmcLevel)
|
|
||||||
.SelectMany(x => x.ItemIds)
|
|
||||||
.ToHashSet(); //.Aggregate((a, p) => a.Concat(p.ItemIds), []);
|
|
||||||
|
|
||||||
var filteredSelection = itemSelection
|
var filteredSelection = itemSelection
|
||||||
.Where(x =>
|
.Where(x =>
|
||||||
{
|
{
|
||||||
// Whitelist can contain item tpls and item base type ids
|
// Whitelist can contain item tpls and item base type ids
|
||||||
return itemIdsWhitelisted.Any(v => itemHelper.IsOfBaseclass(x, v))
|
return itemIdsWhitelisted.Any(v => itemHelper.IsOfBaseclass(x, v)) || itemIdsWhitelisted.Contains(x);
|
||||||
|| itemIdsWhitelisted.Contains(x);
|
|
||||||
})
|
})
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
|
|
||||||
@@ -248,14 +209,9 @@ public class CompletionQuestGenerator(
|
|||||||
/// <param name="itemSelection">Item selection to filter</param>
|
/// <param name="itemSelection">Item selection to filter</param>
|
||||||
/// <param name="pmcLevel">Level of pmc</param>
|
/// <param name="pmcLevel">Level of pmc</param>
|
||||||
/// <returns>Filtered selection, or original if null or empty</returns>
|
/// <returns>Filtered selection, or original if null or empty</returns>
|
||||||
protected HashSet<MongoId> GetBlacklistedItemSelection(
|
protected HashSet<MongoId> GetBlacklistedItemSelection(HashSet<MongoId> itemSelection, int pmcLevel)
|
||||||
HashSet<MongoId> itemSelection,
|
|
||||||
int pmcLevel
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var itemBlacklist = databaseService
|
var itemBlacklist = databaseService.GetTemplates().RepeatableQuests?.Data?.Completion?.ItemsBlacklist;
|
||||||
.GetTemplates()
|
|
||||||
.RepeatableQuests?.Data?.Completion?.ItemsBlacklist;
|
|
||||||
|
|
||||||
// Blacklist doesn't exist or is empty, return original
|
// Blacklist doesn't exist or is empty, return original
|
||||||
if (itemBlacklist is null || itemBlacklist.Count == 0)
|
if (itemBlacklist is null || itemBlacklist.Count == 0)
|
||||||
@@ -272,8 +228,7 @@ public class CompletionQuestGenerator(
|
|||||||
var filteredSelection = itemSelection
|
var filteredSelection = itemSelection
|
||||||
.Where(x =>
|
.Where(x =>
|
||||||
{
|
{
|
||||||
return itemIdsBlacklisted.All(v => !itemHelper.IsOfBaseclass(x, v))
|
return itemIdsBlacklisted.All(v => !itemHelper.IsOfBaseclass(x, v)) || !itemIdsBlacklisted.Contains(x);
|
||||||
|| !itemIdsBlacklisted.Contains(x);
|
|
||||||
})
|
})
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
|
|
||||||
@@ -323,10 +278,7 @@ public class CompletionQuestGenerator(
|
|||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
localisationService.GetText(
|
localisationService.GetText("repeatable-no_reward_item_found_in_price_range", new { minPrice = 0, roublesBudget })
|
||||||
"repeatable-no_reward_item_found_in_price_range",
|
|
||||||
new { minPrice = 0, roublesBudget }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return chosenRequirementItemsTpls;
|
return chosenRequirementItemsTpls;
|
||||||
@@ -356,17 +308,13 @@ public class CompletionQuestGenerator(
|
|||||||
|
|
||||||
// Push a CompletionCondition with the item and the amount of the item into quest
|
// Push a CompletionCondition with the item and the amount of the item into quest
|
||||||
chosenRequirementItemsTpls.Add(tplChosen);
|
chosenRequirementItemsTpls.Add(tplChosen);
|
||||||
quest.Conditions.AvailableForFinish.Add(
|
quest.Conditions.AvailableForFinish.Add(GenerateCondition(tplChosen, value, repeatableConfig.QuestConfig.Completion));
|
||||||
GenerateCondition(tplChosen, value, repeatableConfig.QuestConfig.Completion)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Is there budget left for more items
|
// Is there budget left for more items
|
||||||
if (roublesBudget > 0)
|
if (roublesBudget > 0)
|
||||||
{
|
{
|
||||||
// Reduce item pool to fit budget
|
// Reduce item pool to fit budget
|
||||||
itemSelection = itemSelection
|
itemSelection = itemSelection.Where(tpl => itemHelper.GetItemPrice(tpl) < roublesBudget).ToList();
|
||||||
.Where(tpl => itemHelper.GetItemPrice(tpl) < roublesBudget)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (itemSelection.Count == 0)
|
if (itemSelection.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -393,22 +341,12 @@ public class CompletionQuestGenerator(
|
|||||||
/// <param name="value">Amount of items of this specific type to request</param>
|
/// <param name="value">Amount of items of this specific type to request</param>
|
||||||
/// <param name="completionConfig">Completion config from quest.json</param>
|
/// <param name="completionConfig">Completion config from quest.json</param>
|
||||||
/// <returns>object of "Completion"-condition</returns>
|
/// <returns>object of "Completion"-condition</returns>
|
||||||
protected QuestCondition GenerateCondition(
|
protected QuestCondition GenerateCondition(MongoId itemTpl, double value, Completion completionConfig)
|
||||||
MongoId itemTpl,
|
|
||||||
double value,
|
|
||||||
Completion completionConfig
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var onlyFoundInRaid = completionConfig.RequiredItemsAreFiR;
|
var onlyFoundInRaid = completionConfig.RequiredItemsAreFiR;
|
||||||
var minDurability = itemHelper.IsOfBaseclasses(
|
var minDurability = itemHelper.IsOfBaseclasses(itemTpl, [BaseClasses.WEAPON, BaseClasses.ARMOR])
|
||||||
itemTpl,
|
|
||||||
[BaseClasses.WEAPON, BaseClasses.ARMOR]
|
|
||||||
)
|
|
||||||
? randomUtil.GetArrayValue(
|
? randomUtil.GetArrayValue(
|
||||||
[
|
[completionConfig.RequiredItemMinDurabilityMinMax.Min, completionConfig.RequiredItemMinDurabilityMinMax.Max]
|
||||||
completionConfig.RequiredItemMinDurabilityMinMax.Min,
|
|
||||||
completionConfig.RequiredItemMinDurabilityMinMax.Max,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|||||||
+49
-174
@@ -35,14 +35,13 @@ public class EliminationQuestGenerator(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body parts to present to the client as opposed to the body part information in quest data.
|
/// Body parts to present to the client as opposed to the body part information in quest data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly FrozenDictionary<string, List<string>> _bodyPartsToClient =
|
private static readonly FrozenDictionary<string, List<string>> _bodyPartsToClient = new Dictionary<string, List<string>>
|
||||||
new Dictionary<string, List<string>>
|
{
|
||||||
{
|
{ BodyParts.Arms, [BodyParts.LeftArm, BodyParts.RightArm] },
|
||||||
{ BodyParts.Arms, [BodyParts.LeftArm, BodyParts.RightArm] },
|
{ BodyParts.Legs, [BodyParts.LeftLeg, BodyParts.RightLeg] },
|
||||||
{ BodyParts.Legs, [BodyParts.LeftLeg, BodyParts.RightLeg] },
|
{ BodyParts.Head, [BodyParts.Head] },
|
||||||
{ BodyParts.Head, [BodyParts.Head] },
|
{ BodyParts.Chest, [BodyParts.Chest, BodyParts.Stomach] },
|
||||||
{ BodyParts.Chest, [BodyParts.Chest, BodyParts.Stomach] },
|
}.ToFrozenDictionary();
|
||||||
}.ToFrozenDictionary();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MaxDistDifficulty is defined by 2, this could be a tuning parameter if we don't like the reward generation
|
/// MaxDistDifficulty is defined by 2, this could be a tuning parameter if we don't like the reward generation
|
||||||
@@ -83,9 +82,7 @@ public class EliminationQuestGenerator(
|
|||||||
var generationData = GetGenerationData(repeatableConfig, pmcLevel);
|
var generationData = GetGenerationData(repeatableConfig, pmcLevel);
|
||||||
if (generationData is null)
|
if (generationData is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-eliminationQuestGenerationData-is-null"));
|
||||||
localisationService.GetText("repeatable-eliminationQuestGenerationData-is-null")
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,18 +111,13 @@ public class EliminationQuestGenerator(
|
|||||||
|
|
||||||
// Target on bodyPart max. difficulty is that of the least probable element
|
// Target on bodyPart max. difficulty is that of the least probable element
|
||||||
var maxTargetDifficulty = 1 / generationData.TargetsConfig.MinProbability();
|
var maxTargetDifficulty = 1 / generationData.TargetsConfig.MinProbability();
|
||||||
var maxBodyPartsDifficulty =
|
var maxBodyPartsDifficulty = generationData.EliminationConfig.MinKills / generationData.BodyPartsConfig.MinProbability();
|
||||||
generationData.EliminationConfig.MinKills
|
|
||||||
/ generationData.BodyPartsConfig.MinProbability();
|
|
||||||
|
|
||||||
var maxKillDifficulty = generationData.EliminationConfig.MaxKills;
|
var maxKillDifficulty = generationData.EliminationConfig.MaxKills;
|
||||||
var targetPool = questTypePool.Pool.Elimination;
|
var targetPool = questTypePool.Pool.Elimination;
|
||||||
|
|
||||||
// Get a random bot type to eliminate
|
// Get a random bot type to eliminate
|
||||||
var (botTypeToEliminate, targetsConfig) = GetBotTypeToEliminate(
|
var (botTypeToEliminate, targetsConfig) = GetBotTypeToEliminate(generationData, questTypePool);
|
||||||
generationData,
|
|
||||||
questTypePool
|
|
||||||
);
|
|
||||||
if (botTypeToEliminate is null || targetsConfig is null)
|
if (botTypeToEliminate is null || targetsConfig is null)
|
||||||
{
|
{
|
||||||
logger.Warning(localisationService.GetText("repeatable-no-bot-types-remain"));
|
logger.Warning(localisationService.GetText("repeatable-no-bot-types-remain"));
|
||||||
@@ -143,30 +135,18 @@ public class EliminationQuestGenerator(
|
|||||||
// Try and get a target location pool for this bot type
|
// Try and get a target location pool for this bot type
|
||||||
if (!targetPool.Targets.TryGetValue(botTypeToEliminate, out var targetLocationPool))
|
if (!targetPool.Targets.TryGetValue(botTypeToEliminate, out var targetLocationPool))
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-unable-get-target-pool", botTypeToEliminate));
|
||||||
localisationService.GetText("repeatable-unable-get-target-pool", botTypeToEliminate)
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try and get a location key for this quest
|
// Try and get a location key for this quest
|
||||||
if (
|
if (
|
||||||
!TryGetLocationKey(
|
!TryGetLocationKey(generationData, targetPool, botTypeToEliminate, targetLocationPool.Locations, out var locationKey)
|
||||||
generationData,
|
|| locationKey is null
|
||||||
targetPool,
|
|
||||||
botTypeToEliminate,
|
|
||||||
targetLocationPool.Locations,
|
|
||||||
out var locationKey
|
|
||||||
) || locationKey is null
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-unable-get-location-key", botTypeToEliminate));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-unable-get-location-key",
|
|
||||||
botTypeToEliminate
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -174,9 +154,7 @@ public class EliminationQuestGenerator(
|
|||||||
// Generate a body part, make sure we ref the body part difficulty so it can be adjusted
|
// Generate a body part, make sure we ref the body part difficulty so it can be adjusted
|
||||||
var bodyPartsToClient = new List<string>();
|
var bodyPartsToClient = new List<string>();
|
||||||
var bodyPartDifficulty = 0d;
|
var bodyPartDifficulty = 0d;
|
||||||
var generateBodyParts = randomUtil.GetChance100(
|
var generateBodyParts = randomUtil.GetChance100(generationData.EliminationConfig.BodyPartChance);
|
||||||
generationData.EliminationConfig.BodyPartChance
|
|
||||||
);
|
|
||||||
if (generateBodyParts)
|
if (generateBodyParts)
|
||||||
{
|
{
|
||||||
// draw the target body part and calculate the difficulty factor
|
// draw the target body part and calculate the difficulty factor
|
||||||
@@ -184,12 +162,7 @@ public class EliminationQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw a distance condition
|
// Draw a distance condition
|
||||||
var isDistanceRequirementAllowed = IsDistanceRequirementAllowed(
|
var isDistanceRequirementAllowed = IsDistanceRequirementAllowed(generationData, botTypeToEliminate, locationKey, targetsConfig);
|
||||||
generationData,
|
|
||||||
botTypeToEliminate,
|
|
||||||
locationKey,
|
|
||||||
targetsConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
int? distance = null;
|
int? distance = null;
|
||||||
var distanceDifficulty = 0;
|
var distanceDifficulty = 0;
|
||||||
@@ -204,9 +177,7 @@ public class EliminationQuestGenerator(
|
|||||||
|
|
||||||
string? allowedWeaponsCategory = null;
|
string? allowedWeaponsCategory = null;
|
||||||
|
|
||||||
var generateWeaponCategoryRequirement = randomUtil.GetChance100(
|
var generateWeaponCategoryRequirement = randomUtil.GetChance100(generationData.EliminationConfig.WeaponCategoryRequirementChance);
|
||||||
generationData.EliminationConfig.WeaponCategoryRequirementChance
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate a weapon category requirement
|
// Generate a weapon category requirement
|
||||||
if (generateWeaponCategoryRequirement)
|
if (generateWeaponCategoryRequirement)
|
||||||
@@ -217,9 +188,7 @@ public class EliminationQuestGenerator(
|
|||||||
// Only allow a specific weapon requirement if a weapon category was not chosen
|
// Only allow a specific weapon requirement if a weapon category was not chosen
|
||||||
MongoId? allowedWeapon = null;
|
MongoId? allowedWeapon = null;
|
||||||
|
|
||||||
var generateWeaponRequirement = randomUtil.GetChance100(
|
var generateWeaponRequirement = randomUtil.GetChance100(generationData.EliminationConfig.WeaponRequirementChance);
|
||||||
generationData.EliminationConfig.WeaponRequirementChance
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate a weapon requirement
|
// Generate a weapon requirement
|
||||||
if (!generateWeaponCategoryRequirement && generateWeaponRequirement)
|
if (!generateWeaponCategoryRequirement && generateWeaponRequirement)
|
||||||
@@ -228,11 +197,7 @@ public class EliminationQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw how many npm kills are required
|
// Draw how many npm kills are required
|
||||||
var desiredKillCount = GetEliminationKillCount(
|
var desiredKillCount = GetEliminationKillCount(botTypeToEliminate, targetsConfig, generationData.EliminationConfig);
|
||||||
botTypeToEliminate,
|
|
||||||
targetsConfig,
|
|
||||||
generationData.EliminationConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
var killDifficulty = desiredKillCount;
|
var killDifficulty = desiredKillCount;
|
||||||
|
|
||||||
@@ -261,12 +226,7 @@ public class EliminationQuestGenerator(
|
|||||||
|
|
||||||
if (quest is null)
|
if (quest is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-quest_generation_failed_no_template", "elimination"));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-quest_generation_failed_no_template",
|
|
||||||
"elimination"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -285,19 +245,11 @@ public class EliminationQuestGenerator(
|
|||||||
if (locationKey != "any")
|
if (locationKey != "any")
|
||||||
{
|
{
|
||||||
var locationId = Enum.Parse<ELocationName>(locationKey);
|
var locationId = Enum.Parse<ELocationName>(locationKey);
|
||||||
availableForFinishCondition.Counter.Conditions.Add(
|
availableForFinishCondition.Counter.Conditions.Add(GenerateEliminationLocation(generationData.LocationsConfig[locationId]));
|
||||||
GenerateEliminationLocation(generationData.LocationsConfig[locationId])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
availableForFinishCondition.Counter.Conditions.Add(
|
availableForFinishCondition.Counter.Conditions.Add(
|
||||||
GenerateEliminationCondition(
|
GenerateEliminationCondition(botTypeToEliminate, bodyPartsToClient, distance, allowedWeapon, allowedWeaponsCategory)
|
||||||
botTypeToEliminate,
|
|
||||||
bodyPartsToClient,
|
|
||||||
distance,
|
|
||||||
allowedWeapon,
|
|
||||||
allowedWeaponsCategory
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
availableForFinishCondition.Value = desiredKillCount;
|
availableForFinishCondition.Value = desiredKillCount;
|
||||||
availableForFinishCondition.Id = new MongoId();
|
availableForFinishCondition.Id = new MongoId();
|
||||||
@@ -316,15 +268,9 @@ public class EliminationQuestGenerator(
|
|||||||
return quest;
|
return quest;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EliminationQuestGenerationData? GetGenerationData(
|
protected EliminationQuestGenerationData? GetGenerationData(RepeatableQuestConfig repeatableConfig, int pmcLevel)
|
||||||
RepeatableQuestConfig repeatableConfig,
|
|
||||||
int pmcLevel
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var eliminationConfig = repeatableQuestHelper.GetEliminationConfigByPmcLevel(
|
var eliminationConfig = repeatableQuestHelper.GetEliminationConfigByPmcLevel(pmcLevel, repeatableConfig);
|
||||||
pmcLevel,
|
|
||||||
repeatableConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
if (eliminationConfig is null)
|
if (eliminationConfig is null)
|
||||||
{
|
{
|
||||||
@@ -334,22 +280,13 @@ public class EliminationQuestGenerator(
|
|||||||
|
|
||||||
var locationsConfig = repeatableConfig.Locations;
|
var locationsConfig = repeatableConfig.Locations;
|
||||||
|
|
||||||
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(
|
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(cloner, eliminationConfig.Targets);
|
||||||
cloner,
|
var bodyPartsConfig = new ProbabilityObjectArray<string, List<string>>(cloner, eliminationConfig.BodyParts);
|
||||||
eliminationConfig.Targets
|
|
||||||
);
|
|
||||||
var bodyPartsConfig = new ProbabilityObjectArray<string, List<string>>(
|
|
||||||
cloner,
|
|
||||||
eliminationConfig.BodyParts
|
|
||||||
);
|
|
||||||
var weaponCategoryRequirementConfig = new ProbabilityObjectArray<string, List<MongoId>>(
|
var weaponCategoryRequirementConfig = new ProbabilityObjectArray<string, List<MongoId>>(
|
||||||
cloner,
|
cloner,
|
||||||
eliminationConfig.WeaponCategoryRequirements
|
eliminationConfig.WeaponCategoryRequirements
|
||||||
);
|
);
|
||||||
var weaponRequirementConfig = new ProbabilityObjectArray<string, List<MongoId>>(
|
var weaponRequirementConfig = new ProbabilityObjectArray<string, List<MongoId>>(cloner, eliminationConfig.WeaponRequirements);
|
||||||
cloner,
|
|
||||||
eliminationConfig.WeaponRequirements
|
|
||||||
);
|
|
||||||
|
|
||||||
return new EliminationQuestGenerationData(
|
return new EliminationQuestGenerationData(
|
||||||
eliminationConfig,
|
eliminationConfig,
|
||||||
@@ -374,9 +311,7 @@ public class EliminationQuestGenerator(
|
|||||||
{
|
{
|
||||||
var targetPool = questTypePool.Pool.Elimination;
|
var targetPool = questTypePool.Pool.Elimination;
|
||||||
|
|
||||||
var targetsConfig = generationData.TargetsConfig.Filter(x =>
|
var targetsConfig = generationData.TargetsConfig.Filter(x => targetPool.Targets.ContainsKey(x.Key));
|
||||||
targetPool.Targets.ContainsKey(x.Key)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (targetsConfig.Count != 0 && !targetsConfig.All(x => x.Data?.IsBoss ?? false))
|
if (targetsConfig.Count != 0 && !targetsConfig.All(x => x.Data?.IsBoss ?? false))
|
||||||
{
|
{
|
||||||
@@ -407,9 +342,7 @@ public class EliminationQuestGenerator(
|
|||||||
out string? locationKey
|
out string? locationKey
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var useSpecificLocation = randomUtil.GetChance100(
|
var useSpecificLocation = randomUtil.GetChance100(generationData.EliminationConfig.SpecificLocationChance);
|
||||||
generationData.EliminationConfig.SpecificLocationChance
|
|
||||||
);
|
|
||||||
|
|
||||||
switch (useSpecificLocation)
|
switch (useSpecificLocation)
|
||||||
{
|
{
|
||||||
@@ -432,11 +365,7 @@ public class EliminationQuestGenerator(
|
|||||||
if (locations.Count == 0)
|
if (locations.Count == 0)
|
||||||
{
|
{
|
||||||
// Never should reach this if everything works out
|
// Never should reach this if everything works out
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("quest-repeatable_elimination_generation_failed_please_report"));
|
||||||
localisationService.GetText(
|
|
||||||
"quest-repeatable_elimination_generation_failed_please_report"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
locationKey = null;
|
locationKey = null;
|
||||||
return false;
|
return false;
|
||||||
@@ -459,9 +388,7 @@ public class EliminationQuestGenerator(
|
|||||||
var tmpKey = locationKey;
|
var tmpKey = locationKey;
|
||||||
|
|
||||||
// Filter locations bot can be killed on to just those not chosen by key
|
// Filter locations bot can be killed on to just those not chosen by key
|
||||||
possibleLocationPool.Locations = possibleLocationPool
|
possibleLocationPool.Locations = possibleLocationPool.Locations?.Where(location => location != tmpKey).ToList();
|
||||||
.Locations?.Where(location => location != tmpKey)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// None left after filtering
|
// None left after filtering
|
||||||
if (possibleLocationPool.Locations?.Count is null or 0)
|
if (possibleLocationPool.Locations?.Count is null or 0)
|
||||||
@@ -480,10 +407,7 @@ public class EliminationQuestGenerator(
|
|||||||
/// <param name="generationData">Generation data</param>
|
/// <param name="generationData">Generation data</param>
|
||||||
/// <param name="bodyPartDifficulty">BodyPartDifficulty to modify based on selection</param>
|
/// <param name="bodyPartDifficulty">BodyPartDifficulty to modify based on selection</param>
|
||||||
/// <returns>List of selected body parts</returns>
|
/// <returns>List of selected body parts</returns>
|
||||||
protected List<string> GenerateBodyParts(
|
protected List<string> GenerateBodyParts(EliminationQuestGenerationData generationData, ref double bodyPartDifficulty)
|
||||||
EliminationQuestGenerationData generationData,
|
|
||||||
ref double bodyPartDifficulty
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// if we add a bodyPart condition, we draw randomly one or two parts
|
// if we add a bodyPart condition, we draw randomly one or two parts
|
||||||
// each bodyPart of the BODYPARTS ProbabilityObjectArray includes the string(s)
|
// each bodyPart of the BODYPARTS ProbabilityObjectArray includes the string(s)
|
||||||
@@ -533,9 +457,7 @@ public class EliminationQuestGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// This location is can be chosen for a distance requirement
|
// This location is can be chosen for a distance requirement
|
||||||
var whitelisted = !generationData.EliminationConfig.DistLocationBlacklist.Contains(
|
var whitelisted = !generationData.EliminationConfig.DistLocationBlacklist.Contains(locationKey);
|
||||||
locationKey
|
|
||||||
);
|
|
||||||
|
|
||||||
// We're not whitelisted, exit early to avoid doing a roll for no reason
|
// We're not whitelisted, exit early to avoid doing a roll for no reason
|
||||||
if (!whitelisted)
|
if (!whitelisted)
|
||||||
@@ -544,9 +466,7 @@ public class EliminationQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Are we allowed a distance condition by chance?
|
// Are we allowed a distance condition by chance?
|
||||||
var isAllowedByChance = randomUtil.GetChance100(
|
var isAllowedByChance = randomUtil.GetChance100(generationData.EliminationConfig.DistanceProbability);
|
||||||
generationData.EliminationConfig.DistanceProbability
|
|
||||||
);
|
|
||||||
|
|
||||||
// Not allowed by chance, return early.
|
// Not allowed by chance, return early.
|
||||||
// We now just assume we rolled this condition and don't take it into account anymore.
|
// We now just assume we rolled this condition and don't take it into account anymore.
|
||||||
@@ -567,25 +487,15 @@ public class EliminationQuestGenerator(
|
|||||||
.GetDictionary()
|
.GetDictionary()
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value)
|
||||||
.Where(location => location.Base?.Id != null)
|
.Where(location => location.Base?.Id != null)
|
||||||
.Select(location => new
|
.Select(location => new { location.Base.Id, BossSpawn = location.Base.BossLocationSpawn });
|
||||||
{
|
|
||||||
location.Base.Id,
|
|
||||||
BossSpawn = location.Base.BossLocationSpawn,
|
|
||||||
});
|
|
||||||
|
|
||||||
// filter for the current boss to spawn on map
|
// filter for the current boss to spawn on map
|
||||||
var thisBossSpawns = bossSpawns
|
var thisBossSpawns = bossSpawns
|
||||||
.Select(x => new
|
.Select(x => new { x.Id, BossSpawn = x.BossSpawn.Where(e => e.BossName == botTypeToEliminate) })
|
||||||
{
|
|
||||||
x.Id,
|
|
||||||
BossSpawn = x.BossSpawn.Where(e => e.BossName == botTypeToEliminate),
|
|
||||||
})
|
|
||||||
.Where(x => x.BossSpawn.Any());
|
.Where(x => x.BossSpawn.Any());
|
||||||
|
|
||||||
// remove blacklisted locations
|
// remove blacklisted locations
|
||||||
var allowedSpawns = thisBossSpawns.Where(x =>
|
var allowedSpawns = thisBossSpawns.Where(x => !generationData.EliminationConfig.DistLocationBlacklist.Contains(x.Id));
|
||||||
!generationData.EliminationConfig.DistLocationBlacklist.Contains(x.Id)
|
|
||||||
);
|
|
||||||
|
|
||||||
// if the boss spawns on non-blacklisted locations and the current location is allowed,
|
// if the boss spawns on non-blacklisted locations and the current location is allowed,
|
||||||
// we can generate a distance kill requirement
|
// we can generate a distance kill requirement
|
||||||
@@ -603,19 +513,13 @@ public class EliminationQuestGenerator(
|
|||||||
var distance = (int)
|
var distance = (int)
|
||||||
Math.Floor(
|
Math.Floor(
|
||||||
Math.Abs(randomUtil.Random.NextDouble() - randomUtil.Random.NextDouble())
|
Math.Abs(randomUtil.Random.NextDouble() - randomUtil.Random.NextDouble())
|
||||||
* (
|
* (1 + generationData.EliminationConfig.MaxDistance - generationData.EliminationConfig.MinDistance)
|
||||||
1
|
|
||||||
+ generationData.EliminationConfig.MaxDistance
|
|
||||||
- generationData.EliminationConfig.MinDistance
|
|
||||||
)
|
|
||||||
+ generationData.EliminationConfig.MinDistance
|
+ generationData.EliminationConfig.MinDistance
|
||||||
);
|
);
|
||||||
|
|
||||||
distance = (int)Math.Ceiling((decimal)(distance / 5d)) * 5;
|
distance = (int)Math.Ceiling((decimal)(distance / 5d)) * 5;
|
||||||
|
|
||||||
var distanceDifficulty = (int)(
|
var distanceDifficulty = (int)(MaxDistDifficulty * distance / generationData.EliminationConfig.MaxDistance);
|
||||||
MaxDistDifficulty * distance / generationData.EliminationConfig.MaxDistance
|
|
||||||
);
|
|
||||||
|
|
||||||
return (distance, distanceDifficulty);
|
return (distance, distanceDifficulty);
|
||||||
}
|
}
|
||||||
@@ -626,10 +530,7 @@ public class EliminationQuestGenerator(
|
|||||||
/// <param name="generationData">Generation data</param>
|
/// <param name="generationData">Generation data</param>
|
||||||
/// <param name="distance">Distance to generate it for, pass null if not required</param>
|
/// <param name="distance">Distance to generate it for, pass null if not required</param>
|
||||||
/// <returns>Weapon requirement category selected</returns>
|
/// <returns>Weapon requirement category selected</returns>
|
||||||
protected string? GenerateWeaponCategoryRequirement(
|
protected string? GenerateWeaponCategoryRequirement(EliminationQuestGenerationData generationData, int? distance)
|
||||||
EliminationQuestGenerationData generationData,
|
|
||||||
int? distance
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
switch (distance)
|
switch (distance)
|
||||||
{
|
{
|
||||||
@@ -639,9 +540,7 @@ public class EliminationQuestGenerator(
|
|||||||
HashSet<string> weaponTypeBlacklist = ["Shotgun", "Pistol"];
|
HashSet<string> weaponTypeBlacklist = ["Shotgun", "Pistol"];
|
||||||
|
|
||||||
// Filter out close range weapons from long distance requirement
|
// Filter out close range weapons from long distance requirement
|
||||||
generationData.WeaponCategoryRequirementConfig.RemoveAll(category =>
|
generationData.WeaponCategoryRequirementConfig.RemoveAll(category => weaponTypeBlacklist.Contains(category.Key));
|
||||||
weaponTypeBlacklist.Contains(category.Key)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Filter out long range weapons from close distance requirement
|
// Filter out long range weapons from close distance requirement
|
||||||
@@ -650,9 +549,7 @@ public class EliminationQuestGenerator(
|
|||||||
HashSet<string> weaponTypeBlacklist = ["MarksmanRifle", "DMR"];
|
HashSet<string> weaponTypeBlacklist = ["MarksmanRifle", "DMR"];
|
||||||
|
|
||||||
// Filter out far range weapons from close distance requirement
|
// Filter out far range weapons from close distance requirement
|
||||||
generationData.WeaponCategoryRequirementConfig.RemoveAll(category =>
|
generationData.WeaponCategoryRequirementConfig.RemoveAll(category => weaponTypeBlacklist.Contains(category.Key));
|
||||||
weaponTypeBlacklist.Contains(category.Key)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -669,20 +566,14 @@ public class EliminationQuestGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="generationData">Generation data</param>
|
/// <param name="generationData">Generation data</param>
|
||||||
/// <returns>Weapon to use</returns>
|
/// <returns>Weapon to use</returns>
|
||||||
protected MongoId GenerateSpecificWeaponRequirement(
|
protected MongoId GenerateSpecificWeaponRequirement(EliminationQuestGenerationData generationData)
|
||||||
EliminationQuestGenerationData generationData
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var weaponRequirement = generationData.WeaponRequirementConfig.Draw(1, false);
|
var weaponRequirement = generationData.WeaponRequirementConfig.Draw(1, false);
|
||||||
var specificAllowedWeaponCategory = generationData.WeaponRequirementConfig.Data(
|
var specificAllowedWeaponCategory = generationData.WeaponRequirementConfig.Data(weaponRequirement[0]);
|
||||||
weaponRequirement[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (specificAllowedWeaponCategory?[0] is null)
|
if (specificAllowedWeaponCategory?[0] is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-elimination-specific-weapon-null"));
|
||||||
localisationService.GetText("repeatable-elimination-specific-weapon-null")
|
|
||||||
);
|
|
||||||
return MongoId.Empty();
|
return MongoId.Empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,30 +597,18 @@ public class EliminationQuestGenerator(
|
|||||||
{
|
{
|
||||||
if (targetsConfig.Data(targetKey)?.IsBoss ?? false)
|
if (targetsConfig.Data(targetKey)?.IsBoss ?? false)
|
||||||
{
|
{
|
||||||
return randomUtil.RandInt(
|
return randomUtil.RandInt(eliminationConfig.MinBossKills, eliminationConfig.MaxBossKills + 1);
|
||||||
eliminationConfig.MinBossKills,
|
|
||||||
eliminationConfig.MaxBossKills + 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetsConfig.Data(targetKey)?.IsPmc ?? false)
|
if (targetsConfig.Data(targetKey)?.IsPmc ?? false)
|
||||||
{
|
{
|
||||||
return randomUtil.RandInt(
|
return randomUtil.RandInt(eliminationConfig.MinPmcKills, eliminationConfig.MaxPmcKills + 1);
|
||||||
eliminationConfig.MinPmcKills,
|
|
||||||
eliminationConfig.MaxPmcKills + 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomUtil.RandInt(eliminationConfig.MinKills, eliminationConfig.MaxKills + 1);
|
return randomUtil.RandInt(eliminationConfig.MinKills, eliminationConfig.MaxKills + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double DifficultyWeighing(
|
protected double DifficultyWeighing(double target, double bodyPart, int dist, int kill, int weaponRequirement)
|
||||||
double target,
|
|
||||||
double bodyPart,
|
|
||||||
int dist,
|
|
||||||
int kill,
|
|
||||||
int weaponRequirement
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
|
return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
|
||||||
}
|
}
|
||||||
@@ -796,11 +675,7 @@ public class EliminationQuestGenerator(
|
|||||||
// Don't allow distance + melee requirement
|
// Don't allow distance + melee requirement
|
||||||
if (distance is not null && allowedWeaponCategory != "5b5f7a0886f77409407a7f96")
|
if (distance is not null && allowedWeaponCategory != "5b5f7a0886f77409407a7f96")
|
||||||
{
|
{
|
||||||
killConditionProps.Distance = new CounterConditionDistance
|
killConditionProps.Distance = new CounterConditionDistance { CompareMethod = ">=", Value = distance.Value };
|
||||||
{
|
|
||||||
CompareMethod = ">=",
|
|
||||||
Value = distance.Value,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has specific weapon requirement
|
// Has specific weapon requirement
|
||||||
|
|||||||
+19
-94
@@ -54,20 +54,9 @@ public class ExplorationQuestGenerator(
|
|||||||
var explorationConfig = repeatableConfig.QuestConfig.Exploration;
|
var explorationConfig = repeatableConfig.QuestConfig.Exploration;
|
||||||
|
|
||||||
// Try and get a location to generate for
|
// Try and get a location to generate for
|
||||||
if (
|
if (!TryGetLocationInfo(repeatableConfig, explorationConfig, questTypePool, out var locationInfo) || locationInfo is null)
|
||||||
!TryGetLocationInfo(
|
|
||||||
repeatableConfig,
|
|
||||||
explorationConfig,
|
|
||||||
questTypePool,
|
|
||||||
out var locationInfo
|
|
||||||
) || locationInfo is null
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("repeatable-no_location_found_for_exploration_quest_generation"));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-no_location_found_for_exploration_quest_generation"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -82,12 +71,7 @@ public class ExplorationQuestGenerator(
|
|||||||
|
|
||||||
if (quest is null)
|
if (quest is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-quest_generation_failed_no_template", "exploration"));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-quest_generation_failed_no_template",
|
|
||||||
"exploration"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,45 +79,24 @@ public class ExplorationQuestGenerator(
|
|||||||
if (!TryGenerateAvailableForFinish(quest, locationInfo))
|
if (!TryGenerateAvailableForFinish(quest, locationInfo))
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
localisationService.GetText(
|
localisationService.GetText("repeatable-available_for_finish_condition_failed_to_generate", locationInfo.LocationName)
|
||||||
"repeatable-available_for_finish_condition_failed_to_generate",
|
|
||||||
locationInfo.LocationName
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we require a specific extract requirement, generate it
|
// If we require a specific extract requirement, generate it
|
||||||
if (
|
if (locationInfo.RequiresSpecificExtract && !TryGenerateSpecificExtractRequirement(quest, repeatableConfig, locationInfo))
|
||||||
locationInfo.RequiresSpecificExtract
|
|
||||||
&& !TryGenerateSpecificExtractRequirement(quest, repeatableConfig, locationInfo)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(
|
||||||
localisationService.GetText(
|
localisationService.GetText("repeatable-specific_extract_condition_failed_to_generate", locationInfo.LocationName)
|
||||||
"repeatable-specific_extract_condition_failed_to_generate",
|
|
||||||
locationInfo.LocationName
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Difficulty for exploration goes from 1 extract to maxExtracts
|
// Difficulty for exploration goes from 1 extract to maxExtracts
|
||||||
// Difficulty for reward goes from 0.2...1 -> map
|
// Difficulty for reward goes from 0.2...1 -> map
|
||||||
var difficulty = mathUtil.MapToRange(
|
var difficulty = mathUtil.MapToRange(locationInfo.NumOfExtractsRequired, 1, explorationConfig.MaximumExtracts, 0.2, 1);
|
||||||
locationInfo.NumOfExtractsRequired,
|
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(pmcLevel, difficulty, traderId, repeatableConfig, explorationConfig);
|
||||||
1,
|
|
||||||
explorationConfig.MaximumExtracts,
|
|
||||||
0.2,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(
|
|
||||||
pmcLevel,
|
|
||||||
difficulty,
|
|
||||||
traderId,
|
|
||||||
repeatableConfig,
|
|
||||||
explorationConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
return quest;
|
return quest;
|
||||||
}
|
}
|
||||||
@@ -168,18 +131,11 @@ public class ExplorationQuestGenerator(
|
|||||||
// Make the location info object
|
// Make the location info object
|
||||||
var locationTarget = pool.Pool!.Exploration!.Locations![locationKey];
|
var locationTarget = pool.Pool!.Exploration!.Locations![locationKey];
|
||||||
|
|
||||||
var requiresSpecificExtract = randomUtil.GetChance100(
|
var requiresSpecificExtract = randomUtil.GetChance100(repeatableConfig.QuestConfig.Exploration.SpecificExits.Chance);
|
||||||
repeatableConfig.QuestConfig.Exploration.SpecificExits.Chance
|
|
||||||
);
|
|
||||||
|
|
||||||
var numExtracts = GetNumberOfExits(explorationConfig, requiresSpecificExtract);
|
var numExtracts = GetNumberOfExits(explorationConfig, requiresSpecificExtract);
|
||||||
|
|
||||||
locationInfo = new LocationInfo(
|
locationInfo = new LocationInfo(locationKey, locationTarget.ToList(), requiresSpecificExtract, numExtracts);
|
||||||
locationKey,
|
|
||||||
locationTarget.ToList(),
|
|
||||||
requiresSpecificExtract,
|
|
||||||
numExtracts
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove the location from the available pool
|
// Remove the location from the available pool
|
||||||
pool.Pool.Exploration.Locations.Remove(locationKey);
|
pool.Pool.Exploration.Locations.Remove(locationKey);
|
||||||
@@ -196,9 +152,7 @@ public class ExplorationQuestGenerator(
|
|||||||
protected int GetNumberOfExits(Exploration config, bool requiresSpecificExtract)
|
protected int GetNumberOfExits(Exploration config, bool requiresSpecificExtract)
|
||||||
{
|
{
|
||||||
// Different max extract count when specific extract needed
|
// Different max extract count when specific extract needed
|
||||||
var exitTimesMax = requiresSpecificExtract
|
var exitTimesMax = requiresSpecificExtract ? config.MaximumExtractsWithSpecificExit : config.MaximumExtracts + 1;
|
||||||
? config.MaximumExtractsWithSpecificExit
|
|
||||||
: config.MaximumExtracts + 1;
|
|
||||||
|
|
||||||
return randomUtil.RandInt(1, exitTimesMax);
|
return randomUtil.RandInt(1, exitTimesMax);
|
||||||
}
|
}
|
||||||
@@ -209,10 +163,7 @@ public class ExplorationQuestGenerator(
|
|||||||
/// <param name="locationKey">Map id (e.g. factory4_day)</param>
|
/// <param name="locationKey">Map id (e.g. factory4_day)</param>
|
||||||
/// <param name="playerGroup">Pmc/Scav</param>
|
/// <param name="playerGroup">Pmc/Scav</param>
|
||||||
/// <returns>List of Exit objects</returns>
|
/// <returns>List of Exit objects</returns>
|
||||||
protected IEnumerable<Exit>? GetLocationExitsForSide(
|
protected IEnumerable<Exit>? GetLocationExitsForSide(string locationKey, PlayerGroup playerGroup)
|
||||||
string locationKey,
|
|
||||||
PlayerGroup playerGroup
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var mapExtracts = databaseService.GetLocation(locationKey.ToLowerInvariant())?.AllExtracts;
|
var mapExtracts = databaseService.GetLocation(locationKey.ToLowerInvariant())?.AllExtracts;
|
||||||
|
|
||||||
@@ -235,18 +186,11 @@ public class ExplorationQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lookup the location
|
// Lookup the location
|
||||||
var location = repeatableQuestHelper.GetQuestLocationByMapId(
|
var location = repeatableQuestHelper.GetQuestLocationByMapId(locationInfo.LocationName.ToString());
|
||||||
locationInfo.LocationName.ToString()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (location is null)
|
if (location is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-unable_to_find_location_id_for_location_name", locationInfo.LocationName));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-unable_to_find_location_id_for_location_name",
|
|
||||||
locationInfo.LocationName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,11 +211,7 @@ public class ExplorationQuestGenerator(
|
|||||||
};
|
};
|
||||||
|
|
||||||
quest.Conditions.AvailableForFinish![0].Counter!.Id = new MongoId();
|
quest.Conditions.AvailableForFinish![0].Counter!.Id = new MongoId();
|
||||||
quest.Conditions.AvailableForFinish![0].Counter!.Conditions =
|
quest.Conditions.AvailableForFinish![0].Counter!.Conditions = [exitStatusCondition, locationCondition];
|
||||||
[
|
|
||||||
exitStatusCondition,
|
|
||||||
locationCondition,
|
|
||||||
];
|
|
||||||
quest.Conditions.AvailableForFinish[0].Value = locationInfo.NumOfExtractsRequired;
|
quest.Conditions.AvailableForFinish[0].Value = locationInfo.NumOfExtractsRequired;
|
||||||
quest.Conditions.AvailableForFinish[0].Id = new MongoId();
|
quest.Conditions.AvailableForFinish[0].Id = new MongoId();
|
||||||
|
|
||||||
@@ -294,19 +234,11 @@ public class ExplorationQuestGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Fetch extracts for the requested side
|
// Fetch extracts for the requested side
|
||||||
var mapExits = GetLocationExitsForSide(
|
var mapExits = GetLocationExitsForSide(locationInfo.LocationName.ToString(), repeatableConfig.Side);
|
||||||
locationInfo.LocationName.ToString(),
|
|
||||||
repeatableConfig.Side
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mapExits is null)
|
if (mapExits is null)
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-unable_to_find_exits_for_location", locationInfo.LocationName));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-unable_to_find_exits_for_location",
|
|
||||||
locationInfo.LocationName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,19 +247,12 @@ public class ExplorationQuestGenerator(
|
|||||||
|
|
||||||
// Exclude exits with a requirement to leave (e.g. car extracts)
|
// Exclude exits with a requirement to leave (e.g. car extracts)
|
||||||
var possibleExits = exitPool.Where(exit =>
|
var possibleExits = exitPool.Where(exit =>
|
||||||
repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains(
|
repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains("PassageRequirement")
|
||||||
"PassageRequirement"
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!possibleExits.Any())
|
if (!possibleExits.Any())
|
||||||
{
|
{
|
||||||
logger.Error(
|
logger.Error(localisationService.GetText("repeatable-unable_choose_exit_pool_empty", locationInfo.LocationName));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-unable_choose_exit_pool_empty",
|
|
||||||
locationInfo.LocationName
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-19
@@ -42,9 +42,7 @@ public class PickupQuestGenerator(
|
|||||||
sessionId
|
sessionId
|
||||||
);
|
);
|
||||||
|
|
||||||
var itemTypeToFetchWithCount = randomUtil.GetArrayValue(
|
var itemTypeToFetchWithCount = randomUtil.GetArrayValue(pickupConfig.ItemTypeToFetchWithMaxCount);
|
||||||
pickupConfig.ItemTypeToFetchWithMaxCount
|
|
||||||
);
|
|
||||||
|
|
||||||
var itemCountToFetch = randomUtil.RandInt(
|
var itemCountToFetch = randomUtil.RandInt(
|
||||||
itemTypeToFetchWithCount.MinimumPickupCount.Value,
|
itemTypeToFetchWithCount.MinimumPickupCount.Value,
|
||||||
@@ -54,34 +52,22 @@ public class PickupQuestGenerator(
|
|||||||
// var locationKey: string = this.randomUtil.drawRandomFromDict(questTypePool.pool.Pickup.locations)[0];
|
// var locationKey: string = this.randomUtil.drawRandomFromDict(questTypePool.pool.Pickup.locations)[0];
|
||||||
// var locationTarget = questTypePool.pool.Pickup.locations[locationKey];
|
// var locationTarget = questTypePool.pool.Pickup.locations[locationKey];
|
||||||
|
|
||||||
var findCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x =>
|
var findCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x => x.ConditionType == "FindItem");
|
||||||
x.ConditionType == "FindItem"
|
|
||||||
);
|
|
||||||
findCondition.Target = new ListOrT<string>([itemTypeToFetchWithCount.ItemType], null);
|
findCondition.Target = new ListOrT<string>([itemTypeToFetchWithCount.ItemType], null);
|
||||||
findCondition.Value = itemCountToFetch;
|
findCondition.Value = itemCountToFetch;
|
||||||
|
|
||||||
var counterCreatorCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x =>
|
var counterCreatorCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x => x.ConditionType == "CounterCreator");
|
||||||
x.ConditionType == "CounterCreator"
|
|
||||||
);
|
|
||||||
// var locationCondition = counterCreatorCondition._props.counter.conditions.find(x => x._parent === "Location");
|
// var locationCondition = counterCreatorCondition._props.counter.conditions.find(x => x._parent === "Location");
|
||||||
// (locationCondition._props as ILocationConditionProps).target = [...locationTarget];
|
// (locationCondition._props as ILocationConditionProps).target = [...locationTarget];
|
||||||
|
|
||||||
var equipmentCondition = counterCreatorCondition.Counter.Conditions.FirstOrDefault(x =>
|
var equipmentCondition = counterCreatorCondition.Counter.Conditions.FirstOrDefault(x => x.ConditionType == "Equipment");
|
||||||
x.ConditionType == "Equipment"
|
|
||||||
);
|
|
||||||
equipmentCondition.EquipmentInclusive =
|
equipmentCondition.EquipmentInclusive =
|
||||||
[
|
[
|
||||||
[itemTypeToFetchWithCount.ItemType],
|
[itemTypeToFetchWithCount.ItemType],
|
||||||
];
|
];
|
||||||
|
|
||||||
// Add rewards
|
// Add rewards
|
||||||
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(
|
quest.Rewards = repeatableQuestRewardGenerator.GenerateReward(pmcLevel, 1, traderId, repeatableConfig, pickupConfig);
|
||||||
pmcLevel,
|
|
||||||
1,
|
|
||||||
traderId,
|
|
||||||
repeatableConfig,
|
|
||||||
pickupConfig
|
|
||||||
);
|
|
||||||
|
|
||||||
return quest;
|
return quest;
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-158
@@ -68,11 +68,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Get vars to configure rewards with
|
// Get vars to configure rewards with
|
||||||
var rewardParams = GetQuestRewardValues(
|
var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel);
|
||||||
repeatableConfig.RewardScaling,
|
|
||||||
difficulty,
|
|
||||||
pmcLevel
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get budget to spend on item rewards (copy of raw roubles given)
|
// Get budget to spend on item rewards (copy of raw roubles given)
|
||||||
var itemRewardBudget = rewardParams.RewardRoubles;
|
var itemRewardBudget = rewardParams.RewardRoubles;
|
||||||
@@ -112,13 +108,12 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
|
|
||||||
// Add GP coin reward
|
// Add GP coin reward
|
||||||
rewards["Success"]
|
rewards["Success"].Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex));
|
||||||
.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount, rewardIndex));
|
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
|
|
||||||
// Add preset weapon to reward if checks pass
|
// Add preset weapon to reward if checks pass
|
||||||
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(
|
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(traderWhitelist =>
|
||||||
traderWhitelist => traderWhitelist.TraderId == traderId
|
traderWhitelist.TraderId == traderId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (traderWhitelistDetails is null)
|
if (traderWhitelistDetails is null)
|
||||||
@@ -127,10 +122,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (traderWhitelistDetails.RewardCanBeWeapon && randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent))
|
||||||
traderWhitelistDetails.RewardCanBeWeapon
|
|
||||||
&& randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex);
|
var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget, rewardIndex);
|
||||||
if (chosenWeapon is not null)
|
if (chosenWeapon is not null)
|
||||||
@@ -143,17 +135,11 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(
|
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId);
|
||||||
repeatableConfig,
|
|
||||||
itemRewardBudget,
|
|
||||||
traderId
|
|
||||||
);
|
|
||||||
if (rewardTplBlacklist is not null)
|
if (rewardTplBlacklist is not null)
|
||||||
{
|
{
|
||||||
// Filter reward pool of items from blacklist, only use if there's at least 1 item remaining
|
// Filter reward pool of items from blacklist, only use if there's at least 1 item remaining
|
||||||
var filteredRewardItemPool = inBudgetRewardItemPool
|
var filteredRewardItemPool = inBudgetRewardItemPool.Where(item => !rewardTplBlacklist.Contains(item.Id)).ToList();
|
||||||
.Where(item => !rewardTplBlacklist.Contains(item.Id))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (filteredRewardItemPool.Count != 0)
|
if (filteredRewardItemPool.Count != 0)
|
||||||
{
|
{
|
||||||
@@ -180,8 +166,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
// Add item rewards
|
// Add item rewards
|
||||||
foreach (var itemReward in itemsToReward)
|
foreach (var itemReward in itemsToReward)
|
||||||
{
|
{
|
||||||
rewards["Success"]
|
rewards["Success"].Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex));
|
||||||
.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex));
|
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,9 +190,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId.ToString()} trader reputation reward");
|
||||||
$"Adding: {rewardParams.RewardReputation} {traderId.ToString()} trader reputation reward"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,20 +213,14 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
|
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}");
|
||||||
$"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rewards;
|
return rewards;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected QuestRewardValues GetQuestRewardValues(
|
protected QuestRewardValues GetQuestRewardValues(RewardScaling rewardScaling, double effectiveDifficulty, int pmcLevel)
|
||||||
RewardScaling rewardScaling,
|
|
||||||
double effectiveDifficulty,
|
|
||||||
int pmcLevel
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward
|
// difficulty could go from 0.2 ... -> for lowest difficulty receive 0.2*nominal reward
|
||||||
var levelsConfig = rewardScaling.Levels;
|
var levelsConfig = rewardScaling.Levels;
|
||||||
@@ -260,35 +237,11 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
SkillPointReward = mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig),
|
SkillPointReward = mathUtil.Interp1(pmcLevel, levelsConfig, skillPointRewardConfig),
|
||||||
SkillRewardChance = mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig),
|
SkillRewardChance = mathUtil.Interp1(pmcLevel, levelsConfig, skillRewardChanceConfig),
|
||||||
RewardReputation = GetRewardRep(
|
RewardReputation = GetRewardRep(effectiveDifficulty, pmcLevel, levelsConfig, reputationConfig, rewardSpreadConfig),
|
||||||
effectiveDifficulty,
|
|
||||||
pmcLevel,
|
|
||||||
levelsConfig,
|
|
||||||
reputationConfig,
|
|
||||||
rewardSpreadConfig
|
|
||||||
),
|
|
||||||
RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig),
|
RewardNumItems = GetRewardNumItems(pmcLevel, levelsConfig, itemsConfig),
|
||||||
RewardRoubles = GetRewardRoubles(
|
RewardRoubles = GetRewardRoubles(effectiveDifficulty, pmcLevel, levelsConfig, roublesConfig, rewardSpreadConfig),
|
||||||
effectiveDifficulty,
|
GpCoinRewardCount = GetGpCoinRewardCount(effectiveDifficulty, pmcLevel, levelsConfig, gpCoinConfig, rewardSpreadConfig),
|
||||||
pmcLevel,
|
RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig),
|
||||||
levelsConfig,
|
|
||||||
roublesConfig,
|
|
||||||
rewardSpreadConfig
|
|
||||||
),
|
|
||||||
GpCoinRewardCount = GetGpCoinRewardCount(
|
|
||||||
effectiveDifficulty,
|
|
||||||
pmcLevel,
|
|
||||||
levelsConfig,
|
|
||||||
gpCoinConfig,
|
|
||||||
rewardSpreadConfig
|
|
||||||
),
|
|
||||||
RewardXP = GetRewardXp(
|
|
||||||
effectiveDifficulty,
|
|
||||||
pmcLevel,
|
|
||||||
levelsConfig,
|
|
||||||
xpConfig,
|
|
||||||
rewardSpreadConfig
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,11 +289,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return Math.Round(multiplier) / 100;
|
return Math.Round(multiplier) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int GetRewardNumItems(
|
protected int GetRewardNumItems(int pmcLevel, List<double> levelsConfig, List<double> itemsConfig)
|
||||||
int pmcLevel,
|
|
||||||
List<double> levelsConfig,
|
|
||||||
List<double> itemsConfig
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var interpolatedNumItems = mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig);
|
var interpolatedNumItems = mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig);
|
||||||
|
|
||||||
@@ -395,21 +344,14 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
if (itemHelper.IsOfBaseclass(chosenItemFromPool.Id, BaseClasses.AMMO))
|
if (itemHelper.IsOfBaseclass(chosenItemFromPool.Id, BaseClasses.AMMO))
|
||||||
{
|
{
|
||||||
// Don't reward ammo that stacks to less than what's allowed in config
|
// Don't reward ammo that stacks to less than what's allowed in config
|
||||||
if (
|
if (chosenItemFromPool.Properties.StackMaxSize < repeatableConfig.RewardAmmoStackMinSize)
|
||||||
chosenItemFromPool.Properties.StackMaxSize
|
|
||||||
< repeatableConfig.RewardAmmoStackMinSize
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
i--;
|
i--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose the smallest value between budget, fitting size and stack max
|
// Choose the smallest value between budget, fitting size and stack max
|
||||||
rewardItemStackCount = CalculateAmmoStackSizeThatFitsBudget(
|
rewardItemStackCount = CalculateAmmoStackSizeThatFitsBudget(chosenItemFromPool, itemRewardBudget, maxItemCount);
|
||||||
chosenItemFromPool,
|
|
||||||
itemRewardBudget,
|
|
||||||
maxItemCount
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 25% chance to double, triple or quadruple reward stack
|
// 25% chance to double, triple or quadruple reward stack
|
||||||
@@ -425,9 +367,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
var calculatedItemRewardBudget = itemRewardBudget - rewardItemStackCount * itemCost;
|
var calculatedItemRewardBudget = itemRewardBudget - rewardItemStackCount * itemCost;
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Added item: {chosenItemFromPool.Id} with price: {rewardItemStackCount * itemCost}");
|
||||||
$"Added item: {chosenItemFromPool.Id} with price: {rewardItemStackCount * itemCost}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we still have budget narrow down possible items
|
// If we still have budget narrow down possible items
|
||||||
@@ -444,9 +384,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug))
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
logger.Debug(
|
logger.Debug($"Reward pool empty with: {calculatedItemRewardBudget} roubles of budget remaining");
|
||||||
$"Reward pool empty with: {calculatedItemRewardBudget} roubles of budget remaining"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -466,11 +404,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="roublesBudget"> Rouble budget </param>
|
/// <param name="roublesBudget"> Rouble budget </param>
|
||||||
/// <param name="rewardNumItems"> Count of rewarded items </param>
|
/// <param name="rewardNumItems"> Count of rewarded items </param>
|
||||||
/// <returns> Count that fits budget (min 1) </returns>
|
/// <returns> Count that fits budget (min 1) </returns>
|
||||||
protected int CalculateAmmoStackSizeThatFitsBudget(
|
protected int CalculateAmmoStackSizeThatFitsBudget(TemplateItem itemSelected, double roublesBudget, int rewardNumItems)
|
||||||
TemplateItem itemSelected,
|
|
||||||
double roublesBudget,
|
|
||||||
int rewardNumItems
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Calculate budget per reward item
|
// Calculate budget per reward item
|
||||||
var stackRoubleBudget = roublesBudget / rewardNumItems;
|
var stackRoubleBudget = roublesBudget / rewardNumItems;
|
||||||
@@ -487,18 +421,11 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return (int)Math.Clamp(stackSizeThatFitsBudget, 1, stackMaxCount);
|
return (int)Math.Clamp(stackSizeThatFitsBudget, 1, stackMaxCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool CanIncreaseRewardItemStackSize(
|
protected bool CanIncreaseRewardItemStackSize(TemplateItem item, int maxRoublePriceToStack, int randomChanceToPass = 100)
|
||||||
TemplateItem item,
|
|
||||||
int maxRoublePriceToStack,
|
|
||||||
int randomChanceToPass = 100
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var isEligibleForStackSizeIncrease =
|
var isEligibleForStackSizeIncrease =
|
||||||
presetHelper.GetDefaultPresetOrItemPrice(item.Id) < maxRoublePriceToStack
|
presetHelper.GetDefaultPresetOrItemPrice(item.Id) < maxRoublePriceToStack
|
||||||
&& !itemHelper.IsOfBaseclasses(
|
&& !itemHelper.IsOfBaseclasses(item.Id, [BaseClasses.WEAPON, BaseClasses.ARMORED_EQUIPMENT, BaseClasses.AMMO])
|
||||||
item.Id,
|
|
||||||
[BaseClasses.WEAPON, BaseClasses.ARMORED_EQUIPMENT, BaseClasses.AMMO]
|
|
||||||
)
|
|
||||||
&& !itemHelper.ItemRequiresSoftInserts(item.Id);
|
&& !itemHelper.ItemRequiresSoftInserts(item.Id);
|
||||||
|
|
||||||
return isEligibleForStackSizeIncrease && randomUtil.GetChance100(randomChanceToPass);
|
return isEligibleForStackSizeIncrease && randomUtil.GetChance100(randomChanceToPass);
|
||||||
@@ -548,25 +475,14 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
var rewardableItemPool = GetRewardableItems(repeatableConfig, traderId);
|
var rewardableItemPool = GetRewardableItems(repeatableConfig, traderId);
|
||||||
var minPrice = Math.Min(25000, 0.5 * roublesBudget.Value);
|
var minPrice = Math.Min(25000, 0.5 * roublesBudget.Value);
|
||||||
|
|
||||||
var rewardableItemPoolWithinBudget = FilterRewardPoolWithinBudget(
|
var rewardableItemPoolWithinBudget = FilterRewardPoolWithinBudget(rewardableItemPool, roublesBudget.Value, minPrice);
|
||||||
rewardableItemPool,
|
|
||||||
roublesBudget.Value,
|
|
||||||
minPrice
|
|
||||||
);
|
|
||||||
|
|
||||||
if (rewardableItemPoolWithinBudget.Count == 0)
|
if (rewardableItemPoolWithinBudget.Count == 0)
|
||||||
{
|
{
|
||||||
logger.Warning(
|
logger.Warning(localisationService.GetText("repeatable-no_reward_item_found_in_price_range", new { minPrice, roublesBudget }));
|
||||||
localisationService.GetText(
|
|
||||||
"repeatable-no_reward_item_found_in_price_range",
|
|
||||||
new { minPrice, roublesBudget }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// In case we don't find any items in the price range
|
// In case we don't find any items in the price range
|
||||||
rewardableItemPoolWithinBudget = rewardableItemPool
|
rewardableItemPoolWithinBudget = rewardableItemPool.Where(x => itemHelper.GetItemPrice(x.Id) < roublesBudget).ToList();
|
||||||
.Where(x => itemHelper.GetItemPrice(x.Id) < roublesBudget)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rewardableItemPoolWithinBudget;
|
return rewardableItemPoolWithinBudget;
|
||||||
@@ -579,11 +495,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="roublesBudget"> The budget remaining for rewards </param>
|
/// <param name="roublesBudget"> The budget remaining for rewards </param>
|
||||||
/// <param name="minPrice"> The minimum priced item to include </param>
|
/// <param name="minPrice"> The minimum priced item to include </param>
|
||||||
/// <returns> List of Items </returns>
|
/// <returns> List of Items </returns>
|
||||||
protected List<TemplateItem> FilterRewardPoolWithinBudget(
|
protected List<TemplateItem> FilterRewardPoolWithinBudget(List<TemplateItem> rewardItems, double roublesBudget, double minPrice)
|
||||||
List<TemplateItem> rewardItems,
|
|
||||||
double roublesBudget,
|
|
||||||
double minPrice
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return rewardItems
|
return rewardItems
|
||||||
.Where(item =>
|
.Where(item =>
|
||||||
@@ -600,17 +512,10 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="roublesBudget"> Budget in roubles </param>
|
/// <param name="roublesBudget"> Budget in roubles </param>
|
||||||
/// <param name="rewardIndex"> Index of the reward </param>
|
/// <param name="rewardIndex"> Index of the reward </param>
|
||||||
/// <returns> Dictionary of the reward and it's price, can return null. </returns>
|
/// <returns> Dictionary of the reward and it's price, can return null. </returns>
|
||||||
protected KeyValuePair<Reward, double>? GetRandomWeaponPresetWithinBudget(
|
protected KeyValuePair<Reward, double>? GetRandomWeaponPresetWithinBudget(double roublesBudget, int rewardIndex)
|
||||||
double roublesBudget,
|
|
||||||
int rewardIndex
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Add a random default preset weapon as reward
|
// Add a random default preset weapon as reward
|
||||||
var defaultPresetPool = new ExhaustableArray<Preset>(
|
var defaultPresetPool = new ExhaustableArray<Preset>(presetHelper.GetDefaultWeaponPresets().Values.ToList(), randomUtil, cloner);
|
||||||
presetHelper.GetDefaultWeaponPresets().Values.ToList(),
|
|
||||||
randomUtil,
|
|
||||||
cloner
|
|
||||||
);
|
|
||||||
|
|
||||||
while (defaultPresetPool.HasValues())
|
while (defaultPresetPool.HasValues())
|
||||||
{
|
{
|
||||||
@@ -631,12 +536,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
var chosenPreset = cloner.Clone(randomPreset);
|
var chosenPreset = cloner.Clone(randomPreset);
|
||||||
|
|
||||||
return new KeyValuePair<Reward, double>(
|
return new KeyValuePair<Reward, double>(
|
||||||
GeneratePresetReward(
|
GeneratePresetReward(chosenPreset.Encyclopedia.Value, 1, rewardIndex, chosenPreset.Items),
|
||||||
chosenPreset.Encyclopedia.Value,
|
|
||||||
1,
|
|
||||||
rewardIndex,
|
|
||||||
chosenPreset.Items
|
|
||||||
),
|
|
||||||
presetPrice
|
presetPrice
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -654,13 +554,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="preset"> Optional list of preset items </param>
|
/// <param name="preset"> Optional list of preset items </param>
|
||||||
/// <param name="foundInRaid"> If generated Item is found in raid, default True </param>
|
/// <param name="foundInRaid"> If generated Item is found in raid, default True </param>
|
||||||
/// <returns> Object of "Reward"-item-type </returns>
|
/// <returns> Object of "Reward"-item-type </returns>
|
||||||
protected Reward GeneratePresetReward(
|
protected Reward GeneratePresetReward(MongoId tpl, int count, int index, List<Item>? preset, bool foundInRaid = true)
|
||||||
MongoId tpl,
|
|
||||||
int count,
|
|
||||||
int index,
|
|
||||||
List<Item>? preset,
|
|
||||||
bool foundInRaid = true
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var id = new MongoId();
|
var id = new MongoId();
|
||||||
var questRewardItem = new Reward
|
var questRewardItem = new Reward
|
||||||
@@ -704,12 +598,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="index"> All rewards will be appended to a list, for unknown reasons the client wants the index</param>
|
/// <param name="index"> All rewards will be appended to a list, for unknown reasons the client wants the index</param>
|
||||||
/// <param name="foundInRaid"> If generated Item is found in raid, default True </param>
|
/// <param name="foundInRaid"> If generated Item is found in raid, default True </param>
|
||||||
/// <returns> Object of "Reward"-item-type </returns>
|
/// <returns> Object of "Reward"-item-type </returns>
|
||||||
protected Reward GenerateItemReward(
|
protected Reward GenerateItemReward(MongoId tpl, double count, int index, bool foundInRaid = true)
|
||||||
MongoId tpl,
|
|
||||||
double count,
|
|
||||||
int index,
|
|
||||||
bool foundInRaid = true
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var id = new MongoId();
|
var id = new MongoId();
|
||||||
var questRewardItem = new Reward
|
var questRewardItem = new Reward
|
||||||
@@ -742,16 +631,10 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
// Determine currency based on trader
|
// Determine currency based on trader
|
||||||
// PK and Fence use Euros, everyone else is Roubles
|
// PK and Fence use Euros, everyone else is Roubles
|
||||||
var currency =
|
var currency = traderId == Traders.PEACEKEEPER || traderId == Traders.FENCE ? Money.EUROS : Money.ROUBLES;
|
||||||
traderId == Traders.PEACEKEEPER || traderId == Traders.FENCE
|
|
||||||
? Money.EUROS
|
|
||||||
: Money.ROUBLES;
|
|
||||||
|
|
||||||
// Convert reward amount to Euros if necessary
|
// Convert reward amount to Euros if necessary
|
||||||
var rewardAmountToGivePlayer =
|
var rewardAmountToGivePlayer = currency == Money.EUROS ? handbookHelper.FromRUB(rewardRoubles, Money.EUROS) : rewardRoubles;
|
||||||
currency == Money.EUROS
|
|
||||||
? handbookHelper.FromRUB(rewardRoubles, Money.EUROS)
|
|
||||||
: rewardRoubles;
|
|
||||||
|
|
||||||
// Get chosen currency + amount and return
|
// Get chosen currency + amount and return
|
||||||
return GenerateItemReward(currency, rewardAmountToGivePlayer, rewardIndex, false);
|
return GenerateItemReward(currency, rewardAmountToGivePlayer, rewardIndex, false);
|
||||||
@@ -767,10 +650,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="repeatableQuestConfig"> Config </param>
|
/// <param name="repeatableQuestConfig"> Config </param>
|
||||||
/// <param name="traderId"> ID of trader who will give reward to player </param>
|
/// <param name="traderId"> ID of trader who will give reward to player </param>
|
||||||
/// <returns> List of rewardable items [[_tpl, itemTemplate],...] </returns>
|
/// <returns> List of rewardable items [[_tpl, itemTemplate],...] </returns>
|
||||||
public List<TemplateItem> GetRewardableItems(
|
public List<TemplateItem> GetRewardableItems(RepeatableQuestConfig repeatableQuestConfig, MongoId traderId)
|
||||||
RepeatableQuestConfig repeatableQuestConfig,
|
|
||||||
MongoId traderId
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
// Get an array of seasonal items that should not be shown right now as seasonal event is not active
|
// Get an array of seasonal items that should not be shown right now as seasonal event is not active
|
||||||
var seasonalItems = seasonalEventService.GetInactiveSeasonalEventItems();
|
var seasonalItems = seasonalEventService.GetInactiveSeasonalEventItems();
|
||||||
@@ -793,9 +673,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var traderWhitelist = repeatableQuestConfig.TraderWhitelist.FirstOrDefault(trader =>
|
var traderWhitelist = repeatableQuestConfig.TraderWhitelist.FirstOrDefault(trader => trader.TraderId == traderId);
|
||||||
trader.TraderId == traderId
|
|
||||||
);
|
|
||||||
|
|
||||||
return IsValidRewardItem(
|
return IsValidRewardItem(
|
||||||
itemTemplate.Id,
|
itemTemplate.Id,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user