.NET Format Style Fixes
This commit is contained in:
@@ -1,12 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<Import Project="..\Build.props" />
|
<Import Project="..\Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
||||||
<PackageReference Include="FastCloner" Version="3.3.8" />
|
<PackageReference Include="FastCloner" Version="3.3.8" />
|
||||||
@@ -15,11 +12,9 @@
|
|||||||
<ProjectReference Include="..\Libraries\SPTarkov.Common\SPTarkov.Common.csproj" />
|
<ProjectReference Include="..\Libraries\SPTarkov.Common\SPTarkov.Common.csproj" />
|
||||||
<ProjectReference Include="..\Libraries\SPTarkov.DI\SPTarkov.DI.csproj" />
|
<ProjectReference Include="..\Libraries\SPTarkov.DI\SPTarkov.DI.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Assets\**">
|
<Content Include="Assets\**">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ public class ClonerBenchmarks
|
|||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
var jsonUtil = new JsonUtil([new SptJsonConverterRegistrator()]);
|
var jsonUtil = new JsonUtil([new SptJsonConverterRegistrator()]);
|
||||||
var importer = new ImporterUtil(new MockLogger<ImporterUtil>(), new FileUtil(),
|
var importer = new ImporterUtil(new MockLogger<ImporterUtil>(), new FileUtil(), jsonUtil);
|
||||||
jsonUtil);
|
|
||||||
var loadTask = importer.LoadRecursiveAsync<Templates>("./Assets/database/templates/");
|
var loadTask = importer.LoadRecursiveAsync<Templates>("./Assets/database/templates/");
|
||||||
loadTask.Wait();
|
loadTask.Wait();
|
||||||
_templates = loadTask.Result;
|
_templates = loadTask.Result;
|
||||||
|
|||||||
@@ -6,7 +6,12 @@ namespace Benchmarks.Mock;
|
|||||||
|
|
||||||
public class MockLogger<T> : ISptLogger<T>
|
public class MockLogger<T> : ISptLogger<T>
|
||||||
{
|
{
|
||||||
public void LogWithColor(string data, LogTextColor? textColor = null, LogBackgroundColor? backgroundColor = null, Exception? ex = null)
|
public void LogWithColor(
|
||||||
|
string data,
|
||||||
|
LogTextColor? textColor = null,
|
||||||
|
LogBackgroundColor? backgroundColor = null,
|
||||||
|
Exception? ex = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>4.0.0-prerelease2</Version>
|
<Version>4.0.0-prerelease2</Version>
|
||||||
@@ -7,5 +6,4 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ 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,7 +6,8 @@ namespace SPTarkov.Common.Extensions;
|
|||||||
|
|
||||||
public static class ObjectExtensions
|
public static class ObjectExtensions
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _indexedProperties = new();
|
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _indexedProperties =
|
||||||
|
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)
|
||||||
@@ -15,7 +16,8 @@ public static class ObjectExtensions
|
|||||||
{
|
{
|
||||||
if (!_indexedProperties.TryGetValue(type, out var properties))
|
if (!_indexedProperties.TryGetValue(type, out var properties))
|
||||||
{
|
{
|
||||||
properties = type.GetProperties().ToDictionary(prop => prop.GetJsonName(), prop => prop);
|
properties = type.GetProperties()
|
||||||
|
.ToDictionary(prop => prop.GetJsonName(), prop => prop);
|
||||||
_indexedProperties.Add(type, properties);
|
_indexedProperties.Add(type, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ 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(this string source, [StringSyntax(StringSyntaxAttribute.Regex)] string regexString, string newValue)
|
public static string RegexReplace(
|
||||||
|
this string source,
|
||||||
|
[StringSyntax(StringSyntaxAttribute.Regex)] string regexString,
|
||||||
|
string newValue
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Regex regex;
|
Regex regex;
|
||||||
lock (_regexCacheLock)
|
lock (_regexCacheLock)
|
||||||
@@ -23,7 +27,11 @@ public static class StringExtensions
|
|||||||
return regex.Replace(source, newValue);
|
return regex.Replace(source, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool RegexMatch(this string source, [StringSyntax(StringSyntaxAttribute.Regex)] string regexString, out Match? matchedString)
|
public static bool RegexMatch(
|
||||||
|
this string source,
|
||||||
|
[StringSyntax(StringSyntaxAttribute.Regex)] string regexString,
|
||||||
|
out Match? matchedString
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Regex regex;
|
Regex regex;
|
||||||
lock (_regexCacheLock)
|
lock (_regexCacheLock)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<Import Project="..\..\Build.props" />
|
<Import Project="..\..\Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>SPTarkov.Common</PackageId>
|
<PackageId>SPTarkov.Common</PackageId>
|
||||||
<Authors>Single Player Tarkov</Authors>
|
<Authors>Single Player Tarkov</Authors>
|
||||||
@@ -14,13 +12,10 @@
|
|||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
<PackageReference Include="SemanticVersioning" Version="3.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,30 +1,22 @@
|
|||||||
namespace SPTarkov.DI.Annotations;
|
namespace SPTarkov.DI.Annotations;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||||
public class Injectable(InjectionType injectionType = InjectionType.Scoped, Type? typeOverride = null, int typePriority = int.MaxValue) : Attribute
|
public class Injectable(
|
||||||
|
InjectionType injectionType = InjectionType.Scoped,
|
||||||
|
Type? typeOverride = null,
|
||||||
|
int typePriority = int.MaxValue
|
||||||
|
) : Attribute
|
||||||
{
|
{
|
||||||
public InjectionType InjectionType
|
public InjectionType InjectionType { get; set; } = injectionType;
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
} = injectionType;
|
|
||||||
|
|
||||||
public int TypePriority
|
public int TypePriority { get; set; } = typePriority;
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
} = typePriority;
|
|
||||||
|
|
||||||
public Type? TypeOverride
|
public Type? TypeOverride { get; set; } = typeOverride;
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
} = typeOverride;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InjectionType
|
public enum InjectionType
|
||||||
{
|
{
|
||||||
Singleton,
|
Singleton,
|
||||||
Transient,
|
Transient,
|
||||||
Scoped
|
Scoped,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public class DependencyInjectionHandler
|
|||||||
|
|
||||||
private bool _oneTimeUseFlag;
|
private bool _oneTimeUseFlag;
|
||||||
|
|
||||||
|
|
||||||
public DependencyInjectionHandler(IServiceCollection serviceCollection)
|
public DependencyInjectionHandler(IServiceCollection serviceCollection)
|
||||||
{
|
{
|
||||||
_serviceCollection = serviceCollection;
|
_serviceCollection = serviceCollection;
|
||||||
@@ -43,8 +42,9 @@ public class DependencyInjectionHandler
|
|||||||
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())
|
||||||
{
|
{
|
||||||
foreach (var type in typesToInject)
|
foreach (var type in typesToInject)
|
||||||
@@ -58,16 +58,24 @@ public class DependencyInjectionHandler
|
|||||||
{
|
{
|
||||||
if (_oneTimeUseFlag)
|
if (_oneTimeUseFlag)
|
||||||
{
|
{
|
||||||
throw new Exception("Invalid usage of DependencyInjectionHandler, this is a one time use service!");
|
throw new Exception(
|
||||||
|
"Invalid usage of DependencyInjectionHandler, this is a one time use service!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_oneTimeUseFlag = true;
|
_oneTimeUseFlag = true;
|
||||||
var typeRefValues = _injectedTypeNames.Values
|
var typeRefValues = _injectedTypeNames.Values.Select(t => new TypeRefContainer(
|
||||||
.Select(t => new TypeRefContainer(((Injectable[]) Attribute.GetCustomAttributes(t, typeof(Injectable)))[0], t, t));
|
((Injectable[])Attribute.GetCustomAttributes(t, typeof(Injectable)))[0],
|
||||||
|
t,
|
||||||
|
t
|
||||||
|
));
|
||||||
// All the components that have a type override, we need to find them and remove them before injecting everything
|
// All the components that have a type override, we need to find them and remove them before injecting everything
|
||||||
var componentsToRemove = typeRefValues.Where(tr => tr.InjectableAttribute.TypeOverride != null).Select(tr =>
|
var componentsToRemove = typeRefValues
|
||||||
|
.Where(tr => tr.InjectableAttribute.TypeOverride != null)
|
||||||
|
.Select(tr =>
|
||||||
string.IsNullOrEmpty(tr.InjectableAttribute.TypeOverride!.FullName)
|
string.IsNullOrEmpty(tr.InjectableAttribute.TypeOverride!.FullName)
|
||||||
? $"{tr.InjectableAttribute.TypeOverride.Namespace}.{tr.InjectableAttribute.TypeOverride.Name}"
|
? $"{tr.InjectableAttribute.TypeOverride.Namespace}.{tr.InjectableAttribute.TypeOverride.Name}"
|
||||||
: tr.InjectableAttribute.TypeOverride.FullName!)
|
: tr.InjectableAttribute.TypeOverride.FullName!
|
||||||
|
)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
// All the components without the removed overrides
|
// All the components without the removed overrides
|
||||||
var cleanedComponents = typeRefValues.Where(tr =>
|
var cleanedComponents = typeRefValues.Where(tr =>
|
||||||
@@ -78,17 +86,27 @@ public class DependencyInjectionHandler
|
|||||||
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 => tRef.InjectableAttribute.TypePriority);
|
var sortedInjectableTypes = cleanedComponents.OrderBy(tRef =>
|
||||||
|
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 (var implementedInterface in typeRefToInject.Type.GetInterfaces()
|
foreach (
|
||||||
.Where(t => !t.Namespace.StartsWith("System")))
|
var implementedInterface in typeRefToInject
|
||||||
|
.Type.GetInterfaces()
|
||||||
|
.Where(t => !t.Namespace.StartsWith("System"))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
nodes.Enqueue(new TypeRefContainer(typeRefToInject.InjectableAttribute, typeRefToInject.Type,
|
nodes.Enqueue(
|
||||||
implementedInterface));
|
new TypeRefContainer(
|
||||||
|
typeRefToInject.InjectableAttribute,
|
||||||
|
typeRefToInject.Type,
|
||||||
|
implementedInterface
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (nodes.Any())
|
while (nodes.Any())
|
||||||
@@ -96,8 +114,13 @@ public class DependencyInjectionHandler
|
|||||||
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(new TypeRefContainer(node.InjectableAttribute, typeRefToInject.Type,
|
nodes.Enqueue(
|
||||||
node.Type.BaseType));
|
new TypeRefContainer(
|
||||||
|
node.InjectableAttribute,
|
||||||
|
typeRefToInject.Type,
|
||||||
|
node.Type.BaseType
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.Type.IsGenericType)
|
if (node.Type.IsGenericType)
|
||||||
@@ -106,9 +129,11 @@ public class DependencyInjectionHandler
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RegisterComponent(node.InjectableAttribute.InjectionType,
|
RegisterComponent(
|
||||||
|
node.InjectableAttribute.InjectionType,
|
||||||
node.Type,
|
node.Type,
|
||||||
node.ParentType);
|
node.ParentType
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +143,10 @@ public class DependencyInjectionHandler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_allLoadedTypes ??= AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).ToList();
|
_allLoadedTypes ??= AppDomain
|
||||||
|
.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(t => t.GetTypes())
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
catch (ReflectionTypeLoadException ex)
|
catch (ReflectionTypeLoadException ex)
|
||||||
{
|
{
|
||||||
@@ -130,9 +158,11 @@ public class DependencyInjectionHandler
|
|||||||
var typeName = $"{typeRef.Type.Namespace}.{typeRef.Type.Name}";
|
var typeName = $"{typeRef.Type.Namespace}.{typeRef.Type.Name}";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var matchedConstructors = _allConstructors.Where(c => c.GetParameters()
|
var matchedConstructors = _allConstructors.Where(c =>
|
||||||
.Any(p => p.ParameterType.IsGenericType &&
|
c.GetParameters()
|
||||||
p.ParameterType.GetGenericTypeDefinition().FullName == typeName
|
.Any(p =>
|
||||||
|
p.ParameterType.IsGenericType
|
||||||
|
&& p.ParameterType.GetGenericTypeDefinition().FullName == typeName
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -145,7 +175,11 @@ public class DependencyInjectionHandler
|
|||||||
foreach (var matchedConstructor in constructorInfos)
|
foreach (var matchedConstructor in constructorInfos)
|
||||||
{
|
{
|
||||||
var constructorParams = matchedConstructor.GetParameters();
|
var constructorParams = matchedConstructor.GetParameters();
|
||||||
foreach (var parameterInfo in constructorParams.Where(x => IsMatchingGenericType(x, typeName)))
|
foreach (
|
||||||
|
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);
|
||||||
@@ -166,8 +200,8 @@ public class DependencyInjectionHandler
|
|||||||
|
|
||||||
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(
|
||||||
@@ -188,7 +222,10 @@ public class DependencyInjectionHandler
|
|||||||
_serviceCollection.AddScoped(registrableInterface, implementationType);
|
_serviceCollection.AddScoped(registrableInterface, implementationType);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(injectionType), $"Unknown injection type on {implementationType.Namespace}.{implementationType.Name}");
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(injectionType),
|
||||||
|
$"Unknown injection type on {implementationType.Namespace}.{implementationType.Name}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +234,9 @@ public class DependencyInjectionHandler
|
|||||||
var serviceKey = $"{implementationType.Namespace}.{implementationType.Name}";
|
var serviceKey = $"{implementationType.Namespace}.{implementationType.Name}";
|
||||||
if (registrableInterface != implementationType)
|
if (registrableInterface != implementationType)
|
||||||
{
|
{
|
||||||
_serviceCollection.AddSingleton(registrableInterface, (serviceProvider) =>
|
_serviceCollection.AddSingleton(
|
||||||
|
registrableInterface,
|
||||||
|
(serviceProvider) =>
|
||||||
{
|
{
|
||||||
object service;
|
object service;
|
||||||
lock (_injectedValuesLock)
|
lock (_injectedValuesLock)
|
||||||
@@ -210,7 +249,8 @@ public class DependencyInjectionHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<Import Project="..\..\Build.props" />
|
<Import Project="..\..\Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>SPTarkov.DI</PackageId>
|
<PackageId>SPTarkov.DI</PackageId>
|
||||||
<Authors>Single Player Tarkov</Authors>
|
<Authors>Single Player Tarkov</Authors>
|
||||||
@@ -14,17 +12,16 @@
|
|||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
|
<PackageReference
|
||||||
|
Include="Microsoft.Extensions.DependencyInjection.Abstractions"
|
||||||
|
Version="9.0.5"
|
||||||
|
/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SPTarkov.Common\SPTarkov.Common.csproj" />
|
<ProjectReference Include="..\SPTarkov.Common\SPTarkov.Common.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
public class SingletonStateHolder<T>
|
public class SingletonStateHolder<T>
|
||||||
{
|
{
|
||||||
public T State
|
public T State { get; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SingletonStateHolder(T state)
|
public SingletonStateHolder(T state)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,35 +27,76 @@ public class CodeGenerator
|
|||||||
return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
|
return new CodeInstruction(code.OpCode) { labels = GetLabelList(code) };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Ldfld || code.OpCode == OpCodes.Ldflda || code.OpCode == OpCodes.Stfld)
|
if (
|
||||||
|
code.OpCode == OpCodes.Ldfld
|
||||||
|
|| code.OpCode == OpCodes.Ldflda
|
||||||
|
|| code.OpCode == OpCodes.Stfld
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, AccessTools.Field(code.CallerType, code.OperandTarget as string)) { labels = GetLabelList(code) };
|
return new CodeInstruction(
|
||||||
|
code.OpCode,
|
||||||
|
AccessTools.Field(code.CallerType, code.OperandTarget as string)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
|
if (code.OpCode == OpCodes.Call || code.OpCode == OpCodes.Callvirt)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)) { labels = GetLabelList(code) };
|
return new CodeInstruction(
|
||||||
|
code.OpCode,
|
||||||
|
AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Box)
|
if (code.OpCode == OpCodes.Box)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, code.CallerType) { labels = GetLabelList(code) };
|
return new CodeInstruction(code.OpCode, code.CallerType)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Br || code.OpCode == OpCodes.Brfalse || code.OpCode == OpCodes.Brtrue || code.OpCode == OpCodes.Brtrue_S
|
if (
|
||||||
|| code.OpCode == OpCodes.Brfalse_S || code.OpCode == OpCodes.Br_S)
|
code.OpCode == OpCodes.Br
|
||||||
|
|| code.OpCode == OpCodes.Brfalse
|
||||||
|
|| code.OpCode == OpCodes.Brtrue
|
||||||
|
|| code.OpCode == OpCodes.Brtrue_S
|
||||||
|
|| code.OpCode == OpCodes.Brfalse_S
|
||||||
|
|| code.OpCode == OpCodes.Br_S
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, code.OperandTarget) { labels = GetLabelList(code) };
|
return new CodeInstruction(code.OpCode, code.OperandTarget)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Ldftn)
|
if (code.OpCode == OpCodes.Ldftn)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)) { labels = GetLabelList(code) };
|
return new CodeInstruction(
|
||||||
|
code.OpCode,
|
||||||
|
AccessTools.Method(code.CallerType, code.OperandTarget as string, code.Parameters)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code.OpCode == OpCodes.Newobj)
|
if (code.OpCode == OpCodes.Newobj)
|
||||||
{
|
{
|
||||||
return new CodeInstruction(code.OpCode, code.CallerType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)) { labels = GetLabelList(code) };
|
return new CodeInstruction(
|
||||||
|
code.OpCode,
|
||||||
|
code.CallerType.GetConstructors()
|
||||||
|
.FirstOrDefault(x => x.GetParameters().Length == code.Parameters.Length)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
labels = GetLabelList(code),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Code with OpCode {code.OpCode.ToString()} is not supported.");
|
throw new ArgumentException($"Code with OpCode {code.OpCode.ToString()} is not supported.");
|
||||||
|
|||||||
@@ -6,22 +6,32 @@ public class CodeWithLabel : Code
|
|||||||
{
|
{
|
||||||
public Label Label { get; }
|
public Label Label { get; }
|
||||||
|
|
||||||
public CodeWithLabel(OpCode opCode, Label label) : base(opCode)
|
public CodeWithLabel(OpCode opCode, Label label)
|
||||||
|
: base(opCode)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeWithLabel(OpCode opCode, Label label, object operandTarget) : base(opCode, operandTarget)
|
public CodeWithLabel(OpCode opCode, Label label, object operandTarget)
|
||||||
|
: base(opCode, operandTarget)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeWithLabel(OpCode opCode, Label label, Type callerType) : base(opCode, callerType)
|
public CodeWithLabel(OpCode opCode, Label label, Type callerType)
|
||||||
|
: base(opCode, callerType)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeWithLabel(OpCode opCode, Label label, Type callerType, object operandTarget, Type[] parameters = null) : base(opCode, callerType, operandTarget, parameters)
|
public CodeWithLabel(
|
||||||
|
OpCode opCode,
|
||||||
|
Label label,
|
||||||
|
Type callerType,
|
||||||
|
object operandTarget,
|
||||||
|
Type[] parameters = null
|
||||||
|
)
|
||||||
|
: base(opCode, callerType, operandTarget, parameters)
|
||||||
{
|
{
|
||||||
Label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,17 @@ public abstract class AbstractPatch
|
|||||||
_finalizerList = GetPatchMethods(typeof(PatchFinalizerAttribute));
|
_finalizerList = GetPatchMethods(typeof(PatchFinalizerAttribute));
|
||||||
_ilManipulatorList = GetPatchMethods(typeof(PatchIlManipulatorAttribute));
|
_ilManipulatorList = GetPatchMethods(typeof(PatchIlManipulatorAttribute));
|
||||||
|
|
||||||
if (_prefixList.Count == 0
|
if (
|
||||||
|
_prefixList.Count == 0
|
||||||
&& _postfixList.Count == 0
|
&& _postfixList.Count == 0
|
||||||
&& _transpilerList.Count == 0
|
&& _transpilerList.Count == 0
|
||||||
&& _finalizerList.Count == 0
|
&& _finalizerList.Count == 0
|
||||||
&& _ilManipulatorList.Count == 0)
|
&& _ilManipulatorList.Count == 0
|
||||||
|
)
|
||||||
{
|
{
|
||||||
throw new Exception($"{_harmony.Id}: At least one of the patch methods must be specified");
|
throw new Exception(
|
||||||
|
$"{_harmony.Id}: At least one of the patch methods must be specified"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,8 +55,14 @@ public abstract class AbstractPatch
|
|||||||
var T = GetType();
|
var T = GetType();
|
||||||
var methods = new List<HarmonyMethod>();
|
var methods = new List<HarmonyMethod>();
|
||||||
|
|
||||||
foreach (var method in T.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public |
|
foreach (
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,27 +1,17 @@
|
|||||||
namespace SPTarkov.Reflection.Patching
|
namespace SPTarkov.Reflection.Patching
|
||||||
{
|
{
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class PatchPrefixAttribute : Attribute
|
public class PatchPrefixAttribute : Attribute { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class PatchPostfixAttribute : Attribute
|
public class PatchPostfixAttribute : Attribute { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class PatchTranspilerAttribute : Attribute
|
public class PatchTranspilerAttribute : Attribute { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class PatchFinalizerAttribute : Attribute
|
public class PatchFinalizerAttribute : Attribute { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class PatchIlManipulatorAttribute : Attribute
|
public class PatchIlManipulatorAttribute : Attribute { }
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<Import Project="..\..\Build.props" />
|
<Import Project="..\..\Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>SPTarkov.Reflection</PackageId>
|
<PackageId>SPTarkov.Reflection</PackageId>
|
||||||
<Authors>Single Player Tarkov</Authors>
|
<Authors>Single Player Tarkov</Authors>
|
||||||
@@ -14,13 +12,10 @@
|
|||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="HarmonyX" Version="2.14.0" />
|
<PackageReference Include="HarmonyX" Version="2.14.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<Import Project="..\..\Build.props" />
|
<Import Project="..\..\Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>SPTarkov.Server.Assets</PackageId>
|
<PackageId>SPTarkov.Server.Assets</PackageId>
|
||||||
<Authors>Single Player Tarkov</Authors>
|
<Authors>Single Player Tarkov</Authors>
|
||||||
@@ -16,21 +14,16 @@
|
|||||||
<ContentTargetFolders>content</ContentTargetFolders>
|
<ContentTargetFolders>content</ContentTargetFolders>
|
||||||
<RootNamespace>SptAssets</RootNamespace>
|
<RootNamespace>SptAssets</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="SPT_Data\**">
|
<Content Include="SPT_Data\**">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
<ExcludeFromSingleFile>True</ExcludeFromSingleFile>
|
<ExcludeFromSingleFile>True</ExcludeFromSingleFile>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PostBuildHashFile" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
|
<Target Name="PostBuildHashFile" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
|
||||||
<Exec Command="pwsh -NoProfile -ExecutionPolicy Bypass -File "$(ProjectDir)PostBuild.ps1"" />
|
<Exec Command="pwsh -NoProfile -ExecutionPolicy Bypass -File "$(ProjectDir)PostBuild.ps1"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
<None Include="..\..\LICENSE" Pack="true" Visible="false" PackagePath="" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ public class AchievementCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetAchievements(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetAchievements(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_achievementController.GetAchievements(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_achievementController.GetAchievements(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,6 +28,8 @@ public class AchievementCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> Statistic(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> Statistic(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_achievementController.GetAchievementStatics(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_achievementController.GetAchievementStatics(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class BotCallbacks(
|
public class BotCallbacks(BotController _botController, HttpResponseUtil _httpResponseUtil)
|
||||||
BotController _botController,
|
|
||||||
HttpResponseUtil _httpResponseUtil
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle singleplayer/settings/bot/limit
|
/// Handle singleplayer/settings/bot/limit
|
||||||
@@ -21,7 +18,9 @@ public class BotCallbacks(
|
|||||||
{
|
{
|
||||||
var splitUrl = url.Split('/');
|
var splitUrl = url.Split('/');
|
||||||
var type = splitUrl[^1];
|
var type = splitUrl[^1];
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_botController.GetBotPresetGenerationLimit(type)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_botController.GetBotPresetGenerationLimit(type))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,10 +34,14 @@ public class BotCallbacks(
|
|||||||
var difficulty = splitUrl[^1];
|
var difficulty = splitUrl[^1];
|
||||||
if (difficulty == "core")
|
if (difficulty == "core")
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_botController.GetBotCoreDifficulty()));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_botController.GetBotCoreDifficulty())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_botController.GetBotDifficulty(sessionID, type, difficulty)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_botController.GetBotDifficulty(sessionID, type, difficulty))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -47,16 +50,24 @@ public class BotCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetAllBotDifficulties(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetAllBotDifficulties(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_botController.GetAllBotDifficulties()));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GenerateBotsRequestData info, string sessionID)
|
public ValueTask<string> GenerateBots(
|
||||||
|
string url,
|
||||||
|
GenerateBotsRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_botController.Generate(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_botController.Generate(sessionID, info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ public class BtrDeliveryCallbacks(
|
|||||||
SaveServer _saveServer,
|
SaveServer _saveServer,
|
||||||
HashUtil _hashUtil,
|
HashUtil _hashUtil,
|
||||||
ItemHelper _itemHelper
|
ItemHelper _itemHelper
|
||||||
)
|
) : IOnUpdate
|
||||||
: IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly BtrDeliveryConfig _btrDeliveryConfig = _configServer.GetConfig<BtrDeliveryConfig>();
|
private readonly BtrDeliveryConfig _btrDeliveryConfig =
|
||||||
|
_configServer.GetConfig<BtrDeliveryConfig>();
|
||||||
|
|
||||||
public Task<bool> OnUpdate(long secondsSinceLastRun)
|
public Task<bool> OnUpdate(long secondsSinceLastRun)
|
||||||
{
|
{
|
||||||
@@ -81,9 +81,13 @@ public class BtrDeliveryCallbacks(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Found {deliveryList.Count} BTR delivery package(s) in profile {sessionId}");
|
_logger.Debug(
|
||||||
|
$"Found {deliveryList.Count} BTR delivery package(s) in profile {sessionId}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return deliveryList.Where(toBeDelivered => currentTime >= toBeDelivered.ScheduledTime).ToList();
|
return deliveryList
|
||||||
|
.Where(toBeDelivered => currentTime >= toBeDelivered.ScheduledTime)
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class BuildsCallbacks(
|
public class BuildsCallbacks(HttpResponseUtil _httpResponseUtil, BuildController _buildController)
|
||||||
HttpResponseUtil _httpResponseUtil,
|
|
||||||
BuildController _buildController
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/builds/list
|
/// Handle client/builds/list
|
||||||
@@ -19,7 +16,9 @@ public class BuildsCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetBuilds(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetBuilds(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_buildController.GetUserBuilds(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_buildController.GetUserBuilds(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -29,7 +28,11 @@ public class BuildsCallbacks(
|
|||||||
/// <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(string url, SetMagazineRequest request, string sessionID)
|
public ValueTask<string> CreateMagazineTemplate(
|
||||||
|
string url,
|
||||||
|
SetMagazineRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_buildController.CreateMagazineTemplate(sessionID, request);
|
_buildController.CreateMagazineTemplate(sessionID, request);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -39,7 +42,11 @@ public class BuildsCallbacks(
|
|||||||
/// Handle client/builds/weapon/save
|
/// Handle client/builds/weapon/save
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SetWeapon(string url, PresetBuildActionRequestData request, string sessionID)
|
public ValueTask<string> SetWeapon(
|
||||||
|
string url,
|
||||||
|
PresetBuildActionRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_buildController.SaveWeaponBuild(sessionID, request);
|
_buildController.SaveWeaponBuild(sessionID, request);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -49,7 +56,11 @@ public class BuildsCallbacks(
|
|||||||
/// Handle client/builds/equipment/save
|
/// Handle client/builds/equipment/save
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SetEquipment(string url, PresetBuildActionRequestData request, string sessionID)
|
public ValueTask<string> SetEquipment(
|
||||||
|
string url,
|
||||||
|
PresetBuildActionRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_buildController.SaveEquipmentBuild(sessionID, request);
|
_buildController.SaveEquipmentBuild(sessionID, request);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -59,7 +70,11 @@ public class BuildsCallbacks(
|
|||||||
/// Handle client/builds/delete
|
/// Handle client/builds/delete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> DeleteBuild(string url, RemoveBuildRequestData request, string sessionID)
|
public ValueTask<string> DeleteBuild(
|
||||||
|
string url,
|
||||||
|
RemoveBuildRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_buildController.RemoveBuild(sessionID, request);
|
_buildController.RemoveBuild(sessionID, request);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class BundleCallbacks(
|
public class BundleCallbacks(HttpResponseUtil _httpResponseUtil, BundleLoader _bundleLoader)
|
||||||
HttpResponseUtil _httpResponseUtil,
|
|
||||||
BundleLoader _bundleLoader)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle singleplayer/bundles
|
/// Handle singleplayer/bundles
|
||||||
|
|||||||
@@ -41,15 +41,26 @@ public class ClientLogCallbacks(
|
|||||||
? _localisationService.GetText("release-beta-disclaimer-mods-enabled")
|
? _localisationService.GetText("release-beta-disclaimer-mods-enabled")
|
||||||
: _localisationService.GetText("release-beta-disclaimer");
|
: _localisationService.GetText("release-beta-disclaimer");
|
||||||
|
|
||||||
data.BetaDisclaimerAcceptText = _localisationService.GetText("release-beta-disclaimer-accept");
|
data.BetaDisclaimerAcceptText = _localisationService.GetText(
|
||||||
|
"release-beta-disclaimer-accept"
|
||||||
|
);
|
||||||
data.ServerModsLoadedText = _localisationService.GetText("release-server-mods-loaded");
|
data.ServerModsLoadedText = _localisationService.GetText("release-server-mods-loaded");
|
||||||
data.ServerModsLoadedDebugText = _localisationService.GetText("release-server-mods-debug-message");
|
data.ServerModsLoadedDebugText = _localisationService.GetText(
|
||||||
|
"release-server-mods-debug-message"
|
||||||
|
);
|
||||||
data.ClientModsLoadedText = _localisationService.GetText("release-plugins-loaded");
|
data.ClientModsLoadedText = _localisationService.GetText("release-plugins-loaded");
|
||||||
data.ClientModsLoadedDebugText = _localisationService.GetText("release-plugins-loaded-debug-message");
|
data.ClientModsLoadedDebugText = _localisationService.GetText(
|
||||||
data.IllegalPluginsLoadedText = _localisationService.GetText("release-illegal-plugins-loaded");
|
"release-plugins-loaded-debug-message"
|
||||||
data.IllegalPluginsExceptionText = _localisationService.GetText("release-illegal-plugins-exception");
|
);
|
||||||
|
data.IllegalPluginsLoadedText = _localisationService.GetText(
|
||||||
|
"release-illegal-plugins-loaded"
|
||||||
|
);
|
||||||
|
data.IllegalPluginsExceptionText = _localisationService.GetText(
|
||||||
|
"release-illegal-plugins-exception"
|
||||||
|
);
|
||||||
data.ReleaseSummaryText = _localisationService.GetText("release-summary");
|
data.ReleaseSummaryText = _localisationService.GetText("release-summary");
|
||||||
data.IsBeta = ProgramStatics.ENTRY_TYPE() is EntryType.BLEEDING_EDGE or EntryType.BLEEDING_EDGE_MODS;
|
data.IsBeta =
|
||||||
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,15 @@ public class CustomizationCallbacks(
|
|||||||
/// Handle client/trading/customization/storage
|
/// Handle client/trading/customization/storage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetCustomisationUnlocks(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetCustomisationUnlocks(
|
||||||
|
string url,
|
||||||
|
EmptyRequestData _,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_saveServer.GetProfile(sessionID).CustomisationUnlocks));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_saveServer.GetProfile(sessionID).CustomisationUnlocks)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -33,14 +39,20 @@ public class CustomizationCallbacks(
|
|||||||
var splitUrl = url.Split('/');
|
var splitUrl = url.Split('/');
|
||||||
var traderId = splitUrl[^3];
|
var traderId = splitUrl[^3];
|
||||||
|
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_customizationController.GetTraderSuits(traderId, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_customizationController.GetTraderSuits(traderId, sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle CustomizationBuy event
|
/// Handle CustomizationBuy event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse BuyCustomisation(PmcData pmcData, BuyClothingRequestData request, string sessionID)
|
public ItemEventRouterResponse BuyCustomisation(
|
||||||
|
PmcData pmcData,
|
||||||
|
BuyClothingRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _customizationController.BuyCustomisation(pmcData, request, sessionID);
|
return _customizationController.BuyCustomisation(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -49,9 +61,15 @@ 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(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetHideoutCustomisation(
|
||||||
|
string url,
|
||||||
|
EmptyRequestData _,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_customizationController.GetHideoutCustomisation(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_customizationController.GetHideoutCustomisation(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -60,14 +78,20 @@ public class CustomizationCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetStorage(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetStorage(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_customizationController.GetCustomisationStorage(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_customizationController.GetCustomisationStorage(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle CustomizationSet
|
/// Handle CustomizationSet
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SetCustomisation(PmcData pmcData, CustomizationSetRequest request, string sessionID)
|
public ItemEventRouterResponse SetCustomisation(
|
||||||
|
PmcData pmcData,
|
||||||
|
CustomizationSetRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _customizationController.SetCustomisation(sessionID, request, pmcData);
|
return _customizationController.SetCustomisation(sessionID, request, pmcData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTemplateItems(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTemplateItems(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetUnclearedBody(_databaseService.GetItems()));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetUnclearedBody(_databaseService.GetItems())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -61,7 +63,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTemplateSuits(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTemplateSuits(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetTemplates().Customization));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetTemplates().Customization)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -70,7 +74,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetTemplateCharacter(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTemplateCharacter(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetTemplates().Character));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetTemplates().Character)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -79,7 +85,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutSettings(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetHideoutSettings(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetHideout().Settings));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetHideout().Settings)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -88,7 +96,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutAreas(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetHideoutAreas(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetHideout().Areas));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetHideout().Areas)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -97,7 +107,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetHideoutProduction(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetHideoutProduction(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetHideout().Production));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetHideout().Production)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -106,7 +118,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocalesLanguages(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetLocalesLanguages(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetLocales().Languages));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetLocales().Languages)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -117,7 +131,8 @@ 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 = locales.Menu?[localeId] ?? locales.Menu?.FirstOrDefault(m => m.Key == "en").Value;
|
var result =
|
||||||
|
locales.Menu?[localeId] ?? locales.Menu?.FirstOrDefault(m => m.Key == "en").Value;
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
@@ -145,7 +160,9 @@ public class DataCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetQteList(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetQteList(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetUnclearedBody(_hideoutController.GetQteList(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetUnclearedBody(_hideoutController.GetQteList(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -156,6 +173,8 @@ public class DataCallbacks(
|
|||||||
{
|
{
|
||||||
var traderId = url.Replace("/client/items/prices/", "");
|
var traderId = url.Replace("/client/items/prices/", "");
|
||||||
|
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_traderController.GetItemPrices(sessionID, traderId)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_traderController.GetItemPrices(sessionID, traderId))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ public class DialogueCallbacks(
|
|||||||
TimeUtil _timeUtil,
|
TimeUtil _timeUtil,
|
||||||
HttpResponseUtil _httpResponseUtil,
|
HttpResponseUtil _httpResponseUtil,
|
||||||
DialogueController _dialogueController
|
DialogueController _dialogueController
|
||||||
)
|
) : IOnUpdate
|
||||||
: IOnUpdate
|
|
||||||
{
|
{
|
||||||
public Task<bool> OnUpdate(long timeSinceLastRun)
|
public Task<bool> OnUpdate(long timeSinceLastRun)
|
||||||
{
|
{
|
||||||
@@ -29,14 +28,20 @@ public class DialogueCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetFriendList(string url, EmptyRequestData _, string sessionID)
|
public virtual ValueTask<string> GetFriendList(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.GetFriendList(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GetChatServerListRequestData request, string sessionID)
|
public virtual ValueTask<string> GetChatServerList(
|
||||||
|
string url,
|
||||||
|
GetChatServerListRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var chatServer = new List<ChatServer>
|
var chatServer = new List<ChatServer>
|
||||||
{
|
{
|
||||||
@@ -50,15 +55,8 @@ public class DialogueCallbacks(
|
|||||||
VersionId = "bgkidft87ddd",
|
VersionId = "bgkidft87ddd",
|
||||||
Ip = "",
|
Ip = "",
|
||||||
Port = 0,
|
Port = 0,
|
||||||
Chats =
|
Chats = [new Chat { Id = "0", Members = 0 }],
|
||||||
[
|
},
|
||||||
new Chat
|
|
||||||
{
|
|
||||||
Id = "0",
|
|
||||||
Members = 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(chatServer));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(chatServer));
|
||||||
@@ -69,9 +67,20 @@ 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(string url, GetMailDialogListRequestData request, string sessionID)
|
public virtual ValueTask<string> GetMailDialogList(
|
||||||
|
string url,
|
||||||
|
GetMailDialogListRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.GenerateDialogueList(sessionID), 0, null, false));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(
|
||||||
|
_dialogueController.GenerateDialogueList(sessionID),
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -81,25 +90,48 @@ public class DialogueCallbacks(
|
|||||||
/// <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 virtual ValueTask<string> GetMailDialogView(string url, GetMailDialogViewRequestData request, string sessionID)
|
public virtual ValueTask<string> GetMailDialogView(
|
||||||
|
string url,
|
||||||
|
GetMailDialogViewRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.GenerateDialogueView(request, sessionID), 0, null, false));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GetMailDialogInfoRequestData request, string sessionID)
|
public virtual ValueTask<string> GetMailDialogInfo(
|
||||||
|
string url,
|
||||||
|
GetMailDialogInfoRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.GetDialogueInfo(request.DialogId, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, RemoveDialogRequestData request, string sessionID)
|
public virtual ValueTask<string> RemoveDialog(
|
||||||
|
string url,
|
||||||
|
RemoveDialogRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_dialogueController.RemoveDialogue(request.DialogId, sessionID);
|
_dialogueController.RemoveDialogue(request.DialogId, sessionID);
|
||||||
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -109,7 +141,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/pin
|
/// Handle client/mail/dialog/pin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> PinDialog(string url, PinDialogRequestData request, string sessionID)
|
public virtual ValueTask<string> PinDialog(
|
||||||
|
string url,
|
||||||
|
PinDialogRequestData request,
|
||||||
|
string 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());
|
||||||
@@ -119,7 +155,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/unpin
|
/// Handle client/mail/dialog/unpin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> UnpinDialog(string url, PinDialogRequestData request, string sessionID)
|
public virtual ValueTask<string> UnpinDialog(
|
||||||
|
string url,
|
||||||
|
PinDialogRequestData request,
|
||||||
|
string 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());
|
||||||
@@ -129,7 +169,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/read
|
/// Handle client/mail/dialog/read
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> SetRead(string url, SetDialogReadRequestData request, string sessionID)
|
public virtual ValueTask<string> SetRead(
|
||||||
|
string url,
|
||||||
|
SetDialogReadRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_dialogueController.SetRead(request.Dialogs, sessionID);
|
_dialogueController.SetRead(request.Dialogs, sessionID);
|
||||||
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
||||||
@@ -139,18 +183,32 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/mail/dialog/getAllAttachments
|
/// Handle client/mail/dialog/getAllAttachments
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> GetAllAttachments(string url, GetAllAttachmentsRequestData request, string sessionID)
|
public virtual ValueTask<string> GetAllAttachments(
|
||||||
|
string url,
|
||||||
|
GetAllAttachmentsRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.GetAllAttachments(request.DialogId, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_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 ValueTask<string> SendMessage(string url, SendMessageRequest request, string sessionID)
|
public virtual ValueTask<string> SendMessage(
|
||||||
|
string url,
|
||||||
|
SendMessageRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.SendMessage(sessionID, request)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_dialogueController.SendMessage(sessionID, request))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -175,16 +233,26 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/send
|
/// Handle client/friend/request/send
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> SendFriendRequest(string url, FriendRequestData request, string sessionID)
|
public virtual ValueTask<string> SendFriendRequest(
|
||||||
|
string url,
|
||||||
|
FriendRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_dialogueController.SendFriendRequest(sessionID, request)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, EmptyRequestData _, string sessionID)
|
public virtual ValueTask<string> AcceptAllFriendRequests(
|
||||||
|
string url,
|
||||||
|
EmptyRequestData _,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -193,7 +261,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/accept
|
/// Handle client/friend/request/accept
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> AcceptFriendRequest(string url, AcceptFriendRequestData request, string sessionID)
|
public virtual ValueTask<string> AcceptFriendRequest(
|
||||||
|
string url,
|
||||||
|
AcceptFriendRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -202,7 +274,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/decline
|
/// Handle client/friend/request/decline
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> DeclineFriendRequest(string url, DeclineFriendRequestData request, string sessionID)
|
public virtual ValueTask<string> DeclineFriendRequest(
|
||||||
|
string url,
|
||||||
|
DeclineFriendRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -211,7 +287,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/request/cancel
|
/// Handle client/friend/request/cancel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> CancelFriendRequest(string url, CancelFriendRequestData request, string sessionID)
|
public virtual ValueTask<string> CancelFriendRequest(
|
||||||
|
string url,
|
||||||
|
CancelFriendRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -220,7 +300,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/delete
|
/// Handle client/friend/delete
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> DeleteFriend(string url, DeleteFriendRequest request, string sessionID)
|
public virtual ValueTask<string> DeleteFriend(
|
||||||
|
string url,
|
||||||
|
DeleteFriendRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_dialogueController.DeleteFriend(sessionID, request);
|
_dialogueController.DeleteFriend(sessionID, request);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -230,7 +314,11 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/ignore/set
|
/// Handle client/friend/ignore/set
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> IgnoreFriend(string url, UIDRequestData request, string sessionID)
|
public virtual ValueTask<string> IgnoreFriend(
|
||||||
|
string url,
|
||||||
|
UIDRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -239,34 +327,58 @@ public class DialogueCallbacks(
|
|||||||
/// Handle client/friend/ignore/remove
|
/// Handle client/friend/ignore/remove
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual ValueTask<string> UnIgnoreFriend(string url, UIDRequestData request, string sessionID)
|
public virtual ValueTask<string> UnIgnoreFriend(
|
||||||
|
string url,
|
||||||
|
UIDRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> ClearMail(string url, ClearMailMessageRequest request, string sessionID)
|
public virtual ValueTask<string> ClearMail(
|
||||||
|
string url,
|
||||||
|
ClearMailMessageRequest request,
|
||||||
|
string 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(string url, CreateGroupMailRequest request, string sessionID)
|
public virtual ValueTask<string> CreateGroupMail(
|
||||||
|
string url,
|
||||||
|
CreateGroupMailRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
return new ValueTask<string>(_httpResponseUtil.EmptyArrayResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual ValueTask<string> ChangeMailGroupOwner(string url, ChangeGroupMailOwnerRequest request, string sessionID)
|
public virtual ValueTask<string> ChangeMailGroupOwner(
|
||||||
|
string url,
|
||||||
|
ChangeGroupMailOwnerRequest request,
|
||||||
|
string 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(string url, AddUserGroupMailRequest request, string sessionID)
|
public virtual ValueTask<string> AddUserToMail(
|
||||||
|
string url,
|
||||||
|
AddUserGroupMailRequest request,
|
||||||
|
string 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(string url, RemoveUserGroupMailRequest request, string sessionID)
|
public virtual ValueTask<string> RemoveUserFromMail(
|
||||||
|
string url,
|
||||||
|
RemoveUserGroupMailRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
return new ValueTask<string>("Not Implemented!"); // Not implemented in Node
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ public class GameCallbacks(
|
|||||||
/// Handle client/game/version/validate
|
/// Handle client/game/version/validate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> VersionValidate(string url, VersionValidateRequestData info, string sessionID)
|
public ValueTask<string> VersionValidate(
|
||||||
|
string url,
|
||||||
|
VersionValidateRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -41,12 +45,9 @@ 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>(_httpResponseUtil.GetBody(
|
return new ValueTask<string>(
|
||||||
new GameStartResponse
|
_httpResponseUtil.GetBody(new GameStartResponse { UtcTime = startTimestampSec })
|
||||||
{
|
);
|
||||||
UtcTime = startTimestampSec
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -57,21 +58,22 @@ public class GameCallbacks(
|
|||||||
public async ValueTask<string> GameLogout(string url, EmptyRequestData _, string sessionID)
|
public async ValueTask<string> GameLogout(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
await _saveServer.SaveProfileAsync(sessionID);
|
await _saveServer.SaveProfileAsync(sessionID);
|
||||||
return _httpResponseUtil.GetBody(
|
return _httpResponseUtil.GetBody(new GameLogoutResponseData { Status = "ok" });
|
||||||
new GameLogoutResponseData
|
|
||||||
{
|
|
||||||
Status = "ok"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/config
|
/// Handle client/game/config
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGameConfig(string url, GameEmptyCrcRequestData info, string sessionID)
|
public ValueTask<string> GetGameConfig(
|
||||||
|
string url,
|
||||||
|
GameEmptyCrcRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetGameConfig(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetGameConfig(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -80,7 +82,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGameMode(string url, GameModeRequestData info, string sessionID)
|
public ValueTask<string> GetGameMode(string url, GameModeRequestData info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetGameMode(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetGameMode(sessionID, info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -89,7 +93,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetServer(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetServer(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetServer(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetServer(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -98,7 +104,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetCurrentGroup(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetCurrentGroup(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetCurrentGroup(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetCurrentGroup(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -107,7 +115,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ValidateGameVersion(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> ValidateGameVersion(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetValidGameVersion(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetValidGameVersion(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -116,7 +126,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GameKeepalive(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GameKeepalive(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetKeepAlive(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetKeepAlive(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -126,12 +138,9 @@ public class GameCallbacks(
|
|||||||
public ValueTask<string> GetVersion(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetVersion(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
// change to be a proper type
|
// change to be a proper type
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new
|
_httpResponseUtil.NoBody(new { Version = _watermark.GetInGameVersionLabel() })
|
||||||
{
|
);
|
||||||
Version = _watermark.GetInGameVersionLabel()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -149,7 +158,9 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetRaidTime(string url, GetRaidTimeRequest request, string sessionID)
|
public ValueTask<string> GetRaidTime(string url, GetRaidTimeRequest request, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_gameController.GetRaidTime(sessionID, request)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_gameController.GetRaidTime(sessionID, request))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -158,14 +169,20 @@ public class GameCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetSurvey(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetSurvey(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_gameController.GetSurvey(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_gameController.GetSurvey(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/survey/view
|
/// Handle client/survey/view
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetSurveyView(string url, SendSurveyOpinionRequest request, string sessionID)
|
public ValueTask<string> GetSurveyView(
|
||||||
|
string url,
|
||||||
|
SendSurveyOpinionRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -174,7 +191,11 @@ public class GameCallbacks(
|
|||||||
/// Handle client/survey/opinion
|
/// Handle client/survey/opinion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SendSurveyOpinion(string url, SendSurveyOpinionRequest request, string sessionID)
|
public ValueTask<string> SendSurveyOpinion(
|
||||||
|
string url,
|
||||||
|
SendSurveyOpinionRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,11 @@ 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, string sessionID)
|
public ValueTask<string> HandleWorkoutEffects(string url, WorkoutData info, string sessionID)
|
||||||
{
|
{
|
||||||
_healthController.ApplyWorkoutChanges(_profileHelper.GetPmcProfile(sessionID), info, sessionID);
|
_healthController.ApplyWorkoutChanges(
|
||||||
|
_profileHelper.GetPmcProfile(sessionID),
|
||||||
|
info,
|
||||||
|
sessionID
|
||||||
|
);
|
||||||
return new ValueTask<string>(_httpResponseUtil.EmptyResponse());
|
return new ValueTask<string>(_httpResponseUtil.EmptyResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +39,11 @@ 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(PmcData pmcData, OffraidEatRequestData info, string sessionID)
|
public ItemEventRouterResponse OffraidEat(
|
||||||
|
PmcData pmcData,
|
||||||
|
OffraidEatRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _healthController.OffRaidEat(pmcData, info, sessionID);
|
return _healthController.OffRaidEat(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -47,7 +55,11 @@ 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(PmcData pmcData, OffraidHealRequestData info, string sessionID)
|
public ItemEventRouterResponse OffraidHeal(
|
||||||
|
PmcData pmcData,
|
||||||
|
OffraidHealRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _healthController.OffRaidHeal(pmcData, info, sessionID);
|
return _healthController.OffRaidHeal(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -59,7 +71,11 @@ 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(PmcData pmcData, HealthTreatmentRequestData info, string sessionID)
|
public ItemEventRouterResponse HealthTreatment(
|
||||||
|
PmcData pmcData,
|
||||||
|
HealthTreatmentRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _healthController.HealthTreatment(pmcData, info, sessionID);
|
return _healthController.HealthTreatment(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ 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(
|
public class HideoutCallbacks(HideoutController _hideoutController, ConfigServer _configServer)
|
||||||
HideoutController _hideoutController,
|
: IOnUpdate
|
||||||
ConfigServer _configServer
|
|
||||||
) : IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly HideoutConfig _hideoutConfig = _configServer.GetConfig<HideoutConfig>();
|
private readonly HideoutConfig _hideoutConfig = _configServer.GetConfig<HideoutConfig>();
|
||||||
|
|
||||||
@@ -33,7 +31,12 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutUpgrade event
|
/// Handle HideoutUpgrade event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse Upgrade(PmcData pmcData, HideoutUpgradeRequestData request, string sessionID, ItemEventRouterResponse output)
|
public ItemEventRouterResponse Upgrade(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutUpgradeRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutController.StartUpgrade(pmcData, request, sessionID, output);
|
_hideoutController.StartUpgrade(pmcData, request, sessionID, output);
|
||||||
|
|
||||||
@@ -43,7 +46,12 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutUpgradeComplete event
|
/// Handle HideoutUpgradeComplete event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse UpgradeComplete(PmcData pmcData, HideoutUpgradeCompleteRequestData request, string sessionID, ItemEventRouterResponse output)
|
public ItemEventRouterResponse UpgradeComplete(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutUpgradeCompleteRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutController.UpgradeComplete(pmcData, request, sessionID, output);
|
_hideoutController.UpgradeComplete(pmcData, request, sessionID, output);
|
||||||
|
|
||||||
@@ -53,7 +61,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutPutItemsInAreaSlots
|
/// Handle HideoutPutItemsInAreaSlots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse PutItemsInAreaSlots(PmcData pmcData, HideoutPutItemInRequestData request, string sessionID)
|
public ItemEventRouterResponse PutItemsInAreaSlots(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutPutItemInRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.PutItemsInAreaSlots(pmcData, request, sessionID);
|
return _hideoutController.PutItemsInAreaSlots(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -61,7 +73,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutTakeItemsFromAreaSlots event
|
/// Handle HideoutTakeItemsFromAreaSlots event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse TakeItemsFromAreaSlots(PmcData pmcData, HideoutTakeItemOutRequestData request, string sessionID)
|
public ItemEventRouterResponse TakeItemsFromAreaSlots(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutTakeItemOutRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.TakeItemsFromAreaSlots(pmcData, request, sessionID);
|
return _hideoutController.TakeItemsFromAreaSlots(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -69,7 +85,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutToggleArea event
|
/// Handle HideoutToggleArea event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ToggleArea(PmcData pmcData, HideoutToggleAreaRequestData request, string sessionID)
|
public ItemEventRouterResponse ToggleArea(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutToggleAreaRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.ToggleArea(pmcData, request, sessionID);
|
return _hideoutController.ToggleArea(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -77,7 +97,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutSingleProductionStart event
|
/// Handle HideoutSingleProductionStart event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse SingleProductionStart(PmcData pmcData, HideoutSingleProductionStartRequestData request, string sessionID)
|
public ItemEventRouterResponse SingleProductionStart(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutSingleProductionStartRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.SingleProductionStart(pmcData, request, sessionID);
|
return _hideoutController.SingleProductionStart(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -85,7 +109,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutScavCaseProductionStart event
|
/// Handle HideoutScavCaseProductionStart event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ScavCaseProductionStart(PmcData pmcData, HideoutScavCaseStartRequestData request, string sessionID)
|
public ItemEventRouterResponse ScavCaseProductionStart(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutScavCaseStartRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.ScavCaseProductionStart(pmcData, request, sessionID);
|
return _hideoutController.ScavCaseProductionStart(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -93,7 +121,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutContinuousProductionStart
|
/// Handle HideoutContinuousProductionStart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ContinuousProductionStart(PmcData pmcData, HideoutContinuousProductionStartRequestData request, string sessionID)
|
public ItemEventRouterResponse ContinuousProductionStart(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutContinuousProductionStartRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.ContinuousProductionStart(pmcData, request, sessionID);
|
return _hideoutController.ContinuousProductionStart(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -101,7 +133,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutTakeProduction event
|
/// Handle HideoutTakeProduction event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse TakeProduction(PmcData pmcData, HideoutTakeProductionRequestData request, string sessionID)
|
public ItemEventRouterResponse TakeProduction(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutTakeProductionRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.TakeProduction(pmcData, request, sessionID);
|
return _hideoutController.TakeProduction(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -109,7 +145,12 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle HideoutQuickTimeEvent
|
/// Handle HideoutQuickTimeEvent
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse HandleQTEEvent(PmcData pmcData, HandleQTEEventRequestData request, string sessionID, ItemEventRouterResponse output)
|
public ItemEventRouterResponse HandleQTEEvent(
|
||||||
|
PmcData pmcData,
|
||||||
|
HandleQTEEventRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutController.HandleQTEEventOutcome(sessionID, pmcData, request, output);
|
_hideoutController.HandleQTEEventOutcome(sessionID, pmcData, request, output);
|
||||||
|
|
||||||
@@ -119,8 +160,12 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse RecordShootingRangePoints(PmcData pmcData, RecordShootingRangePoints request, string sessionID,
|
public ItemEventRouterResponse RecordShootingRangePoints(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
RecordShootingRangePoints request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutController.RecordShootingRangePoints(sessionID, pmcData, request);
|
_hideoutController.RecordShootingRangePoints(sessionID, pmcData, request);
|
||||||
|
|
||||||
@@ -130,7 +175,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
/// Handle client/game/profile/items/moving - RecordShootingRangePoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse ImproveArea(PmcData pmcData, HideoutImproveAreaRequestData request, string sessionID)
|
public ItemEventRouterResponse ImproveArea(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutImproveAreaRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.ImproveArea(sessionID, pmcData, request);
|
return _hideoutController.ImproveArea(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -138,7 +187,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - HideoutCancelProductionCommand
|
/// Handle client/game/profile/items/moving - HideoutCancelProductionCommand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse CancelProduction(PmcData pmcData, HideoutCancelProductionRequestData request, string sessionID)
|
public ItemEventRouterResponse CancelProduction(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutCancelProductionRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.CancelProduction(sessionID, pmcData, request);
|
return _hideoutController.CancelProduction(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -146,7 +199,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - HideoutCircleOfCultistProductionStart
|
/// Handle client/game/profile/items/moving - HideoutCircleOfCultistProductionStart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse CicleOfCultistProductionStart(PmcData pmcData, HideoutCircleOfCultistProductionStartRequestData request, string sessionID)
|
public ItemEventRouterResponse CicleOfCultistProductionStart(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutCircleOfCultistProductionStartRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.CicleOfCultistProductionStart(sessionID, pmcData, request);
|
return _hideoutController.CicleOfCultistProductionStart(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -154,7 +211,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - HideoutDeleteProductionCommand
|
/// Handle client/game/profile/items/moving - HideoutDeleteProductionCommand
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse HideoutDeleteProductionCommand(PmcData pmcData, HideoutDeleteProductionRequestData request, string sessionID)
|
public ItemEventRouterResponse HideoutDeleteProductionCommand(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutDeleteProductionRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.HideoutDeleteProductionCommand(sessionID, pmcData, request);
|
return _hideoutController.HideoutDeleteProductionCommand(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -162,7 +223,11 @@ public class HideoutCallbacks(
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/game/profile/items/moving - HideoutCustomizationApply
|
/// Handle client/game/profile/items/moving - HideoutCustomizationApply
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemEventRouterResponse HideoutCustomizationApplyCommand(PmcData pmcData, HideoutCustomizationApplyRequestData request, string sessionID)
|
public ItemEventRouterResponse HideoutCustomizationApplyCommand(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutCustomizationApplyRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.HideoutCustomizationApply(sessionID, pmcData, request);
|
return _hideoutController.HideoutCustomizationApply(sessionID, pmcData, request);
|
||||||
}
|
}
|
||||||
@@ -171,7 +236,11 @@ public class HideoutCallbacks(
|
|||||||
/// Handle client/game/profile/items/moving - hideoutCustomizationSetMannequinPose
|
/// Handle client/game/profile/items/moving - hideoutCustomizationSetMannequinPose
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse HideoutCustomizationSetMannequinPose(PmcData pmcData, HideoutCustomizationSetMannequinPoseRequest request, string sessionId)
|
public ItemEventRouterResponse HideoutCustomizationSetMannequinPose(
|
||||||
|
PmcData pmcData,
|
||||||
|
HideoutCustomizationSetMannequinPoseRequest request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _hideoutController.HideoutCustomizationSetMannequinPose(sessionId, pmcData, request);
|
return _hideoutController.HideoutCustomizationSetMannequinPose(sessionId, pmcData, request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using SPTarkov.Server.Core.DI;
|
|||||||
using SPTarkov.Server.Core.Servers;
|
using SPTarkov.Server.Core.Servers;
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton, TypePriority = OnLoadOrder.HttpCallbacks)]
|
[Injectable(InjectionType.Singleton, TypePriority = OnLoadOrder.HttpCallbacks)]
|
||||||
public class HttpCallbacks(HttpServer _httpServer) : IOnLoad
|
public class HttpCallbacks(HttpServer _httpServer) : IOnLoad
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
namespace SPTarkov.Server.Core.Callbacks;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class InraidCallbacks(
|
public class InraidCallbacks(InRaidController _inRaidController, HttpResponseUtil _httpResponseUtil)
|
||||||
InRaidController _inRaidController,
|
|
||||||
HttpResponseUtil _httpResponseUtil
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/location/getLocalloot
|
/// Handle client/location/getLocalloot
|
||||||
@@ -20,7 +17,11 @@ public class InraidCallbacks(
|
|||||||
/// <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(string url, RegisterPlayerRequestData info, string sessionID)
|
public ValueTask<string> RegisterPlayer(
|
||||||
|
string url,
|
||||||
|
RegisterPlayerRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inRaidController.AddPlayer(sessionID, info);
|
_inRaidController.AddPlayer(sessionID, info);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -45,16 +46,24 @@ public class InraidCallbacks(
|
|||||||
/// <returns>JSON as string</returns>
|
/// <returns>JSON as string</returns>
|
||||||
public ValueTask<string> GetRaidMenuSettings()
|
public ValueTask<string> GetRaidMenuSettings()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_inRaidController.GetInRaidConfig().RaidMenuSettings));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTraitorScavHostileChance(
|
||||||
|
string url,
|
||||||
|
EmptyRequestData _,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_inRaidController.GetTraitorScavHostileChance(url, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_inRaidController.GetTraitorScavHostileChance(url, sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -63,6 +72,8 @@ public class InraidCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetBossTypes(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetBossTypes(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_inRaidController.GetBossTypes(url, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_inRaidController.GetBossTypes(url, sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ public class InsuranceCallbacks(
|
|||||||
InsuranceService _insuranceService,
|
InsuranceService _insuranceService,
|
||||||
HttpResponseUtil _httpResponseUtil,
|
HttpResponseUtil _httpResponseUtil,
|
||||||
ConfigServer _configServer
|
ConfigServer _configServer
|
||||||
)
|
) : IOnUpdate
|
||||||
: IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly InsuranceConfig _insuranceConfig = _configServer.GetConfig<InsuranceConfig>();
|
private readonly InsuranceConfig _insuranceConfig = _configServer.GetConfig<InsuranceConfig>();
|
||||||
|
|
||||||
@@ -41,9 +40,15 @@ 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(string url, GetInsuranceCostRequestData info, string sessionID)
|
public ValueTask<string> GetInsuranceCost(
|
||||||
|
string url,
|
||||||
|
GetInsuranceCostRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_insuranceController.Cost(info, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_insuranceController.Cost(info, sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,8 +21,12 @@ 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 MoveItem(PmcData pmcData, InventoryMoveRequestData info, string sessionID,
|
public ItemEventRouterResponse MoveItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryMoveRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.MoveItem(pmcData, info, sessionID, output);
|
_inventoryController.MoveItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -36,8 +40,12 @@ 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 RemoveItem(PmcData pmcData, InventoryRemoveRequestData info, string sessionID,
|
public ItemEventRouterResponse RemoveItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryRemoveRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.DiscardItem(pmcData, info, sessionID, output);
|
_inventoryController.DiscardItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -51,8 +59,12 @@ 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 SplitItem(PmcData pmcData, InventorySplitRequestData info, string sessionID,
|
public ItemEventRouterResponse SplitItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventorySplitRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.SplitItem(pmcData, info, sessionID, output);
|
_inventoryController.SplitItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -65,8 +77,12 @@ 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 MergeItem(PmcData pmcData, InventoryMergeRequestData info, string sessionID,
|
public ItemEventRouterResponse MergeItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryMergeRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.MergeItem(pmcData, info, sessionID, output);
|
_inventoryController.MergeItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -79,8 +95,12 @@ 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 TransferItem(PmcData pmcData, InventoryTransferRequestData info, string sessionID,
|
public ItemEventRouterResponse TransferItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryTransferRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.TransferItem(pmcData, info, sessionID, output);
|
_inventoryController.TransferItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -93,7 +113,11 @@ 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(PmcData pmcData, InventorySwapRequestData info, string sessionID)
|
public ItemEventRouterResponse SwapItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventorySwapRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _inventoryController.SwapItem(pmcData, info, sessionID);
|
return _inventoryController.SwapItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -104,7 +128,11 @@ 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(PmcData pmcData, InventoryFoldRequestData info, string sessionID)
|
public ItemEventRouterResponse FoldItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryFoldRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _inventoryController.FoldItem(pmcData, info, sessionID);
|
return _inventoryController.FoldItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -115,7 +143,11 @@ 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(PmcData pmcData, InventoryToggleRequestData info, string sessionID)
|
public ItemEventRouterResponse ToggleItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryToggleRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _inventoryController.ToggleItem(pmcData, info, sessionID);
|
return _inventoryController.ToggleItem(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -126,7 +158,11 @@ 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(PmcData pmcData, InventoryTagRequestData request, string sessionId)
|
public ItemEventRouterResponse TagItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryTagRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _inventoryController.TagItem(pmcData, request, sessionId);
|
return _inventoryController.TagItem(pmcData, request, sessionId);
|
||||||
}
|
}
|
||||||
@@ -138,8 +174,12 @@ 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 BindItem(PmcData pmcData, InventoryBindRequestData info, string sessionID,
|
public ItemEventRouterResponse BindItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryBindRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.BindItem(pmcData, info, sessionID, output);
|
_inventoryController.BindItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -152,8 +192,12 @@ 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 UnBindItem(PmcData pmcData, InventoryBindRequestData info, string sessionID,
|
public ItemEventRouterResponse UnBindItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryBindRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.UnBindItem(pmcData, info, sessionID, output);
|
_inventoryController.UnBindItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -166,8 +210,12 @@ 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 ExamineItem(PmcData pmcData, InventoryExamineRequestData info, string sessionID,
|
public ItemEventRouterResponse ExamineItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryExamineRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.ExamineItem(pmcData, info, sessionID, output);
|
_inventoryController.ExamineItem(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -180,8 +228,11 @@ 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(PmcData pmcData, InventoryReadEncyclopediaRequestData info,
|
public ItemEventRouterResponse ReadEncyclopedia(
|
||||||
string sessionID)
|
PmcData pmcData,
|
||||||
|
InventoryReadEncyclopediaRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _inventoryController.ReadEncyclopedia(pmcData, info, sessionID);
|
return _inventoryController.ReadEncyclopedia(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -194,8 +245,12 @@ 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 SortInventory(PmcData pmcData, InventorySortRequestData info, string sessionID,
|
public ItemEventRouterResponse SortInventory(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventorySortRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.SortInventory(pmcData, info, sessionID, output);
|
_inventoryController.SortInventory(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -208,8 +263,12 @@ 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 CreateMapMarker(PmcData pmcData, InventoryCreateMarkerRequestData info,
|
public ItemEventRouterResponse CreateMapMarker(
|
||||||
string sessionID, ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryCreateMarkerRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.CreateMapMarker(pmcData, info, sessionID, output);
|
_inventoryController.CreateMapMarker(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -222,8 +281,12 @@ 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 DeleteMapMarker(PmcData pmcData, InventoryDeleteMarkerRequestData info,
|
public ItemEventRouterResponse DeleteMapMarker(
|
||||||
string sessionID, ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryDeleteMarkerRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.DeleteMapMarker(pmcData, info, sessionID, output);
|
_inventoryController.DeleteMapMarker(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -236,8 +299,12 @@ 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 EditMapMarker(PmcData pmcData, InventoryEditMarkerRequestData info, string sessionID,
|
public ItemEventRouterResponse EditMapMarker(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryEditMarkerRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.EditMapMarker(pmcData, info, sessionID, output);
|
_inventoryController.EditMapMarker(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -251,9 +318,12 @@ 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 OpenRandomLootContainer(PmcData pmcData, OpenRandomLootContainerRequestData info,
|
public ItemEventRouterResponse OpenRandomLootContainer(
|
||||||
|
PmcData pmcData,
|
||||||
|
OpenRandomLootContainerRequestData info,
|
||||||
string sessionID,
|
string sessionID,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.OpenRandomLootContainer(pmcData, info, sessionID, output);
|
_inventoryController.OpenRandomLootContainer(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -266,8 +336,12 @@ 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 RedeemProfileReward(PmcData pmcData, RedeemProfileRequestData info, string sessionID,
|
public ItemEventRouterResponse RedeemProfileReward(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
RedeemProfileRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.RedeemProfileReward(pmcData, info, sessionID);
|
_inventoryController.RedeemProfileReward(pmcData, info, sessionID);
|
||||||
return output;
|
return output;
|
||||||
@@ -281,8 +355,12 @@ 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 SetFavoriteItem(PmcData pmcData, SetFavoriteItems info, string sessionID,
|
public ItemEventRouterResponse SetFavoriteItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
SetFavoriteItems info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.SetFavoriteItem(pmcData, info, sessionID);
|
_inventoryController.SetFavoriteItem(pmcData, info, sessionID);
|
||||||
return output;
|
return output;
|
||||||
@@ -297,8 +375,12 @@ 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(PmcData pmcData, FailQuestRequestData info, string sessionID,
|
public ItemEventRouterResponse FailQuest(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
FailQuestRequestData info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_questController.FailQuest(pmcData, info, sessionID, output);
|
_questController.FailQuest(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
@@ -311,8 +393,12 @@ 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(PmcData pmcData, PinOrLockItemRequest info, string sessionID,
|
public ItemEventRouterResponse PinOrLock(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
PinOrLockItemRequest info,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_inventoryController.PinOrLock(pmcData, info, sessionID, output);
|
_inventoryController.PinOrLock(pmcData, info, sessionID, output);
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -7,13 +7,24 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
namespace SPTarkov.Server.Core.Callbacks;
|
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(string url, ItemEventRouterRequest info, string sessionID)
|
public async ValueTask<string> HandleEvents(
|
||||||
|
string url,
|
||||||
|
ItemEventRouterRequest info,
|
||||||
|
string 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(eventResponse, GetErrorCode(eventResponse.Warnings), eventResponse.Warnings[0].ErrorMessage)
|
? _httpResponseUtil.GetBody(
|
||||||
|
eventResponse,
|
||||||
|
GetErrorCode(eventResponse.Warnings),
|
||||||
|
eventResponse.Warnings[0].ErrorMessage
|
||||||
|
)
|
||||||
: _httpResponseUtil.GetBody(eventResponse);
|
: _httpResponseUtil.GetBody(eventResponse);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -34,7 +45,7 @@ public class ItemEventCallbacks(HttpResponseUtil _httpResponseUtil, ItemEventRou
|
|||||||
// 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)
|
||||||
@@ -51,6 +62,8 @@ public class ItemEventCallbacks(HttpResponseUtil _httpResponseUtil, ItemEventRou
|
|||||||
public static BackendErrorCodes GetErrorCode(List<Warning> warnings)
|
public static BackendErrorCodes GetErrorCode(List<Warning> warnings)
|
||||||
{
|
{
|
||||||
// Cast int to string to get the error code of 220 for Unknown Error.
|
// Cast int to string to get the error code of 220 for Unknown Error.
|
||||||
return warnings.FirstOrDefault()?.Code is null ? BackendErrorCodes.UnknownError : warnings.FirstOrDefault()?.Code ?? BackendErrorCodes.UnknownError;
|
return warnings.FirstOrDefault()?.Code is null
|
||||||
|
? BackendErrorCodes.UnknownError
|
||||||
|
: warnings.FirstOrDefault()?.Code ?? BackendErrorCodes.UnknownError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,21 +68,33 @@ public class LauncherCallbacks(
|
|||||||
|
|
||||||
public ValueTask<string> RemoveProfile(string url, RemoveProfileData info, string sessionID)
|
public ValueTask<string> RemoveProfile(string url, RemoveProfileData info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_saveServer.RemoveProfile(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_saveServer.RemoveProfile(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> GetCompatibleTarkovVersion()
|
public ValueTask<string> GetCompatibleTarkovVersion()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_launcherController.GetCompatibleTarkovVersion()));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_launcherController.GetCompatibleTarkovVersion())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> GetLoadedServerMods()
|
public ValueTask<string> GetLoadedServerMods()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_launcherController.GetLoadedServerMods()));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_launcherController.GetLoadedServerMods())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> GetServerModsProfileUsed(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetServerModsProfileUsed(
|
||||||
|
string url,
|
||||||
|
EmptyRequestData _,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(_launcherController.GetServerModsProfileUsed(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(_launcherController.GetServerModsProfileUsed(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,32 +15,29 @@ public class LauncherV2Callbacks(
|
|||||||
{
|
{
|
||||||
public ValueTask<string> Ping()
|
public ValueTask<string> Ping()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new LauncherV2PingResponse
|
_httpResponseUtil.NoBody(
|
||||||
{
|
new LauncherV2PingResponse { Response = _launcherV2Controller.Ping() }
|
||||||
Response = _launcherV2Controller.Ping()
|
)
|
||||||
}
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Types()
|
public ValueTask<string> Types()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new LauncherV2TypesResponse
|
_httpResponseUtil.NoBody(
|
||||||
{
|
new LauncherV2TypesResponse { Response = _launcherV2Controller.Types() }
|
||||||
Response = _launcherV2Controller.Types()
|
)
|
||||||
}
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Login(LoginRequestData info)
|
public ValueTask<string> Login(LoginRequestData info)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new LauncherV2LoginResponse
|
_httpResponseUtil.NoBody(
|
||||||
{
|
new LauncherV2LoginResponse { Response = _launcherV2Controller.Login(info) }
|
||||||
Response = _launcherV2Controller.Login(info)
|
)
|
||||||
}
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<string> Register(RegisterData info)
|
public async ValueTask<string> Register(RegisterData info)
|
||||||
@@ -49,7 +46,7 @@ public class LauncherV2Callbacks(
|
|||||||
new LauncherV2RegisterResponse
|
new LauncherV2RegisterResponse
|
||||||
{
|
{
|
||||||
Response = await _launcherV2Controller.Register(info),
|
Response = await _launcherV2Controller.Register(info),
|
||||||
Profiles = _profileController.GetMiniProfiles()
|
Profiles = _profileController.GetMiniProfiles(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -60,63 +57,67 @@ public class LauncherV2Callbacks(
|
|||||||
new LauncherV2PasswordChangeResponse
|
new LauncherV2PasswordChangeResponse
|
||||||
{
|
{
|
||||||
Response = await _launcherV2Controller.PasswordChange(info),
|
Response = await _launcherV2Controller.PasswordChange(info),
|
||||||
Profiles = _profileController.GetMiniProfiles()
|
Profiles = _profileController.GetMiniProfiles(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Remove(LoginRequestData info)
|
public ValueTask<string> Remove(LoginRequestData info)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(
|
||||||
new LauncherV2RemoveResponse
|
new LauncherV2RemoveResponse
|
||||||
{
|
{
|
||||||
Response = _launcherV2Controller.Remove(info),
|
Response = _launcherV2Controller.Remove(info),
|
||||||
Profiles = _profileController.GetMiniProfiles()
|
Profiles = _profileController.GetMiniProfiles(),
|
||||||
}
|
}
|
||||||
));
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> CompatibleVersion()
|
public ValueTask<string> CompatibleVersion()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(
|
||||||
new LauncherV2VersionResponse
|
new LauncherV2VersionResponse
|
||||||
{
|
{
|
||||||
Response = new LauncherV2CompatibleVersion
|
Response = new LauncherV2CompatibleVersion
|
||||||
{
|
{
|
||||||
SptVersion = _launcherV2Controller.SptVersion(),
|
SptVersion = _launcherV2Controller.SptVersion(),
|
||||||
EftVersion = _launcherV2Controller.EftVersion()
|
EftVersion = _launcherV2Controller.EftVersion(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Mods()
|
public ValueTask<string> Mods()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new LauncherV2ModsResponse
|
_httpResponseUtil.NoBody(
|
||||||
{
|
new LauncherV2ModsResponse { Response = _launcherV2Controller.LoadedMods() }
|
||||||
Response = _launcherV2Controller.LoadedMods()
|
)
|
||||||
}
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Profiles()
|
public ValueTask<string> Profiles()
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
new LauncherV2ProfilesResponse
|
_httpResponseUtil.NoBody(
|
||||||
{
|
new LauncherV2ProfilesResponse { Response = _profileController.GetMiniProfiles() }
|
||||||
Response = _profileController.GetMiniProfiles()
|
)
|
||||||
}
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> Profile(string? sessionId)
|
public ValueTask<string> Profile(string? sessionId)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NoBody(
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.NoBody(
|
||||||
new LauncherV2ProfileResponse
|
new LauncherV2ProfileResponse
|
||||||
{
|
{
|
||||||
Response = _launcherV2Controller.GetProfile(sessionId)
|
Response = _launcherV2Controller.GetProfile(sessionId),
|
||||||
}
|
}
|
||||||
));
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,15 +18,23 @@ public class LocationCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocationData(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetLocationData(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_locationController.GenerateAll(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GetAirdropLootRequest info, string sessionID)
|
public ValueTask<string> GetAirdropLoot(
|
||||||
|
string url,
|
||||||
|
GetAirdropLootRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_locationController.GetAirDropLoot(info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_locationController.GetAirDropLoot(info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,12 +54,9 @@ public class MatchCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GroupCurrent(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GroupCurrent(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(
|
return new ValueTask<string>(
|
||||||
new MatchGroupCurrentResponse
|
_httpResponseUtil.GetBody(new MatchGroupCurrentResponse { Squad = [] })
|
||||||
{
|
);
|
||||||
Squad = []
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -84,7 +81,11 @@ 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(string url, MatchGroupInviteSendRequest info, string sessionID)
|
public ValueTask<string> SendGroupInvite(
|
||||||
|
string url,
|
||||||
|
MatchGroupInviteSendRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody("2427943f23698ay9f2863735"));
|
return new ValueTask<string>(_httpResponseUtil.GetBody("2427943f23698ay9f2863735"));
|
||||||
}
|
}
|
||||||
@@ -95,12 +96,7 @@ public class MatchCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> AcceptGroupInvite(string url, RequestIdRequest info, string sessionID)
|
public ValueTask<string> AcceptGroupInvite(string url, RequestIdRequest info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(
|
return new ValueTask<string>(_httpResponseUtil.GetBody(new List<GroupCharacter> { new() }));
|
||||||
new List<GroupCharacter>
|
|
||||||
{
|
|
||||||
new()
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -134,7 +130,11 @@ 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(string url, MatchGroupTransferRequest info, string sessionID)
|
public ValueTask<string> TransferGroup(
|
||||||
|
string url,
|
||||||
|
MatchGroupTransferRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,11 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/analytics/event-disconnect
|
/// Handle client/analytics/event-disconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> EventDisconnect(string url, PutMetricsRequestData info, string sessionID)
|
public ValueTask<string> EventDisconnect(
|
||||||
|
string url,
|
||||||
|
PutMetricsRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
@@ -179,9 +183,15 @@ public class MatchCallbacks(
|
|||||||
/// Handle match/group/start_game
|
/// Handle match/group/start_game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> JoinMatch(string url, MatchGroupStartGameRequest info, string sessionID)
|
public ValueTask<string> JoinMatch(
|
||||||
|
string url,
|
||||||
|
MatchGroupStartGameRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_matchController.JoinMatch(info, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_matchController.JoinMatch(info, sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -190,7 +200,9 @@ public class MatchCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetMetrics(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetMetrics(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_databaseService.GetMatch().Metrics));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_databaseService.GetMatch().Metrics)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -198,9 +210,15 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/group/status
|
/// Handle client/match/group/status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetGroupStatus(string url, MatchGroupStatusRequest info, string sessionID)
|
public ValueTask<string> GetGroupStatus(
|
||||||
|
string url,
|
||||||
|
MatchGroupStatusRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_matchController.GetGroupStatus(info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_matchController.GetGroupStatus(info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -226,7 +244,11 @@ 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(string url, MatchGroupPlayerRemoveRequest info, string sessionID)
|
public ValueTask<string> RemovePlayerFromGroup(
|
||||||
|
string url,
|
||||||
|
MatchGroupPlayerRemoveRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
return new ValueTask<string>(_httpResponseUtil.GetBody(true));
|
||||||
}
|
}
|
||||||
@@ -235,16 +257,26 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/match/local/start
|
/// Handle client/match/local/start
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> StartLocalRaid(string url, StartLocalRaidRequestData info, string sessionID)
|
public ValueTask<string> StartLocalRaid(
|
||||||
|
string url,
|
||||||
|
StartLocalRaidRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_matchController.StartLocalRaid(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, EndLocalRaidRequestData info, string sessionID)
|
public ValueTask<string> EndLocalRaid(
|
||||||
|
string url,
|
||||||
|
EndLocalRaidRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_matchController.EndLocalRaid(sessionID, info);
|
_matchController.EndLocalRaid(sessionID, info);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -254,7 +286,11 @@ public class MatchCallbacks(
|
|||||||
/// Handle client/raid/configuration
|
/// Handle client/raid/configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetRaidConfiguration(string url, GetRaidConfigurationRequestData info, string sessionID)
|
public ValueTask<string> GetRaidConfiguration(
|
||||||
|
string url,
|
||||||
|
GetRaidConfigurationRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_matchController.ConfigureOfflineRaid(info, sessionID);
|
_matchController.ConfigureOfflineRaid(info, sessionID);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -267,7 +303,11 @@ 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(string url, GetRaidConfigurationRequestData info, string sessionID)
|
public ValueTask<string> GetConfigurationByProfile(
|
||||||
|
string url,
|
||||||
|
GetRaidConfigurationRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ 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(PmcData pmcData, NoteActionRequest request, string sessionID)
|
public ItemEventRouterResponse AddNote(
|
||||||
|
PmcData pmcData,
|
||||||
|
NoteActionRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _noteController.AddNote(pmcData, request, sessionID);
|
return _noteController.AddNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -28,7 +32,11 @@ 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(PmcData pmcData, NoteActionRequest request, string sessionID)
|
public ItemEventRouterResponse EditNote(
|
||||||
|
PmcData pmcData,
|
||||||
|
NoteActionRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _noteController.EditNote(pmcData, request, sessionID);
|
return _noteController.EditNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
@@ -40,7 +48,11 @@ 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(PmcData pmcData, NoteActionRequest request, string sessionID)
|
public ItemEventRouterResponse DeleteNote(
|
||||||
|
PmcData pmcData,
|
||||||
|
NoteActionRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _noteController.DeleteNote(pmcData, request, sessionID);
|
return _noteController.DeleteNote(pmcData, request, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,12 +32,14 @@ public class NotifierCallbacks(
|
|||||||
* Take our array of JSON message objects and cast them to JSON strings, so that they can then
|
* Take our array of JSON message objects and cast them to JSON strings, so that they can then
|
||||||
* be sent to client as NEWLINE separated strings... yup.
|
* be sent to client as NEWLINE separated strings... yup.
|
||||||
*/
|
*/
|
||||||
_notifierController.NotifyAsync(tmpSessionID)
|
_notifierController
|
||||||
.ContinueWith(messages => messages.Result.Select(message => string.Join("\n", jsonUtil.Serialize(message))))
|
.NotifyAsync(tmpSessionID)
|
||||||
|
.ContinueWith(messages =>
|
||||||
|
messages.Result.Select(message => string.Join("\n", jsonUtil.Serialize(message)))
|
||||||
|
)
|
||||||
.ContinueWith(text => httpServerHelper.SendTextJson(resp, text.Result));
|
.ContinueWith(text => httpServerHelper.SendTextJson(resp, text.Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TODO: removed from client?
|
/// TODO: removed from client?
|
||||||
/// Handle push/notifier/get
|
/// Handle push/notifier/get
|
||||||
@@ -55,7 +57,9 @@ public class NotifierCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> CreateNotifierChannel(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> CreateNotifierChannel(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_notifierController.GetChannel(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_notifierController.GetChannel(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -64,12 +68,9 @@ public class NotifierCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> SelectProfile(string url, UIDRequestData info, string sessionID)
|
public ValueTask<string> SelectProfile(string url, UIDRequestData info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(
|
return new ValueTask<string>(
|
||||||
new SelectProfileResponse
|
_httpResponseUtil.GetBody(new SelectProfileResponse { Status = "ok" })
|
||||||
{
|
);
|
||||||
Status = "ok"
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ public class PrestigeCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetPrestige(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetPrestige(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_prestigeController.GetPrestige(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_prestigeController.GetPrestige(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -31,7 +33,11 @@ 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(string url, ObtainPrestigeRequestList info, string sessionID)
|
public async ValueTask<string> ObtainPrestige(
|
||||||
|
string url,
|
||||||
|
ObtainPrestigeRequestList info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
await _prestigeController.ObtainPrestige(sessionID, info);
|
await _prestigeController.ObtainPrestige(sessionID, info);
|
||||||
|
|
||||||
|
|||||||
@@ -22,15 +22,14 @@ public class ProfileCallbacks(
|
|||||||
/// Handle client/game/profile/create
|
/// Handle client/game/profile/create
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async ValueTask<string> CreateProfile(string url, ProfileCreateRequestData info, string sessionID)
|
public async ValueTask<string> CreateProfile(
|
||||||
|
string url,
|
||||||
|
ProfileCreateRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var id = await _profileController.CreateProfile(info, sessionID);
|
var id = await _profileController.CreateProfile(info, sessionID);
|
||||||
return _httpResponse.GetBody(
|
return _httpResponse.GetBody(new CreateProfileResponse { UserId = id });
|
||||||
new CreateProfileResponse
|
|
||||||
{
|
|
||||||
UserId = id
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,7 +39,9 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetProfileData(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetProfileData(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(_profileController.GetCompleteProfile(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponse.GetBody(_profileController.GetCompleteProfile(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,19 +52,22 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> RegenerateScav(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> RegenerateScav(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(
|
return new ValueTask<string>(
|
||||||
new List<PmcData>
|
_httpResponse.GetBody(
|
||||||
{
|
new List<PmcData> { _profileController.GeneratePlayerScav(sessionID) }
|
||||||
_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(string url, ProfileChangeVoiceRequestData info, string sessionID)
|
public ValueTask<string> ChangeVoice(
|
||||||
|
string url,
|
||||||
|
ProfileChangeVoiceRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_profileController.ChangeVoice(info, sessionID);
|
_profileController.ChangeVoice(info, sessionID);
|
||||||
return new ValueTask<string>(_httpResponse.NullResponse());
|
return new ValueTask<string>(_httpResponse.NullResponse());
|
||||||
@@ -74,21 +78,35 @@ 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(string url, ProfileChangeNicknameRequestData info, string sessionId)
|
public ValueTask<string> ChangeNickname(
|
||||||
|
string url,
|
||||||
|
ProfileChangeNicknameRequestData info,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _profileController.ChangeNickname(info, sessionId);
|
var output = _profileController.ChangeNickname(info, sessionId);
|
||||||
|
|
||||||
return output switch
|
return output switch
|
||||||
{
|
{
|
||||||
NicknameValidationResult.Taken => new ValueTask<string>(_httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotUnique, $"{BackendErrorCodes.NicknameNotUnique} - ")),
|
NicknameValidationResult.Taken => new ValueTask<string>(
|
||||||
NicknameValidationResult.Short => new ValueTask<string>(_httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotValid, $"{BackendErrorCodes.NicknameNotValid} - ")),
|
_httpResponse.GetBody<object?>(
|
||||||
_ => new ValueTask<string>(_httpResponse.GetBody<object>(
|
null,
|
||||||
new
|
BackendErrorCodes.NicknameNotUnique,
|
||||||
{
|
$"{BackendErrorCodes.NicknameNotUnique} - "
|
||||||
status = 0,
|
)
|
||||||
NicknameChangeDate = _timeUtil.GetTimeStamp()
|
),
|
||||||
}
|
NicknameValidationResult.Short => new ValueTask<string>(
|
||||||
))
|
_httpResponse.GetBody<object?>(
|
||||||
|
null,
|
||||||
|
BackendErrorCodes.NicknameNotValid,
|
||||||
|
$"{BackendErrorCodes.NicknameNotValid} - "
|
||||||
|
)
|
||||||
|
),
|
||||||
|
_ => new ValueTask<string>(
|
||||||
|
_httpResponse.GetBody<object>(
|
||||||
|
new { status = 0, NicknameChangeDate = _timeUtil.GetTimeStamp() }
|
||||||
|
)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,18 +114,29 @@ 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(string url, ValidateNicknameRequestData info, string sessionId)
|
public ValueTask<string> ValidateNickname(
|
||||||
|
string url,
|
||||||
|
ValidateNicknameRequestData info,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _profileController.ValidateNickname(info, sessionId) switch
|
return _profileController.ValidateNickname(info, sessionId) switch
|
||||||
{
|
{
|
||||||
NicknameValidationResult.Taken => new ValueTask<string>(_httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotUnique, $"{BackendErrorCodes.NicknameNotUnique} - ")),
|
NicknameValidationResult.Taken => new ValueTask<string>(
|
||||||
NicknameValidationResult.Short => new ValueTask<string>(_httpResponse.GetBody<object?>(null, BackendErrorCodes.NicknameNotValid, $"{BackendErrorCodes.NicknameNotValid} - ")),
|
_httpResponse.GetBody<object?>(
|
||||||
_ => new ValueTask<string>(_httpResponse.GetBody(
|
null,
|
||||||
new
|
BackendErrorCodes.NicknameNotUnique,
|
||||||
{
|
$"{BackendErrorCodes.NicknameNotUnique} - "
|
||||||
status = "ok"
|
)
|
||||||
}
|
),
|
||||||
))
|
NicknameValidationResult.Short => new ValueTask<string>(
|
||||||
|
_httpResponse.GetBody<object?>(
|
||||||
|
null,
|
||||||
|
BackendErrorCodes.NicknameNotValid,
|
||||||
|
$"{BackendErrorCodes.NicknameNotValid} - "
|
||||||
|
)
|
||||||
|
),
|
||||||
|
_ => new ValueTask<string>(_httpResponse.GetBody(new { status = "ok" })),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +163,9 @@ public class ProfileCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetProfileStatus(string url, EmptyRequestData _, string sessionId)
|
public ValueTask<string> GetProfileStatus(string url, EmptyRequestData _, string sessionId)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(_profileController.GetProfileStatus(sessionId)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponse.GetBody(_profileController.GetProfileStatus(sessionId))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -142,36 +173,60 @@ 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(string url, GetOtherProfileRequest request, string sessionID)
|
public ValueTask<string> GetOtherProfile(
|
||||||
|
string url,
|
||||||
|
GetOtherProfileRequest request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(_profileController.GetOtherProfile(sessionID, request)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GetProfileSettingsRequest info, string sessionID)
|
public ValueTask<string> GetProfileSettings(
|
||||||
|
string url,
|
||||||
|
GetProfileSettingsRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(_profileController.SetChosenProfileIcon(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, SearchProfilesRequestData info, string sessionID)
|
public ValueTask<string> SearchProfiles(
|
||||||
|
string url,
|
||||||
|
SearchProfilesRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.GetBody(_profileController.SearchProfiles(info, sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_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(string url, GetMiniProfileRequestData info, string sessionID)
|
public ValueTask<string> GetMiniProfile(
|
||||||
|
string url,
|
||||||
|
GetMiniProfileRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponse.NoBody(_profileController.GetMiniProfile(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponse.NoBody(_profileController.GetMiniProfile(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ 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(PmcData pmcData, RepeatableQuestChangeRequest info, string sessionID)
|
public ItemEventRouterResponse ChangeRepeatableQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
RepeatableQuestChangeRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _repeatableQuestController.ChangeRepeatableQuest(pmcData, info, sessionID);
|
return _repeatableQuestController.ChangeRepeatableQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -33,7 +37,11 @@ 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(PmcData pmcData, AcceptQuestRequestData info, string sessionID)
|
public ItemEventRouterResponse AcceptQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
AcceptQuestRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (info.Type == "repeatable")
|
if (info.Type == "repeatable")
|
||||||
{
|
{
|
||||||
@@ -50,7 +58,11 @@ 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(PmcData pmcData, CompleteQuestRequestData info, string sessionID)
|
public ItemEventRouterResponse CompleteQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
CompleteQuestRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _questController.CompleteQuest(pmcData, info, sessionID);
|
return _questController.CompleteQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -62,7 +74,11 @@ 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(PmcData pmcData, HandoverQuestRequestData info, string sessionID)
|
public ItemEventRouterResponse HandoverQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
HandoverQuestRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _questController.HandoverQuest(pmcData, info, sessionID);
|
return _questController.HandoverQuest(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -76,7 +92,9 @@ public class QuestCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ListQuests(string url, ListQuestsRequestData info, string sessionID)
|
public ValueTask<string> ListQuests(string url, ListQuestsRequestData info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_questController.GetClientQuests(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_questController.GetClientQuests(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -88,6 +106,10 @@ public class QuestCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> ActivityPeriods(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> ActivityPeriods(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_repeatableQuestController.GetClientRepeatableQuests(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(
|
||||||
|
_repeatableQuestController.GetClientRepeatableQuests(sessionID)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ public class RagfairCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> Search(string url, SearchRequestData info, string sessionID)
|
public ValueTask<string> Search(string url, SearchRequestData info, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_ragfairController.GetOffers(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_ragfairController.GetOffers(sessionID, info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -71,9 +73,15 @@ 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(string url, GetMarketPriceRequestData info, string sessionID)
|
public ValueTask<string> GetMarketPrice(
|
||||||
|
string url,
|
||||||
|
GetMarketPriceRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_ragfairController.GetItemMinAvgMaxFleaPriceValues(info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_ragfairController.GetItemMinAvgMaxFleaPriceValues(info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -83,7 +91,11 @@ 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(PmcData pmcData, AddOfferRequestData info, string sessionID)
|
public ItemEventRouterResponse AddOffer(
|
||||||
|
PmcData pmcData,
|
||||||
|
AddOfferRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _ragfairController.AddPlayerOffer(pmcData, info, sessionID);
|
return _ragfairController.AddPlayerOffer(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -95,7 +107,11 @@ 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(PmcData pmcData, RemoveOfferRequestData info, string sessionID)
|
public ItemEventRouterResponse RemoveOffer(
|
||||||
|
PmcData pmcData,
|
||||||
|
RemoveOfferRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _ragfairController.FlagOfferForRemoval(info.OfferId, sessionID);
|
return _ragfairController.FlagOfferForRemoval(info.OfferId, sessionID);
|
||||||
}
|
}
|
||||||
@@ -107,7 +123,11 @@ 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(PmcData pmcData, ExtendOfferRequestData info, string sessionID)
|
public ItemEventRouterResponse ExtendOffer(
|
||||||
|
PmcData pmcData,
|
||||||
|
ExtendOfferRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _ragfairController.ExtendOffer(info, sessionID);
|
return _ragfairController.ExtendOffer(info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -122,7 +142,9 @@ public class RagfairCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetFleaPrices(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetFleaPrices(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_ragfairController.GetAllFleaPrices()));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_ragfairController.GetAllFleaPrices())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -132,12 +154,20 @@ 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(string url, SendRagfairReportRequestData info, string sessionID)
|
public ValueTask<string> SendReport(
|
||||||
|
string url,
|
||||||
|
SendRagfairReportRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<string> StorePlayerOfferTaxAmount(string url, StorePlayerOfferTaxAmountRequestData info, string sessionID)
|
public ValueTask<string> StorePlayerOfferTaxAmount(
|
||||||
|
string url,
|
||||||
|
StorePlayerOfferTaxAmountRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_ragfairTaxService.StoreClientOfferTaxValue(sessionID, info);
|
_ragfairTaxService.StoreClientOfferTaxValue(sessionID, info);
|
||||||
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
return new ValueTask<string>(_httpResponseUtil.NullResponse());
|
||||||
@@ -150,8 +180,14 @@ 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(string url, GetRagfairOfferByIdRequest info, string sessionID)
|
public ValueTask<string> GetFleaOfferById(
|
||||||
|
string url,
|
||||||
|
GetRagfairOfferByIdRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_ragfairController.GetOfferByInternalId(sessionID, info)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_ragfairController.GetOfferByInternalId(sessionID, info))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ 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(PmcData pmcData, TraderRepairActionDataRequest info, string sessionID)
|
public ItemEventRouterResponse TraderRepair(
|
||||||
|
PmcData pmcData,
|
||||||
|
TraderRepairActionDataRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _repairController.TraderRepair(sessionID, info, pmcData);
|
return _repairController.TraderRepair(sessionID, info, pmcData);
|
||||||
}
|
}
|
||||||
@@ -30,7 +34,11 @@ 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(PmcData pmcData, RepairActionDataRequest info, string sessionID)
|
public ItemEventRouterResponse Repair(
|
||||||
|
PmcData pmcData,
|
||||||
|
RepairActionDataRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _repairController.RepairWithKit(sessionID, info, pmcData);
|
return _repairController.RepairWithKit(sessionID, info, pmcData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ public class SaveCallbacks(
|
|||||||
SaveServer _saveServer,
|
SaveServer _saveServer,
|
||||||
ConfigServer _configServer,
|
ConfigServer _configServer,
|
||||||
BackupService _backupService
|
BackupService _backupService
|
||||||
)
|
) : IOnLoad, IOnUpdate
|
||||||
: IOnLoad, IOnUpdate
|
|
||||||
{
|
{
|
||||||
private readonly CoreConfig _coreConfig = _configServer.GetConfig<CoreConfig>();
|
private readonly CoreConfig _coreConfig = _configServer.GetConfig<CoreConfig>();
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ 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(PmcData pmcData, ProcessBaseTradeRequestData info, string sessionID)
|
public ItemEventRouterResponse ProcessTrade(
|
||||||
|
PmcData pmcData,
|
||||||
|
ProcessBaseTradeRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _tradeController.ConfirmTrading(pmcData, info, sessionID);
|
return _tradeController.ConfirmTrading(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -28,7 +32,11 @@ 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(PmcData pmcData, ProcessRagfairTradeRequestData info, string sessionID)
|
public ItemEventRouterResponse ProcessRagfairTrade(
|
||||||
|
PmcData pmcData,
|
||||||
|
ProcessRagfairTradeRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _tradeController.ConfirmRagfairTrading(pmcData, info, sessionID);
|
return _tradeController.ConfirmRagfairTrading(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -40,7 +48,11 @@ 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(PmcData pmcData, SellScavItemsToFenceRequestData info, string sessionID)
|
public ItemEventRouterResponse SellAllFromSavage(
|
||||||
|
PmcData pmcData,
|
||||||
|
SellScavItemsToFenceRequestData info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _tradeController.SellScavItemsToFence(pmcData, info, sessionID);
|
return _tradeController.SellScavItemsToFence(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ public class TraderCallbacks(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ValueTask<string> GetTraderSettings(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTraderSettings(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_traderController.GetAllTraders(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_traderController.GetAllTraders(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,7 +46,9 @@ public class TraderCallbacks(
|
|||||||
public ValueTask<string> GetTrader(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetTrader(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
var traderID = url.Replace("/client/trading/api/getTrader/", "");
|
var traderID = url.Replace("/client/trading/api/getTrader/", "");
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_traderController.GetTrader(sessionID, traderID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_traderController.GetTrader(sessionID, traderID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -54,7 +58,9 @@ public class TraderCallbacks(
|
|||||||
public ValueTask<string> GetAssort(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetAssort(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
var traderID = url.Replace("/client/trading/api/getTraderAssort/", "");
|
var traderID = url.Replace("/client/trading/api/getTraderAssort/", "");
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_traderController.GetAssort(sessionID, traderID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_traderController.GetAssort(sessionID, traderID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public class WeatherCallbacks(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask<string> GetLocalWeather(string url, EmptyRequestData _, string sessionID)
|
public ValueTask<string> GetLocalWeather(string url, EmptyRequestData _, string sessionID)
|
||||||
{
|
{
|
||||||
return new ValueTask<string>(_httpResponseUtil.GetBody(_weatherController.GenerateLocal(sessionID)));
|
return new ValueTask<string>(
|
||||||
|
_httpResponseUtil.GetBody(_weatherController.GenerateLocal(sessionID))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,11 @@ 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(PmcData pmcData, AddToWishlistRequest info, string sessionID)
|
public ItemEventRouterResponse AddToWishlist(
|
||||||
|
PmcData pmcData,
|
||||||
|
AddToWishlistRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _wishlistController.AddToWishList(pmcData, info, sessionID);
|
return _wishlistController.AddToWishList(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -28,7 +32,11 @@ 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(PmcData pmcData, RemoveFromWishlistRequest info, string sessionID)
|
public ItemEventRouterResponse RemoveFromWishlist(
|
||||||
|
PmcData pmcData,
|
||||||
|
RemoveFromWishlistRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _wishlistController.RemoveFromWishList(pmcData, info, sessionID);
|
return _wishlistController.RemoveFromWishList(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
@@ -40,7 +48,11 @@ 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(PmcData pmcData, ChangeWishlistItemCategoryRequest info, string sessionID)
|
public ItemEventRouterResponse ChangeWishlistItemCategory(
|
||||||
|
PmcData pmcData,
|
||||||
|
ChangeWishlistItemCategoryRequest info,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _wishlistController.ChangeWishListItemCategory(pmcData, info, sessionID);
|
return _wishlistController.ChangeWishListItemCategory(pmcData, info, sessionID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,7 @@ public class AchievementController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public virtual GetAchievementsResponse GetAchievements(string sessionID)
|
public virtual GetAchievementsResponse GetAchievements(string sessionID)
|
||||||
{
|
{
|
||||||
return new GetAchievementsResponse
|
return new GetAchievementsResponse { Elements = databaseService.GetAchievements() };
|
||||||
{
|
|
||||||
Elements = databaseService.GetAchievements()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,12 +34,21 @@ public class AchievementController(
|
|||||||
public virtual CompletedAchievementsResponse GetAchievementStatics(string sessionId)
|
public virtual CompletedAchievementsResponse GetAchievementStatics(string sessionId)
|
||||||
{
|
{
|
||||||
var stats = new Dictionary<string, int>();
|
var stats = new Dictionary<string, int>();
|
||||||
var profiles = profileHelper.GetProfiles()
|
var profiles = profileHelper
|
||||||
.Where(kvp => !coreConfig.Features.AchievementProfileIdBlacklist.Contains(kvp.Value.ProfileInfo.ProfileId))
|
.GetProfiles()
|
||||||
|
.Where(kvp =>
|
||||||
|
!coreConfig.Features.AchievementProfileIdBlacklist.Contains(
|
||||||
|
kvp.Value.ProfileInfo.ProfileId
|
||||||
|
)
|
||||||
|
)
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
|
|
||||||
var achievements = databaseService.GetAchievements();
|
var achievements = databaseService.GetAchievements();
|
||||||
foreach (var achievementId in achievements.Select(achievement => achievement.Id).Where(achievementId => !string.IsNullOrEmpty(achievementId)))
|
foreach (
|
||||||
|
var achievementId in achievements
|
||||||
|
.Select(achievement => achievement.Id)
|
||||||
|
.Where(achievementId => !string.IsNullOrEmpty(achievementId))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var profilesHaveAchievement = 0;
|
var profilesHaveAchievement = 0;
|
||||||
foreach (var (profileId, profile) in profiles)
|
foreach (var (profileId, profile) in profiles)
|
||||||
@@ -63,15 +69,13 @@ public class AchievementController(
|
|||||||
var percentage = 0;
|
var percentage = 0;
|
||||||
if (profiles.Count > 0)
|
if (profiles.Count > 0)
|
||||||
{
|
{
|
||||||
percentage = (int)Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
|
percentage = (int)
|
||||||
|
Math.Round((double)profilesHaveAchievement / profiles.Count * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.Add(achievementId, percentage);
|
stats.Add(achievementId, percentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CompletedAchievementsResponse
|
return new CompletedAchievementsResponse { Elements = stats };
|
||||||
{
|
|
||||||
Elements = stats
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using SPTarkov.Server.Core.Constants;
|
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Constants;
|
||||||
using SPTarkov.Server.Core.Generators;
|
using SPTarkov.Server.Core.Generators;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Common;
|
using SPTarkov.Server.Core.Models.Common;
|
||||||
@@ -50,7 +50,9 @@ public class BotController(
|
|||||||
{
|
{
|
||||||
if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
|
if (!_botConfig.PresetBatch.TryGetValue(type, out var limit))
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("bot-bot_preset_count_value_missing", type));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("bot-bot_preset_count_value_missing", type)
|
||||||
|
);
|
||||||
|
|
||||||
return 10;
|
return 10;
|
||||||
}
|
}
|
||||||
@@ -78,23 +80,38 @@ public class BotController(
|
|||||||
/// <param name="raidConfig">OPTIONAL - applicationContext Data stored at start of raid</param>
|
/// <param name="raidConfig">OPTIONAL - applicationContext Data stored at start of raid</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(string sessionId, string type, string diffLevel, bool ignoreRaidSettings = false)
|
public DifficultyCategories GetBotDifficulty(
|
||||||
|
string sessionId,
|
||||||
|
string type,
|
||||||
|
string diffLevel,
|
||||||
|
bool ignoreRaidSettings = false
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var difficulty = diffLevel.ToLower();
|
var difficulty = diffLevel.ToLower();
|
||||||
|
|
||||||
var raidConfig = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
|
var raidConfig = _profileActivityService
|
||||||
|
.GetProfileActivityRaidData(sessionId)
|
||||||
|
?.RaidConfiguration;
|
||||||
|
|
||||||
if (!(raidConfig != null || ignoreRaidSettings))
|
if (!(raidConfig != null || ignoreRaidSettings))
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("bot-missing_application_context", "RAID_CONFIGURATION"));
|
_logger.Error(
|
||||||
|
_localisationService.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 = raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLower() ?? "asonline";
|
var botDifficultyDropDownValue =
|
||||||
|
raidConfig?.WavesSettings?.BotDifficulty?.ToString().ToLower() ?? "asonline";
|
||||||
if (botDifficultyDropDownValue != "asonline")
|
if (botDifficultyDropDownValue != "asonline")
|
||||||
{
|
{
|
||||||
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(botDifficultyDropDownValue);
|
difficulty = _botDifficultyHelper.ConvertBotDifficultyDropdownToBotDifficulty(
|
||||||
|
botDifficultyDropDownValue
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var botDb = _databaseService.GetBots();
|
var botDb = _databaseService.GetBots();
|
||||||
@@ -130,7 +147,9 @@ 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($"Unable to find bot: {botTypeLower} in db, copying '{Roles.Assault}'");
|
_logger.Debug(
|
||||||
|
$"Unable to find bot: {botTypeLower} in db, copying '{Roles.Assault}'"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -139,7 +158,9 @@ 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($"Unable to find bot: {botTypeLower} difficulty values in db, skipping");
|
_logger.Warning(
|
||||||
|
$"Unable to find bot: {botTypeLower} difficulty values in db, skipping"
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +174,11 @@ public class BotController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/impossible
|
// Store all difficulty values in dict keyed by difficulty type e.g. easy/normal/impossible
|
||||||
result[botNameKey].Add(difficultyName, GetBotDifficulty(string.Empty, botNameKey, difficultyName, true));
|
result[botNameKey]
|
||||||
|
.Add(
|
||||||
|
difficultyName,
|
||||||
|
GetBotDifficulty(string.Empty, botNameKey, difficultyName, true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +205,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(GenerateBotsRequestData request, PmcData? pmcProfile, string sessionId)
|
protected List<BotBase> GenerateBotWaves(
|
||||||
|
GenerateBotsRequestData request,
|
||||||
|
PmcData? pmcProfile,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var generatedBotList = new List<BotBase>();
|
var generatedBotList = new List<BotBase>();
|
||||||
var raidSettings = GetMostRecentRaidSettings(sessionId);
|
var raidSettings = GetMostRecentRaidSettings(sessionId);
|
||||||
@@ -191,23 +220,36 @@ public class BotController(
|
|||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
// Map conditions to promises for bot generation
|
// Map conditions to promises for bot generation
|
||||||
|
|
||||||
Task.WaitAll((request.Conditions ?? [])
|
Task.WaitAll(
|
||||||
.Select(condition => Task.Factory.StartNew(() =>
|
(request.Conditions ?? [])
|
||||||
|
.Select(condition =>
|
||||||
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
var botWaveGenerationDetails = GetBotGenerationDetailsForWave(
|
var botWaveGenerationDetails = GetBotGenerationDetailsForWave(
|
||||||
condition,
|
condition,
|
||||||
pmcProfile,
|
pmcProfile,
|
||||||
allPmcsHaveSameNameAsPlayer,
|
allPmcsHaveSameNameAsPlayer,
|
||||||
raidSettings);
|
raidSettings
|
||||||
|
);
|
||||||
|
|
||||||
GenerateBotWave(condition, botWaveGenerationDetails, generatedBotList, sessionId);
|
GenerateBotWave(
|
||||||
})).ToArray());
|
condition,
|
||||||
|
botWaveGenerationDetails,
|
||||||
|
generatedBotList,
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.ToArray()
|
||||||
|
);
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()");
|
_logger.Debug(
|
||||||
|
$"Took {stopwatch.ElapsedMilliseconds}ms to GenerateMultipleBotsAndCache()"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return generatedBotList;
|
return generatedBotList;
|
||||||
@@ -225,9 +267,13 @@ public class BotController(
|
|||||||
GenerateCondition generateRequest,
|
GenerateCondition generateRequest,
|
||||||
BotGenerationDetails botGenerationDetails,
|
BotGenerationDetails botGenerationDetails,
|
||||||
List<BotBase> botList,
|
List<BotBase> botList,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var isEventBot = generateRequest.Role?.Contains("event", StringComparison.OrdinalIgnoreCase);
|
var isEventBot = generateRequest.Role?.Contains(
|
||||||
|
"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
|
||||||
@@ -241,21 +287,30 @@ public class BotController(
|
|||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}");
|
_logger.Debug(
|
||||||
|
$"Generating wave of: {botGenerationDetails.BotCountToGenerate} bots of type: {role} {botGenerationDetails.BotDifficulty}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parallel.For(0, botGenerationDetails.BotCountToGenerate.Value, (i) =>
|
Parallel.For(
|
||||||
|
0,
|
||||||
|
botGenerationDetails.BotCountToGenerate.Value,
|
||||||
|
(i) =>
|
||||||
{
|
{
|
||||||
BotBase bot = null;
|
BotBase bot = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bot = _botGenerator.PrepareAndGenerateBot(sessionId, _cloner.Clone(botGenerationDetails));
|
bot = _botGenerator.PrepareAndGenerateBot(
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,13 +328,14 @@ public class BotController(
|
|||||||
|
|
||||||
// Store bot details in cache so post-raid PMC messages can use data
|
// Store bot details in cache so post-raid PMC messages can use data
|
||||||
_matchBotDetailsCacheService.CacheBot(bot);
|
_matchBotDetailsCacheService.CacheBot(bot);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
$"Generated: {botGenerationDetails.BotCountToGenerate} {botGenerationDetails.Role}" +
|
$"Generated: {botGenerationDetails.BotCountToGenerate} {botGenerationDetails.Role}"
|
||||||
$"({botGenerationDetails.EventRole ?? botGenerationDetails.Role ?? ""}) {botGenerationDetails.BotDifficulty} bots"
|
+ $"({botGenerationDetails.EventRole ?? botGenerationDetails.Role ?? ""}) {botGenerationDetails.BotDifficulty} bots"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,11 +346,15 @@ public class BotController(
|
|||||||
/// <returns>GetRaidConfigurationRequestData if it exists</returns>
|
/// <returns>GetRaidConfigurationRequestData if it exists</returns>
|
||||||
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(string sessionId)
|
protected GetRaidConfigurationRequestData? GetMostRecentRaidSettings(string sessionId)
|
||||||
{
|
{
|
||||||
var raidConfiguration = _profileActivityService.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
|
var raidConfiguration = _profileActivityService
|
||||||
|
.GetProfileActivityRaidData(sessionId)
|
||||||
|
?.RaidConfiguration;
|
||||||
|
|
||||||
if (raidConfiguration is null)
|
if (raidConfiguration is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext"));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("bot-unable_to_load_raid_settings_from_appcontext")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return raidConfiguration;
|
return raidConfiguration;
|
||||||
@@ -307,7 +367,10 @@ 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(location?.ToLower() ?? "", null);
|
return _pmcConfig.LocationSpecificPmcLevelOverride!.GetValueOrDefault(
|
||||||
|
location?.ToLower() ?? "",
|
||||||
|
null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -322,24 +385,30 @@ public class BotController(
|
|||||||
GenerateCondition condition,
|
GenerateCondition condition,
|
||||||
PmcData? pmcProfile,
|
PmcData? pmcProfile,
|
||||||
bool allPmcsHaveSameNameAsPlayer,
|
bool allPmcsHaveSameNameAsPlayer,
|
||||||
GetRaidConfigurationRequestData? raidSettings)
|
GetRaidConfigurationRequestData? raidSettings
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var generateAsPmc = _botHelper.IsBotPmc(condition.Role);
|
var generateAsPmc = _botHelper.IsBotPmc(condition.Role);
|
||||||
|
|
||||||
return new BotGenerationDetails
|
return new BotGenerationDetails
|
||||||
{
|
{
|
||||||
IsPmc = generateAsPmc,
|
IsPmc = generateAsPmc,
|
||||||
Side = generateAsPmc ? _botHelper.GetPmcSideByRole(condition.Role ?? string.Empty) : "Savage",
|
Side = generateAsPmc
|
||||||
|
? _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(GetBotPresetGenerationLimit(condition.Role), condition.Limit), // Choose largest between value passed in from request vs what's in bot.config
|
BotCountToGenerate = Math.Max(
|
||||||
|
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,
|
||||||
AllPmcsHaveSameNameAsPlayer = allPmcsHaveSameNameAsPlayer
|
AllPmcsHaveSameNameAsPlayer = allPmcsHaveSameNameAsPlayer,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +428,10 @@ public class BotController(
|
|||||||
if (location == "default")
|
if (location == "default")
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("bot-no_bot_cap_found_for_location", location.ToLower())
|
_localisationService.GetText(
|
||||||
|
"bot-no_bot_cap_found_for_location",
|
||||||
|
location.ToLower()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,7 +448,7 @@ public class BotController(
|
|||||||
{
|
{
|
||||||
PmcType = _pmcConfig.PmcType,
|
PmcType = _pmcConfig.PmcType,
|
||||||
Assault = _botConfig.AssaultBrainType,
|
Assault = _botConfig.AssaultBrainType,
|
||||||
PlayerScav = _botConfig.PlayerScavBrainType
|
PlayerScav = _botConfig.PlayerScavBrainType,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,23 +456,11 @@ public class BotController(
|
|||||||
public record AiBotBrainTypes
|
public record AiBotBrainTypes
|
||||||
{
|
{
|
||||||
[JsonPropertyName("pmc")]
|
[JsonPropertyName("pmc")]
|
||||||
public Dictionary<string, Dictionary<string, Dictionary<string, double>>> PmcType
|
public Dictionary<string, Dictionary<string, Dictionary<string, double>>> PmcType { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("assault")]
|
[JsonPropertyName("assault")]
|
||||||
public Dictionary<string, Dictionary<string, int>> Assault
|
public Dictionary<string, Dictionary<string, int>> Assault { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("playerScav")]
|
[JsonPropertyName("playerScav")]
|
||||||
public Dictionary<string, Dictionary<string, int>> PlayerScav
|
public Dictionary<string, Dictionary<string, int>> PlayerScav { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,30 +42,37 @@ public class BuildController(
|
|||||||
{
|
{
|
||||||
EquipmentBuilds = [],
|
EquipmentBuilds = [],
|
||||||
WeaponBuilds = [],
|
WeaponBuilds = [],
|
||||||
MagazineBuilds = []
|
MagazineBuilds = [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.Clone(_databaseService.GetTemplates().DefaultEquipmentPresets)
|
var defaultEquipmentPresetsClone = _cloner
|
||||||
|
.Clone(_databaseService.GetTemplates().DefaultEquipmentPresets)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Get players secure container
|
// Get players secure container
|
||||||
var playerSecureContainer = profile?.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId
|
var playerSecureContainer =
|
||||||
|
profile?.CharacterData?.PmcData?.Inventory?.Items?.FirstOrDefault(x =>
|
||||||
|
x.SlotId == secureContainerSlotId
|
||||||
);
|
);
|
||||||
|
|
||||||
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone?
|
var firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone
|
||||||
.FirstOrDefault()
|
?.FirstOrDefault()
|
||||||
?.Items?
|
?.Items?.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
|
||||||
.FirstOrDefault(x => x.SlotId == secureContainerSlotId);
|
|
||||||
|
|
||||||
if (playerSecureContainer is not null && playerSecureContainer.Template != firstDefaultItemsSecureContainer?.Template)
|
if (
|
||||||
|
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 => item.SlotId == secureContainerSlotId);
|
var secureContainer = defaultPreset.Items?.FirstOrDefault(item =>
|
||||||
|
item.SlotId == secureContainerSlotId
|
||||||
|
);
|
||||||
if (secureContainer is not null)
|
if (secureContainer is not null)
|
||||||
{
|
{
|
||||||
secureContainer.Template = playerSecureContainer.Template;
|
secureContainer.Template = playerSecureContainer.Template;
|
||||||
@@ -102,7 +109,7 @@ public class BuildController(
|
|||||||
Id = body.Id,
|
Id = body.Id,
|
||||||
Name = body.Name,
|
Name = body.Name,
|
||||||
Root = body.Root,
|
Root = body.Root,
|
||||||
Items = body.Items
|
Items = body.Items,
|
||||||
};
|
};
|
||||||
|
|
||||||
var profile = _profileHelper.GetFullProfile(sessionId);
|
var profile = _profileHelper.GetFullProfile(sessionId);
|
||||||
@@ -132,8 +139,9 @@ 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 =
|
var existingSavedEquipmentBuilds = _saveServer
|
||||||
_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.
|
||||||
@@ -145,10 +153,11 @@ public class BuildController(
|
|||||||
Name = request.Name,
|
Name = request.Name,
|
||||||
BuildType = EquipmentBuildType.Custom,
|
BuildType = EquipmentBuildType.Custom,
|
||||||
Root = request.Items[0].Id,
|
Root = request.Items[0].Id,
|
||||||
Items = request.Items
|
Items = request.Items,
|
||||||
};
|
};
|
||||||
|
|
||||||
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build => build.Name == request.Name || build.Id == request.Id
|
var existingBuild = existingSavedEquipmentBuilds?.FirstOrDefault(build =>
|
||||||
|
build.Name == request.Name || build.Id == request.Id
|
||||||
);
|
);
|
||||||
if (existingBuild is not null)
|
if (existingBuild is not null)
|
||||||
{
|
{
|
||||||
@@ -190,7 +199,7 @@ public class BuildController(
|
|||||||
Caliber = request.Caliber,
|
Caliber = request.Caliber,
|
||||||
TopCount = request.TopCount,
|
TopCount = request.TopCount,
|
||||||
BottomCount = request.BottomCount,
|
BottomCount = request.BottomCount,
|
||||||
Items = request.Items
|
Items = request.Items,
|
||||||
};
|
};
|
||||||
|
|
||||||
var profile = _profileHelper.GetFullProfile(sessionId);
|
var profile = _profileHelper.GetFullProfile(sessionId);
|
||||||
@@ -198,7 +207,9 @@ 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 => item.Name == request.Name);
|
var magazineBuildToRemove = profile.UserBuildData.MagazineBuilds.FirstOrDefault(item =>
|
||||||
|
item.Name == request.Name
|
||||||
|
);
|
||||||
if (magazineBuildToRemove is not null)
|
if (magazineBuildToRemove is not null)
|
||||||
{
|
{
|
||||||
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
|
profile.UserBuildData.MagazineBuilds.Remove(magazineBuildToRemove);
|
||||||
@@ -222,7 +233,9 @@ 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 => weaponBuild.Id == idToRemove);
|
var matchingWeaponBuild = weaponBuilds.FirstOrDefault(weaponBuild =>
|
||||||
|
weaponBuild.Id == idToRemove
|
||||||
|
);
|
||||||
if (matchingWeaponBuild is not null)
|
if (matchingWeaponBuild is not null)
|
||||||
{
|
{
|
||||||
weaponBuilds.Remove(matchingWeaponBuild);
|
weaponBuilds.Remove(matchingWeaponBuild);
|
||||||
@@ -231,7 +244,9 @@ public class BuildController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Id not found in weapons, try equipment
|
// Id not found in weapons, try equipment
|
||||||
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild => equipmentBuild.Id == idToRemove);
|
var matchingEquipmentBuild = equipmentBuilds.FirstOrDefault(equipmentBuild =>
|
||||||
|
equipmentBuild.Id == idToRemove
|
||||||
|
);
|
||||||
if (matchingEquipmentBuild is not null)
|
if (matchingEquipmentBuild is not null)
|
||||||
{
|
{
|
||||||
equipmentBuilds.Remove(matchingEquipmentBuild);
|
equipmentBuilds.Remove(matchingEquipmentBuild);
|
||||||
@@ -240,7 +255,9 @@ public class BuildController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Id not found in weapons/equipment, try mags
|
// Id not found in weapons/equipment, try mags
|
||||||
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild => magBuild.Id == idToRemove);
|
var matchingMagazineBuild = magazineBuilds.FirstOrDefault(magBuild =>
|
||||||
|
magBuild.Id == idToRemove
|
||||||
|
);
|
||||||
if (matchingMagazineBuild is not null)
|
if (matchingMagazineBuild is not null)
|
||||||
{
|
{
|
||||||
magazineBuilds.Remove(matchingMagazineBuild);
|
magazineBuilds.Remove(matchingMagazineBuild);
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class ClientLogController(
|
public class ClientLogController(ISptLogger<ClientLogController> _logger)
|
||||||
ISptLogger<ClientLogController> _logger
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle /singleplayer/log
|
/// Handle /singleplayer/log
|
||||||
|
|||||||
@@ -44,16 +44,18 @@ public class CustomizationController(
|
|||||||
var suits = _databaseService.GetTrader(traderId).Suits;
|
var suits = _databaseService.GetTrader(traderId).Suits;
|
||||||
|
|
||||||
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId!)).ToList();
|
var matchingSuits = suits?.Where(s => clothing.ContainsKey(s.SuiteId!)).ToList();
|
||||||
matchingSuits = matchingSuits?.Where(s => clothing[s.SuiteId ?? string.Empty]
|
matchingSuits = matchingSuits
|
||||||
?.Properties?.Side?
|
?.Where(s =>
|
||||||
.Contains(pmcData?.Info?.Side ?? string.Empty) ??
|
clothing[s.SuiteId ?? string.Empty]
|
||||||
false
|
?.Properties?.Side?.Contains(pmcData?.Info?.Side ?? string.Empty) ?? false
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (matchingSuits == null)
|
if (matchingSuits == null)
|
||||||
{
|
{
|
||||||
throw new Exception(_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId));
|
throw new Exception(
|
||||||
|
_localisationService.GetText("customisation-unable_to_get_trader_suits", traderId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchingSuits;
|
return matchingSuits;
|
||||||
@@ -70,7 +72,8 @@ public class CustomizationController(
|
|||||||
public ItemEventRouterResponse BuyCustomisation(
|
public ItemEventRouterResponse BuyCustomisation(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
BuyClothingRequestData buyClothingRequest,
|
BuyClothingRequestData buyClothingRequest,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionId);
|
var output = _eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -78,7 +81,10 @@ public class CustomizationController(
|
|||||||
if (traderOffer is null)
|
if (traderOffer is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("customisation-unable_to_find_suit_by_id", buyClothingRequest.Offer)
|
_localisationService.GetText(
|
||||||
|
"customisation-unable_to_find_suit_by_id",
|
||||||
|
buyClothingRequest.Offer
|
||||||
|
)
|
||||||
);
|
);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -90,11 +96,7 @@ public class CustomizationController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"customisation-item_already_purchased",
|
"customisation-item_already_purchased",
|
||||||
new
|
new { itemId = suitDetails?.Id, itemName = suitDetails?.Name }
|
||||||
{
|
|
||||||
itemId = suitDetails?.Id,
|
|
||||||
itemName = suitDetails?.Name
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -111,7 +113,7 @@ public class CustomizationController(
|
|||||||
{
|
{
|
||||||
Id = suitId,
|
Id = suitId,
|
||||||
Source = CustomisationSource.UNLOCKED_IN_GAME,
|
Source = CustomisationSource.UNLOCKED_IN_GAME,
|
||||||
Type = CustomisationType.SUITE
|
Type = CustomisationType.SUITE,
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.CustomisationUnlocks.Add(rewardToStore);
|
profile.CustomisationUnlocks.Add(rewardToStore);
|
||||||
@@ -130,7 +132,9 @@ 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 => Equals(customisation.Id, suitId));
|
return fullProfile.CustomisationUnlocks.Exists(customisation =>
|
||||||
|
Equals(customisation.Id, suitId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -144,7 +148,9 @@ 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(_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("customisation-unable_to_find_suit_with_id", offerId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundSuit;
|
return foundSuit;
|
||||||
@@ -157,9 +163,12 @@ public class CustomizationController(
|
|||||||
/// <param name="pmcData">Player profile</param>
|
/// <param name="pmcData">Player profile</param>
|
||||||
/// <param name="itemsToPayForClothingWith">Clothing purchased</param>
|
/// <param name="itemsToPayForClothingWith">Clothing purchased</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
protected void PayForClothingItems(string sessionId, PmcData pmcData,
|
protected void PayForClothingItems(
|
||||||
|
string sessionId,
|
||||||
|
PmcData pmcData,
|
||||||
List<PaymentItemForClothing>? itemsToPayForClothingWith,
|
List<PaymentItemForClothing>? itemsToPayForClothingWith,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (itemsToPayForClothingWith is null || itemsToPayForClothingWith.Count == 0)
|
if (itemsToPayForClothingWith is null || itemsToPayForClothingWith.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -175,15 +184,15 @@ public class CustomizationController(
|
|||||||
new IdWithCount
|
new IdWithCount
|
||||||
{
|
{
|
||||||
Count = inventoryItemToProcess.Count.Value,
|
Count = inventoryItemToProcess.Count.Value,
|
||||||
Id = inventoryItemToProcess.Id
|
Id = inventoryItemToProcess.Id,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
TransactionId = Traders.RAGMAN,
|
TransactionId = Traders.RAGMAN,
|
||||||
Action = "BuyCustomization",
|
Action = "BuyCustomization",
|
||||||
Type = "",
|
Type = "",
|
||||||
ItemId = "",
|
ItemId = "",
|
||||||
Count = 0,
|
Count = 0,
|
||||||
SchemeId = 0
|
SchemeId = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
_paymentService.PayMoney(pmcData, options, sessionId, output);
|
_paymentService.PayMoney(pmcData, options, sessionId, output);
|
||||||
@@ -202,7 +211,10 @@ public class CustomizationController(
|
|||||||
|
|
||||||
foreach (var trader in traders)
|
foreach (var trader in traders)
|
||||||
{
|
{
|
||||||
if (trader.Value.Base?.CustomizationSeller is not null && trader.Value.Base.CustomizationSeller.Value)
|
if (
|
||||||
|
trader.Value.Base?.CustomizationSeller is not null
|
||||||
|
&& trader.Value.Base.CustomizationSeller.Value
|
||||||
|
)
|
||||||
{
|
{
|
||||||
result.AddRange(GetTraderSuits(trader.Key, sessionId));
|
result.AddRange(GetTraderSuits(trader.Key, sessionId));
|
||||||
}
|
}
|
||||||
@@ -226,10 +238,11 @@ public class CustomizationController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<CustomisationStorage> GetCustomisationStorage(
|
public List<CustomisationStorage> GetCustomisationStorage(string sessionId)
|
||||||
string sessionId)
|
|
||||||
{
|
{
|
||||||
var customisationResultsClone = _cloner.Clone(_databaseService.GetTemplates().CustomisationStorage);
|
var customisationResultsClone = _cloner.Clone(
|
||||||
|
_databaseService.GetTemplates().CustomisationStorage
|
||||||
|
);
|
||||||
|
|
||||||
var profile = _profileHelper.GetFullProfile(sessionId);
|
var profile = _profileHelper.GetFullProfile(sessionId);
|
||||||
if (profile is null)
|
if (profile is null)
|
||||||
@@ -249,7 +262,11 @@ 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></returns>
|
/// <returns></returns>
|
||||||
public ItemEventRouterResponse SetCustomisation(string sessionId, CustomizationSetRequest request, PmcData pmcData)
|
public ItemEventRouterResponse SetCustomisation(
|
||||||
|
string sessionId,
|
||||||
|
CustomizationSetRequest request,
|
||||||
|
PmcData pmcData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var customisation in request.Customizations)
|
foreach (var customisation in request.Customizations)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -37,13 +37,17 @@ 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(_localisationService.GetText("dialog-chatbot_id_already_exists", chatBot.GetChatBot().Id));
|
_logger.Error(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"dialog-chatbot_id_already_exists",
|
||||||
|
chatBot.GetChatBot().Id
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dialogueChatBots.Add(chatBot);
|
_dialogueChatBots.Add(chatBot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle onUpdate spt event
|
/// Handle onUpdate spt event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -80,7 +84,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Id = friendProfile.Id,
|
Id = friendProfile.Id,
|
||||||
Aid = friendProfile.Aid,
|
Aid = friendProfile.Aid,
|
||||||
Info = friendProfile.Info
|
Info = friendProfile.Info,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -91,7 +95,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Friends = friends,
|
Friends = friends,
|
||||||
Ignore = [],
|
Ignore = [],
|
||||||
InIgnoreList = []
|
InIgnoreList = [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,9 +148,7 @@ public class DialogueController(
|
|||||||
/// <param name="dialogueId">Dialog id</param>
|
/// <param name="dialogueId">Dialog id</param>
|
||||||
/// <param name="sessionId">Session Id</param>
|
/// <param name="sessionId">Session Id</param>
|
||||||
/// <returns>DialogueInfo</returns>
|
/// <returns>DialogueInfo</returns>
|
||||||
public virtual DialogueInfo? GetDialogueInfo(
|
public virtual DialogueInfo? GetDialogueInfo(string? dialogueId, string sessionId)
|
||||||
string? dialogueId,
|
|
||||||
string sessionId)
|
|
||||||
{
|
{
|
||||||
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
|
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
|
||||||
var dialogue = dialogs!.GetValueOrDefault(dialogueId);
|
var dialogue = dialogs!.GetValueOrDefault(dialogueId);
|
||||||
@@ -164,7 +166,7 @@ public class DialogueController(
|
|||||||
New = dialogue?.New,
|
New = dialogue?.New,
|
||||||
AttachmentsNew = dialogue?.AttachmentsNew,
|
AttachmentsNew = dialogue?.AttachmentsNew,
|
||||||
Pinned = dialogue?.Pinned,
|
Pinned = dialogue?.Pinned,
|
||||||
Users = GetDialogueUsers(dialogue, dialogue?.Type, sessionId)
|
Users = GetDialogueUsers(dialogue, dialogue?.Type, sessionId),
|
||||||
};
|
};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -180,14 +182,19 @@ public class DialogueController(
|
|||||||
public virtual List<UserDialogInfo> GetDialogueUsers(
|
public virtual List<UserDialogInfo> GetDialogueUsers(
|
||||||
Dialogue? dialog,
|
Dialogue? dialog,
|
||||||
MessageType? messageType,
|
MessageType? messageType,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var profile = _saveServer.GetProfile(sessionId);
|
var profile = _saveServer.GetProfile(sessionId);
|
||||||
|
|
||||||
// User to user messages are special in that they need the player to exist in them, add if they don't
|
// User to user messages are special in that they need the player to exist in them, add if they don't
|
||||||
if (messageType == MessageType.UserMessage &&
|
if (
|
||||||
dialog?.Users is not null &&
|
messageType == MessageType.UserMessage
|
||||||
dialog.Users.All(userDialog => userDialog.Id != profile.CharacterData?.PmcData?.SessionId))
|
&& dialog?.Users is not null
|
||||||
|
&& dialog.Users.All(userDialog =>
|
||||||
|
userDialog.Id != profile.CharacterData?.PmcData?.SessionId
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
dialog.Users.Add(
|
dialog.Users.Add(
|
||||||
new UserDialogInfo
|
new UserDialogInfo
|
||||||
@@ -200,8 +207,12 @@ 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.CharacterData?.PmcData?.Info?.SelectedMemberCategory
|
SelectedMemberCategory = profile
|
||||||
}
|
.CharacterData
|
||||||
|
?.PmcData
|
||||||
|
?.Info
|
||||||
|
?.SelectedMemberCategory,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -220,7 +231,8 @@ public class DialogueController(
|
|||||||
/// <returns>GetMailDialogViewResponseData object</returns>
|
/// <returns>GetMailDialogViewResponseData object</returns>
|
||||||
public virtual GetMailDialogViewResponseData GenerateDialogueView(
|
public virtual GetMailDialogViewResponseData GenerateDialogueView(
|
||||||
GetMailDialogViewRequestData request,
|
GetMailDialogViewRequestData request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var dialogueId = request.DialogId;
|
var dialogueId = request.DialogId;
|
||||||
var fullProfile = _saveServer.GetProfile(sessionId);
|
var fullProfile = _saveServer.GetProfile(sessionId);
|
||||||
@@ -232,7 +244,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Messages = [],
|
Messages = [],
|
||||||
Profiles = [],
|
Profiles = [],
|
||||||
HasMessagesWithRewards = false
|
HasMessagesWithRewards = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +258,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Messages = dialogue.Messages,
|
Messages = dialogue.Messages,
|
||||||
Profiles = GetProfilesForMail(fullProfile, dialogue.Users),
|
Profiles = GetProfilesForMail(fullProfile, dialogue.Users),
|
||||||
HasMessagesWithRewards = MessagesHaveUncollectedRewards(dialogue.Messages!)
|
HasMessagesWithRewards = MessagesHaveUncollectedRewards(dialogue.Messages!),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,11 +270,16 @@ public class DialogueController(
|
|||||||
/// <returns>Dialogue</returns>
|
/// <returns>Dialogue</returns>
|
||||||
protected Dialogue GetDialogByIdFromProfile(
|
protected Dialogue GetDialogByIdFromProfile(
|
||||||
SptProfile profile,
|
SptProfile profile,
|
||||||
GetMailDialogViewRequestData request)
|
GetMailDialogViewRequestData request
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (profile.DialogueRecords is null || profile.DialogueRecords.ContainsKey(request.DialogId!))
|
if (
|
||||||
|
profile.DialogueRecords is null
|
||||||
|
|| profile.DialogueRecords.ContainsKey(request.DialogId!)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return profile.DialogueRecords?[request.DialogId!] ?? throw new NullReferenceException();
|
return profile.DialogueRecords?[request.DialogId!]
|
||||||
|
?? throw new NullReferenceException();
|
||||||
}
|
}
|
||||||
|
|
||||||
profile.DialogueRecords[request.DialogId!] = new Dialogue
|
profile.DialogueRecords[request.DialogId!] = new Dialogue
|
||||||
@@ -272,7 +289,7 @@ public class DialogueController(
|
|||||||
Pinned = false,
|
Pinned = false,
|
||||||
Messages = [],
|
Messages = [],
|
||||||
New = 0,
|
New = 0,
|
||||||
Type = request.Type
|
Type = request.Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (request.Type != MessageType.UserMessage)
|
if (request.Type != MessageType.UserMessage)
|
||||||
@@ -282,7 +299,9 @@ public class DialogueController(
|
|||||||
|
|
||||||
var dialogue = profile.DialogueRecords[request.DialogId!];
|
var dialogue = profile.DialogueRecords[request.DialogId!];
|
||||||
dialogue.Users = [];
|
dialogue.Users = [];
|
||||||
var chatBot = _dialogueChatBots.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId);
|
var chatBot = _dialogueChatBots.FirstOrDefault(cb =>
|
||||||
|
cb.GetChatBot().Id == request.DialogId
|
||||||
|
);
|
||||||
|
|
||||||
if (chatBot is null)
|
if (chatBot is null)
|
||||||
{
|
{
|
||||||
@@ -301,7 +320,10 @@ 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(SptProfile fullProfile, List<UserDialogInfo>? userDialogs)
|
protected List<UserDialogInfo> GetProfilesForMail(
|
||||||
|
SptProfile fullProfile,
|
||||||
|
List<UserDialogInfo>? userDialogs
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<UserDialogInfo> result = [];
|
List<UserDialogInfo> result = [];
|
||||||
if (userDialogs is null)
|
if (userDialogs is null)
|
||||||
@@ -330,8 +352,8 @@ public class DialogueController(
|
|||||||
Side = pmcProfile?.Info?.Side,
|
Side = pmcProfile?.Info?.Side,
|
||||||
Level = pmcProfile?.Info?.Level,
|
Level = pmcProfile?.Info?.Level,
|
||||||
MemberCategory = pmcProfile?.Info?.MemberCategory,
|
MemberCategory = pmcProfile?.Info?.MemberCategory,
|
||||||
SelectedMemberCategory = pmcProfile?.Info?.SelectedMemberCategory
|
SelectedMemberCategory = pmcProfile?.Info?.SelectedMemberCategory,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -344,15 +366,16 @@ public class DialogueController(
|
|||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <param name="dialogueId">Dialog id</param>
|
/// <param name="dialogueId">Dialog id</param>
|
||||||
/// <returns>Count of messages with attachments</returns>
|
/// <returns>Count of messages with attachments</returns>
|
||||||
protected int GetUnreadMessagesWithAttachmentsCount(
|
protected int GetUnreadMessagesWithAttachmentsCount(string sessionId, string dialogueId)
|
||||||
string sessionId,
|
|
||||||
string dialogueId)
|
|
||||||
{
|
{
|
||||||
var newAttachmentCount = 0;
|
var newAttachmentCount = 0;
|
||||||
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
|
var activeMessages = GetActiveMessagesFromDialog(sessionId, dialogueId);
|
||||||
foreach (var message in activeMessages)
|
foreach (var message in activeMessages)
|
||||||
{
|
{
|
||||||
if (message.HasRewards.GetValueOrDefault(false) && !message.RewardCollected.GetValueOrDefault(false))
|
if (
|
||||||
|
message.HasRewards.GetValueOrDefault(false)
|
||||||
|
&& !message.RewardCollected.GetValueOrDefault(false)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
newAttachmentCount++;
|
newAttachmentCount++;
|
||||||
}
|
}
|
||||||
@@ -372,11 +395,13 @@ public class DialogueController(
|
|||||||
var timeNow = _timeUtil.GetTimeStamp();
|
var timeNow = _timeUtil.GetTimeStamp();
|
||||||
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
|
var dialogs = _dialogueHelper.GetDialogsForProfile(sessionId);
|
||||||
|
|
||||||
return dialogs[dialogueId].Messages?.Where(message =>
|
return dialogs[dialogueId]
|
||||||
|
.Messages?.Where(message =>
|
||||||
{
|
{
|
||||||
var checkTime = message.DateTime + (message.MaxStorageTime ?? 0);
|
var checkTime = message.DateTime + (message.MaxStorageTime ?? 0);
|
||||||
return timeNow < checkTime;
|
return timeNow < checkTime;
|
||||||
}).ToList() ?? [];
|
})
|
||||||
|
.ToList() ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -395,9 +420,7 @@ public class DialogueController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dialogueId">id of the dialog to remove</param>
|
/// <param name="dialogueId">id of the dialog to remove</param>
|
||||||
/// <param name="sessionId">Player id</param>
|
/// <param name="sessionId">Player id</param>
|
||||||
public virtual void RemoveDialogue(
|
public virtual void RemoveDialogue(string? dialogueId, string sessionId)
|
||||||
string? dialogueId,
|
|
||||||
string sessionId)
|
|
||||||
{
|
{
|
||||||
var profile = _saveServer.GetProfile(sessionId);
|
var profile = _saveServer.GetProfile(sessionId);
|
||||||
if (!profile.DialogueRecords.ContainsKey(dialogueId))
|
if (!profile.DialogueRecords.ContainsKey(dialogueId))
|
||||||
@@ -405,11 +428,7 @@ public class DialogueController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"dialogue-unable_to_find_in_profile",
|
"dialogue-unable_to_find_in_profile",
|
||||||
new
|
new { sessionId, dialogueId }
|
||||||
{
|
|
||||||
sessionId,
|
|
||||||
dialogueId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -433,11 +452,7 @@ public class DialogueController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"dialogue-unable_to_find_in_profile",
|
"dialogue-unable_to_find_in_profile",
|
||||||
new
|
new { sessionId, dialogueId }
|
||||||
{
|
|
||||||
sessionId,
|
|
||||||
dialogueId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -461,10 +476,7 @@ public class DialogueController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"dialogue-unable_to_find_dialogs_in_profile",
|
"dialogue-unable_to_find_dialogs_in_profile",
|
||||||
new
|
new { sessionId }
|
||||||
{
|
|
||||||
sessionId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -491,9 +503,7 @@ public class DialogueController(
|
|||||||
var dialog = dialogs.TryGetValue(dialogueId, out var dialogInfo);
|
var dialog = dialogs.TryGetValue(dialogueId, out var dialogInfo);
|
||||||
if (!dialog)
|
if (!dialog)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(_localisationService.GetText("dialogue-unable_to_find_in_profile"));
|
||||||
_localisationService.GetText("dialogue-unable_to_find_in_profile")
|
|
||||||
);
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -508,7 +518,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Messages = messagesWithAttachments,
|
Messages = messagesWithAttachments,
|
||||||
Profiles = [],
|
Profiles = [],
|
||||||
HasMessagesWithRewards = MessagesHaveUncollectedRewards(messagesWithAttachments)
|
HasMessagesWithRewards = MessagesHaveUncollectedRewards(messagesWithAttachments),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,18 +528,15 @@ 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 string SendMessage(
|
public virtual string SendMessage(string sessionId, SendMessageRequest request)
|
||||||
string sessionId,
|
|
||||||
SendMessageRequest request)
|
|
||||||
{
|
{
|
||||||
_mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId!, request.Text!);
|
_mailSendService.SendPlayerMessageToNpc(sessionId, request.DialogId!, request.Text!);
|
||||||
|
|
||||||
return (_dialogueChatBots.FirstOrDefault(cb =>
|
return (
|
||||||
cb.GetChatBot().Id == request.DialogId
|
_dialogueChatBots
|
||||||
)
|
.FirstOrDefault(cb => cb.GetChatBot().Id == request.DialogId)
|
||||||
?.HandleMessage(sessionId, request) ??
|
?.HandleMessage(sessionId, request) ?? request.DialogId
|
||||||
request.DialogId) ??
|
) ?? string.Empty;
|
||||||
string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -592,7 +599,10 @@ 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(string sessionID, FriendRequestData request)
|
public virtual FriendRequestSendResponse SendFriendRequest(
|
||||||
|
string 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);
|
var friendProfile = _profileHelper.GetFullProfile(request.To);
|
||||||
@@ -602,7 +612,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Status = BackendErrorCodes.PlayerProfileNotFound,
|
Status = BackendErrorCodes.PlayerProfileNotFound,
|
||||||
RequestId = "", // Unused in an error state
|
RequestId = "", // Unused in an error state
|
||||||
RetryAfter = 600
|
RetryAfter = 600,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +630,9 @@ public class DialogueController(
|
|||||||
var notification = new WsFriendsListAccept
|
var notification = new WsFriendsListAccept
|
||||||
{
|
{
|
||||||
EventType = NotificationEventType.friendListRequestAccept,
|
EventType = NotificationEventType.friendListRequestAccept,
|
||||||
Profile = _profileHelper.GetChatRoomMemberFromPmcProfile(friendProfile.CharacterData.PmcData)
|
Profile = _profileHelper.GetChatRoomMemberFromPmcProfile(
|
||||||
|
friendProfile.CharacterData.PmcData
|
||||||
|
),
|
||||||
};
|
};
|
||||||
_notificationSendHelper.SendMessage(sessionID, notification);
|
_notificationSendHelper.SendMessage(sessionID, notification);
|
||||||
},
|
},
|
||||||
@@ -633,7 +645,7 @@ public class DialogueController(
|
|||||||
{
|
{
|
||||||
Status = BackendErrorCodes.None,
|
Status = BackendErrorCodes.None,
|
||||||
RequestId = friendProfile.ProfileInfo.Aid.ToString(),
|
RequestId = friendProfile.ProfileInfo.Aid.ToString(),
|
||||||
RetryAfter = 600
|
RetryAfter = 600,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,7 +674,9 @@ 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($"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}");
|
_logger.Warning(
|
||||||
|
$"unable to clear messages from dialog: {request.DialogId} as it cannot be found in profile: {sessionId}"
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ using SPTarkov.Server.Core.Utils.Cloners;
|
|||||||
using SPTarkov.Server.Core.Utils.Json;
|
using SPTarkov.Server.Core.Utils.Json;
|
||||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||||
|
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
@@ -81,7 +80,7 @@ public class GameController(
|
|||||||
fullProfile.SptData ??= new Spt
|
fullProfile.SptData ??= new Spt
|
||||||
{
|
{
|
||||||
//TODO: complete
|
//TODO: complete
|
||||||
Version = "Replace_me"
|
Version = "Replace_me",
|
||||||
};
|
};
|
||||||
fullProfile.SptData.Migrations ??= new Dictionary<string, long>();
|
fullProfile.SptData.Migrations ??= new Dictionary<string, long>();
|
||||||
fullProfile.FriendProfileIds ??= [];
|
fullProfile.FriendProfileIds ??= [];
|
||||||
@@ -91,8 +90,14 @@ public class GameController(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<string, int>(new Dictionary<string, int>(), []);
|
fullProfile.CharacterData!.PmcData!.WishList ??= new DictionaryOrList<string, int>(
|
||||||
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<string, int>(new Dictionary<string, int>(), []);
|
new Dictionary<string, int>(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
fullProfile.CharacterData.ScavData!.WishList ??= new DictionaryOrList<string, int>(
|
||||||
|
new Dictionary<string, int>(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
if (fullProfile.DialogueRecords is not null)
|
if (fullProfile.DialogueRecords is not null)
|
||||||
{
|
{
|
||||||
@@ -101,7 +106,9 @@ public class GameController(
|
|||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}");
|
_logger.Debug(
|
||||||
|
$"Started game with session {sessionId} {fullProfile.ProfileInfo?.Username}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmcProfile = fullProfile.CharacterData.PmcData;
|
var pmcProfile = fullProfile.CharacterData.PmcData;
|
||||||
@@ -133,7 +140,12 @@ public class GameController(
|
|||||||
_hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
|
_hideoutHelper.UnlockHideoutWallInProfile(pmcProfile);
|
||||||
|
|
||||||
// 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 (!_profileActivityService.ActiveWithinLastMinutes(sessionId, _hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes))
|
if (
|
||||||
|
!_profileActivityService.ActiveWithinLastMinutes(
|
||||||
|
sessionId,
|
||||||
|
_hideoutConfig.UpdateProfileHideoutWhenActiveWithinMinutes
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutHelper.UpdatePlayerHideout(sessionId);
|
_hideoutHelper.UpdatePlayerHideout(sessionId);
|
||||||
}
|
}
|
||||||
@@ -167,10 +179,12 @@ public class GameController(
|
|||||||
public GameConfigResponse GetGameConfig(string sessionId)
|
public GameConfigResponse GetGameConfig(string sessionId)
|
||||||
{
|
{
|
||||||
var profile = _profileHelper.GetPmcProfile(sessionId);
|
var profile = _profileHelper.GetPmcProfile(sessionId);
|
||||||
var gameTime = profile?.Stats?.Eft?.OverallCounters?.Items?
|
var gameTime =
|
||||||
.FirstOrDefault(c => c.Key!.Contains("LifeTime") && c.Key.Contains("Pmc"))
|
profile
|
||||||
?.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
|
||||||
{
|
{
|
||||||
@@ -188,18 +202,14 @@ public class GameController(
|
|||||||
Trading = _httpServerHelper.GetBackendUrl(),
|
Trading = _httpServerHelper.GetBackendUrl(),
|
||||||
Messaging = _httpServerHelper.GetBackendUrl(),
|
Messaging = _httpServerHelper.GetBackendUrl(),
|
||||||
Main = _httpServerHelper.GetBackendUrl(),
|
Main = _httpServerHelper.GetBackendUrl(),
|
||||||
RagFair = _httpServerHelper.GetBackendUrl()
|
RagFair = _httpServerHelper.GetBackendUrl(),
|
||||||
},
|
},
|
||||||
UseProtobuf = false,
|
UseProtobuf = false,
|
||||||
UtcTime = _timeUtil.GetTimeStamp(),
|
UtcTime = _timeUtil.GetTimeStamp(),
|
||||||
TotalInGame = gameTime,
|
TotalInGame = gameTime,
|
||||||
SessionMode = "pve",
|
SessionMode = "pve",
|
||||||
PurchasedGames = new PurchasedGames
|
PurchasedGames = new PurchasedGames { IsEftPurchased = true, IsArenaPurchased = false },
|
||||||
{
|
IsGameSynced = true,
|
||||||
IsEftPurchased = true,
|
|
||||||
IsArenaPurchased = false
|
|
||||||
},
|
|
||||||
IsGameSynced = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@@ -211,14 +221,12 @@ public class GameController(
|
|||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <param name="requestData"></param>
|
/// <param name="requestData"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public GameModeResponse GetGameMode(
|
public GameModeResponse GetGameMode(string sessionId, GameModeRequestData requestData)
|
||||||
string sessionId,
|
|
||||||
GameModeRequestData requestData)
|
|
||||||
{
|
{
|
||||||
return new GameModeResponse
|
return new GameModeResponse
|
||||||
{
|
{
|
||||||
GameMode = "pve",
|
GameMode = "pve",
|
||||||
BackendUrl = _httpServerHelper.GetBackendUrl()
|
BackendUrl = _httpServerHelper.GetBackendUrl(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,14 +237,7 @@ public class GameController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public List<ServerDetails> GetServer(string sessionId)
|
public List<ServerDetails> GetServer(string sessionId)
|
||||||
{
|
{
|
||||||
return
|
return [new ServerDetails { Ip = _httpConfig.BackendIp, Port = _httpConfig.BackendPort }];
|
||||||
[
|
|
||||||
new ServerDetails
|
|
||||||
{
|
|
||||||
Ip = _httpConfig.BackendIp,
|
|
||||||
Port = _httpConfig.BackendPort
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -246,13 +247,9 @@ public class GameController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public CurrentGroupResponse GetCurrentGroup(string sessionId)
|
public CurrentGroupResponse GetCurrentGroup(string sessionId)
|
||||||
{
|
{
|
||||||
return new CurrentGroupResponse
|
return new CurrentGroupResponse { Squad = [] };
|
||||||
{
|
|
||||||
Squad = []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/checkVersion
|
/// Handle client/checkVersion
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -263,7 +260,7 @@ public class GameController(
|
|||||||
return new CheckVersionResponse
|
return new CheckVersionResponse
|
||||||
{
|
{
|
||||||
IsValid = true,
|
IsValid = true,
|
||||||
LatestVersion = _coreConfig.CompatibleTarkovVersion
|
LatestVersion = _coreConfig.CompatibleTarkovVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,11 +272,7 @@ public class GameController(
|
|||||||
public GameKeepAliveResponse GetKeepAlive(string sessionId)
|
public GameKeepAliveResponse GetKeepAlive(string sessionId)
|
||||||
{
|
{
|
||||||
_profileActivityService.SetActivityTimestamp(sessionId);
|
_profileActivityService.SetActivityTimestamp(sessionId);
|
||||||
return new GameKeepAliveResponse
|
return new GameKeepAliveResponse { Message = "OK", UtcTime = _timeUtil.GetTimeStamp() };
|
||||||
{
|
|
||||||
Message = "OK",
|
|
||||||
UtcTime = _timeUtil.GetTimeStamp()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -311,7 +304,9 @@ public class GameController(
|
|||||||
var botReloadSkill = _profileHelper.GetSkillFromProfile(pmcProfile, SkillTypes.BotReload);
|
var botReloadSkill = _profileHelper.GetSkillFromProfile(pmcProfile, SkillTypes.BotReload);
|
||||||
if (botReloadSkill?.Progress > 0)
|
if (botReloadSkill?.Progress > 0)
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("server_start_player_active_botreload_skill"));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("server_start_player_active_botreload_skill")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,23 +332,25 @@ public class GameController(
|
|||||||
var hpRegenPerHour = 456.6;
|
var hpRegenPerHour = 456.6;
|
||||||
|
|
||||||
// Set new values, whatever is smallest
|
// Set new values, whatever is smallest
|
||||||
energyRegenPerHour += pmcProfile.Bonuses!
|
energyRegenPerHour += pmcProfile
|
||||||
.Where(bonus => bonus.Type == BonusType.EnergyRegeneration)
|
.Bonuses!.Where(bonus => bonus.Type == BonusType.EnergyRegeneration)
|
||||||
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
||||||
|
|
||||||
hydrationRegenPerHour += pmcProfile.Bonuses!
|
hydrationRegenPerHour += pmcProfile
|
||||||
.Where(bonus => bonus.Type == BonusType.HydrationRegeneration)
|
.Bonuses!.Where(bonus => bonus.Type == BonusType.HydrationRegeneration)
|
||||||
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
||||||
|
|
||||||
hpRegenPerHour += pmcProfile.Bonuses!
|
hpRegenPerHour += pmcProfile
|
||||||
.Where(bonus => bonus.Type == BonusType.HealthRegeneration)
|
.Bonuses!.Where(bonus => bonus.Type == BonusType.HealthRegeneration)
|
||||||
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
.Aggregate(0d, (sum, bonus) => sum + bonus.Value!.Value);
|
||||||
|
|
||||||
// Player has energy deficit
|
// Player has energy deficit
|
||||||
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(energyRegenPerHour * (diffSeconds!.Value / 3600));
|
pmcProfile.Health!.Energy!.Current += Math.Round(
|
||||||
|
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;
|
||||||
@@ -361,9 +358,14 @@ public class GameController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Player has hydration deficit
|
// Player has hydration deficit
|
||||||
if (pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum <= _deviation)
|
if (
|
||||||
|
pmcProfile.Health?.Hydration?.Current - pmcProfile.Health?.Hydration?.Maximum
|
||||||
|
<= _deviation
|
||||||
|
)
|
||||||
{
|
{
|
||||||
pmcProfile.Health!.Hydration!.Current += Math.Round(hydrationRegenPerHour * (diffSeconds!.Value / 3600));
|
pmcProfile.Health!.Hydration!.Current += Math.Round(
|
||||||
|
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;
|
||||||
@@ -383,10 +385,15 @@ 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(PmcData pmcProfile, double hpRegenPerHour, double diffSeconds)
|
protected void DecreaseBodyPartEffectTimes(
|
||||||
|
PmcData pmcProfile,
|
||||||
|
double hpRegenPerHour,
|
||||||
|
double diffSeconds
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var bodyPart in pmcProfile.Health!.BodyParts!
|
foreach (
|
||||||
.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)
|
||||||
@@ -399,7 +406,6 @@ public class GameController(
|
|||||||
bodyPart.Health.Current = bodyPart.Health.Maximum;
|
bodyPart.Health.Current = bodyPart.Health.Maximum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (bodyPart.Effects is null || bodyPart.Effects.Count == 0)
|
if (bodyPart.Effects is null || bodyPart.Effects.Count == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -475,7 +481,9 @@ public class GameController(
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
fullProfile.SptData.Mods.Any(m =>
|
fullProfile.SptData.Mods.Any(m =>
|
||||||
m.Author == mod.ModMetadata.Author && m.Version == mod.ModMetadata.Version && m.Name == mod.ModMetadata.Name
|
m.Author == mod.ModMetadata.Author
|
||||||
|
&& m.Version == mod.ModMetadata.Version
|
||||||
|
&& m.Name == mod.ModMetadata.Name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -490,7 +498,7 @@ public class GameController(
|
|||||||
Version = mod.ModMetadata.Version,
|
Version = mod.ModMetadata.Version,
|
||||||
Name = mod.ModMetadata.Name,
|
Name = mod.ModMetadata.Name,
|
||||||
Url = mod.ModMetadata.Url,
|
Url = mod.ModMetadata.Url,
|
||||||
DateAdded = _timeUtil.GetTimeStamp()
|
DateAdded = _timeUtil.GetTimeStamp(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -552,7 +560,9 @@ 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($"Server version: {ProgramStatics.SPT_VERSION() ?? _coreConfig.SptVersion} {ProgramStatics.COMMIT()}");
|
_logger.Debug(
|
||||||
|
$"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()}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ public class HealthController(
|
|||||||
LocalisationService _localisationService,
|
LocalisationService _localisationService,
|
||||||
HttpResponseUtil _httpResponseUtil,
|
HttpResponseUtil _httpResponseUtil,
|
||||||
HealthHelper _healthHelper,
|
HealthHelper _healthHelper,
|
||||||
ICloner _cloner)
|
ICloner _cloner
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When healing in menu
|
/// When healing in menu
|
||||||
@@ -37,15 +38,21 @@ public class HealthController(
|
|||||||
public ItemEventRouterResponse OffRaidHeal(
|
public ItemEventRouterResponse OffRaidHeal(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
OffraidHealRequestData request,
|
OffraidHealRequestData request,
|
||||||
string sessionID)
|
string 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 => item.Id == request.Item);
|
var healingItemToUse = pmcData.Inventory.Items.FirstOrDefault(item =>
|
||||||
|
item.Id == request.Item
|
||||||
|
);
|
||||||
if (healingItemToUse is null)
|
if (healingItemToUse is null)
|
||||||
{
|
{
|
||||||
var errorMessage = _localisationService.GetText("health-healing_item_not_found", request.Item);
|
var errorMessage = _localisationService.GetText(
|
||||||
|
"health-healing_item_not_found",
|
||||||
|
request.Item
|
||||||
|
);
|
||||||
_logger.Error(errorMessage);
|
_logger.Error(errorMessage);
|
||||||
|
|
||||||
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
return _httpResponseUtil.AppendErrorToOutput(output, errorMessage);
|
||||||
@@ -61,11 +68,10 @@ public class HealthController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get max healing from db
|
// Get max healing from db
|
||||||
var maxHp = _itemHelper.GetItem(healingItemToUse.Template).Value.Properties.MaxHpResource;
|
var maxHp = _itemHelper
|
||||||
healingItemToUse.Upd.MedKit = new UpdMedKit
|
.GetItem(healingItemToUse.Template)
|
||||||
{
|
.Value.Properties.MaxHpResource;
|
||||||
HpResource = maxHp - request.Count
|
healingItemToUse.Upd.MedKit = new UpdMedKit { HpResource = maxHp - request.Count }; // Subtract amout used from max
|
||||||
}; // 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)
|
||||||
}
|
}
|
||||||
@@ -82,7 +88,9 @@ 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($"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}");
|
_logger.Warning(
|
||||||
|
$"Player: {sessionID} Tried to heal a non-existent body part: {request.Part}"
|
||||||
|
);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -105,7 +113,12 @@ public class HealthController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if healing item removes the effect on limb
|
// Check if healing item removes the effect on limb
|
||||||
if (!healItemEffectDetails.TryGetValue(effect, out var matchingEffectFromHealingItem))
|
if (
|
||||||
|
!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;
|
||||||
@@ -140,7 +153,8 @@ public class HealthController(
|
|||||||
public ItemEventRouterResponse OffRaidEat(
|
public ItemEventRouterResponse OffRaidEat(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
OffraidEatRequestData request,
|
OffraidEatRequestData request,
|
||||||
string sessionID)
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionID);
|
var output = _eventOutputHolder.GetOutput(sessionID);
|
||||||
var resourceLeft = 0d;
|
var resourceLeft = 0d;
|
||||||
@@ -155,7 +169,9 @@ public class HealthController(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var consumedItemMaxResource = _itemHelper.GetItem(itemToConsume.Template).Value.Properties.MaxResource;
|
var consumedItemMaxResource = _itemHelper
|
||||||
|
.GetItem(itemToConsume.Template)
|
||||||
|
.Value.Properties.MaxResource;
|
||||||
if (consumedItemMaxResource > 1)
|
if (consumedItemMaxResource > 1)
|
||||||
{
|
{
|
||||||
// Ensure item has a upd object
|
// Ensure item has a upd object
|
||||||
@@ -165,7 +181,7 @@ public class HealthController(
|
|||||||
{
|
{
|
||||||
itemToConsume.Upd.FoodDrink = new UpdFoodDrink
|
itemToConsume.Upd.FoodDrink = new UpdFoodDrink
|
||||||
{
|
{
|
||||||
HpPercent = consumedItemMaxResource - request.Count
|
HpPercent = consumedItemMaxResource - request.Count,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -192,14 +208,21 @@ public class HealthController(
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case HealthFactor.Hydration:
|
case HealthFactor.Hydration:
|
||||||
ApplyEdibleEffect(pmcData.Health.Hydration, effectProps, foodIsSingleUse, request);
|
ApplyEdibleEffect(
|
||||||
|
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($"Unhandled effect after consuming: {itemToConsume.Template}, {key}");
|
_logger.Warning(
|
||||||
|
$"Unhandled effect after consuming: {itemToConsume.Template}, {key}"
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,8 +237,12 @@ public class HealthController(
|
|||||||
/// <param name="consumptionDetails">Properties of consumed item</param>
|
/// <param name="consumptionDetails">Properties of consumed item</param>
|
||||||
/// <param name="foodIsSingleUse">Single use item</param>
|
/// <param name="foodIsSingleUse">Single use item</param>
|
||||||
/// <param name="request">Client request</param>
|
/// <param name="request">Client request</param>
|
||||||
protected void ApplyEdibleEffect(CurrentMinMax bodyValue, EffectsHealthProps consumptionDetails, bool foodIsSingleUse,
|
protected void ApplyEdibleEffect(
|
||||||
OffraidEatRequestData request)
|
CurrentMinMax bodyValue,
|
||||||
|
EffectsHealthProps consumptionDetails,
|
||||||
|
bool foodIsSingleUse,
|
||||||
|
OffraidEatRequestData request
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (foodIsSingleUse)
|
if (foodIsSingleUse)
|
||||||
// Apply whole value from passed in parameter
|
// Apply whole value from passed in parameter
|
||||||
@@ -253,7 +280,8 @@ public class HealthController(
|
|||||||
public ItemEventRouterResponse HealthTreatment(
|
public ItemEventRouterResponse HealthTreatment(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
HealthTreatmentRequestData healthTreatmentRequest,
|
HealthTreatmentRequestData healthTreatmentRequest,
|
||||||
string sessionID)
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionID);
|
var output = _eventOutputHolder.GetOutput(sessionID);
|
||||||
var payMoneyRequest = new ProcessBuyTradeRequestData
|
var payMoneyRequest = new ProcessBuyTradeRequestData
|
||||||
@@ -264,7 +292,7 @@ public class HealthController(
|
|||||||
Type = "",
|
Type = "",
|
||||||
ItemId = "",
|
ItemId = "",
|
||||||
Count = 0,
|
Count = 0,
|
||||||
SchemeId = 0
|
SchemeId = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
_paymentService.PayMoney(pmcData, payMoneyRequest, sessionID, output);
|
_paymentService.PayMoney(pmcData, payMoneyRequest, sessionID, output);
|
||||||
@@ -315,10 +343,7 @@ public class HealthController(
|
|||||||
/// <param name="pmcData">Player profile</param>
|
/// <param name="pmcData">Player profile</param>
|
||||||
/// <param name="request">Request data</param>
|
/// <param name="request">Request data</param>
|
||||||
/// <param name="sessionId">session id</param>
|
/// <param name="sessionId">session id</param>
|
||||||
public void ApplyWorkoutChanges(
|
public void ApplyWorkoutChanges(PmcData? pmcData, WorkoutData request, string sessionId)
|
||||||
PmcData? pmcData,
|
|
||||||
WorkoutData request,
|
|
||||||
string sessionId)
|
|
||||||
{
|
{
|
||||||
pmcData.Skills.Common = request.Skills.Common;
|
pmcData.Skills.Common = request.Skills.Common;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -91,11 +91,15 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}");
|
_logger.Debug(
|
||||||
|
$"Found {profileInsuranceDetails.Count} insurance packages in profile {sessionId}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return profileInsuranceDetails.Where(insured => insuranceTime >= insured.ScheduledTime).ToList();
|
return profileInsuranceDetails
|
||||||
|
.Where(insured => insuranceTime >= insured.ScheduledTime)
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -159,17 +163,20 @@ public class InsuranceController(
|
|||||||
protected void RemoveInsurancePackageFromProfile(string sessionId, Insurance insPackage)
|
protected void RemoveInsurancePackageFromProfile(string sessionId, Insurance insPackage)
|
||||||
{
|
{
|
||||||
var profile = _saveServer.GetProfile(sessionId);
|
var profile = _saveServer.GetProfile(sessionId);
|
||||||
profile.InsuranceList = profile.InsuranceList.Where(insurance =>
|
profile.InsuranceList = profile
|
||||||
insurance.TraderId != insPackage.TraderId ||
|
.InsuranceList.Where(insurance =>
|
||||||
insurance.SystemData?.Date != insPackage.SystemData?.Date ||
|
insurance.TraderId != insPackage.TraderId
|
||||||
insurance.SystemData?.Time != insPackage.SystemData?.Time ||
|
|| insurance.SystemData?.Date != insPackage.SystemData?.Date
|
||||||
insurance.SystemData?.Location != insPackage.SystemData?.Location
|
|| insurance.SystemData?.Time != insPackage.SystemData?.Time
|
||||||
|
|| insurance.SystemData?.Location != insPackage.SystemData?.Location
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}");
|
_logger.Debug(
|
||||||
|
$"Removed processed insurance package. Remaining packages: {profile.InsuranceList.Count}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,11 +193,14 @@ 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 = _itemHelper.GenerateItemsMap(insured.Items);
|
var itemsMap = _itemHelper.GenerateItemsMap(insured.Items);
|
||||||
var parentAttachmentsMap = PopulateParentAttachmentsMap(rootItemParentId, insured, itemsMap);
|
var parentAttachmentsMap = PopulateParentAttachmentsMap(
|
||||||
|
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));
|
||||||
);
|
|
||||||
|
|
||||||
// Process all items that are not attached, attachments; those are handled separately, by value.
|
// Process all items that are not attached, attachments; those are handled separately, by value.
|
||||||
if (hasRegularItems)
|
if (hasRegularItems)
|
||||||
@@ -229,7 +239,11 @@ public class InsuranceController(
|
|||||||
/// <param name="insured">The insurance object containing the items to evaluate</param>
|
/// <param name="insured">The insurance object containing the items to evaluate</param>
|
||||||
/// <param name="itemsMap">A Dictionary for quick item look-up by item ID</param>
|
/// <param name="itemsMap">A Dictionary for quick item look-up by item ID</param>
|
||||||
/// <returns>A dictionary containing parent item IDs to arrays of their attachment items</returns>
|
/// <returns>A dictionary containing parent item IDs to arrays of their attachment items</returns>
|
||||||
protected Dictionary<string, List<Item>> PopulateParentAttachmentsMap(string rootItemParentID, Insurance insured, Dictionary<string, Item> itemsMap)
|
protected Dictionary<string, List<Item>> PopulateParentAttachmentsMap(
|
||||||
|
string rootItemParentID,
|
||||||
|
Insurance insured,
|
||||||
|
Dictionary<string, Item> itemsMap
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var mainParentToAttachmentsMap = new Dictionary<string, List<Item>>();
|
var mainParentToAttachmentsMap = new Dictionary<string, List<Item>>();
|
||||||
foreach (var insuredItem in insured.Items)
|
foreach (var insuredItem in insured.Items)
|
||||||
@@ -247,7 +261,7 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
insuredItemId = insuredItem.Id,
|
insuredItemId = insuredItem.Id,
|
||||||
insuredItemTpl = insuredItem.Template,
|
insuredItemTpl = insuredItem.Template,
|
||||||
parentId = insuredItem.ParentId
|
parentId = insuredItem.ParentId,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -270,7 +284,7 @@ public class InsuranceController(
|
|||||||
new
|
new
|
||||||
{
|
{
|
||||||
insuredItemId = insuredItem.Id,
|
insuredItemId = insuredItem.Id,
|
||||||
insuredItemTpl = insuredItem.Template
|
insuredItemTpl = insuredItem.Template,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -290,7 +304,7 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
insuredItemId = insuredItem.Id,
|
insuredItemId = insuredItem.Id,
|
||||||
insuredItemTpl = insuredItem.Template,
|
insuredItemTpl = insuredItem.Template,
|
||||||
parentId = insuredItem.ParentId
|
parentId = insuredItem.ParentId,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -322,8 +336,10 @@ public class InsuranceController(
|
|||||||
/// <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>
|
||||||
/// <param name="itemsMap">Hashset containing parent item IDs to arrays of their attachment items which are not moddable in-raid</param>
|
/// <param name="itemsMap">Hashset containing parent item IDs to arrays of their attachment items which are not moddable in-raid</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected Dictionary<string, List<Item>> RemoveNonModdableAttachments(Dictionary<string, List<Item>> parentAttachmentsMap,
|
protected Dictionary<string, List<Item>> RemoveNonModdableAttachments(
|
||||||
Dictionary<string, Item> itemsMap)
|
Dictionary<string, List<Item>> parentAttachmentsMap,
|
||||||
|
Dictionary<string, Item> itemsMap
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var updatedMap = new Dictionary<string, List<Item>>();
|
var updatedMap = new Dictionary<string, List<Item>>();
|
||||||
|
|
||||||
@@ -371,7 +387,11 @@ 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(Insurance insured, HashSet<string> toDelete, Dictionary<string, List<Item>> parentAttachmentsMap)
|
protected void ProcessRegularItems(
|
||||||
|
Insurance insured,
|
||||||
|
HashSet<string> toDelete,
|
||||||
|
Dictionary<string, List<Item>> parentAttachmentsMap
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var insuredItem in insured.Items)
|
foreach (var insuredItem in insured.Items)
|
||||||
{
|
{
|
||||||
@@ -419,8 +439,12 @@ public class InsuranceController(
|
|||||||
/// <param name="itemsMap">Dictionary for quick item look-up by item ID</param>
|
/// <param name="itemsMap">Dictionary for quick item look-up by item ID</param>
|
||||||
/// <param name="insuredTraderId">Trader ID from the Insurance object</param>
|
/// <param name="insuredTraderId">Trader ID from the Insurance object</param>
|
||||||
/// <param name="toDelete">Tracked attachment ids to be removed</param>
|
/// <param name="toDelete">Tracked attachment ids to be removed</param>
|
||||||
protected void ProcessAttachments(Dictionary<string, List<Item>> mainParentToAttachmentsMap, Dictionary<string, Item> itemsMap, string? insuredTraderId,
|
protected void ProcessAttachments(
|
||||||
HashSet<string> toDelete)
|
Dictionary<string, List<Item>> mainParentToAttachmentsMap,
|
||||||
|
Dictionary<string, Item> itemsMap,
|
||||||
|
string? insuredTraderId,
|
||||||
|
HashSet<string> toDelete
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var parentObj in mainParentToAttachmentsMap)
|
foreach (var parentObj in mainParentToAttachmentsMap)
|
||||||
{
|
{
|
||||||
@@ -444,7 +468,6 @@ public class InsuranceController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by
|
/// Takes an array of attachment items that belong to the same main-parent item, sorts them in descending order by
|
||||||
/// their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the
|
/// their maximum price. For each attachment, a roll is made to determine if a deletion should be made. Once the
|
||||||
@@ -454,16 +477,26 @@ 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(List<Item> attachments, string? traderId, HashSet<string> toDelete)
|
protected void ProcessAttachmentByParent(
|
||||||
|
List<Item> attachments,
|
||||||
|
string? traderId,
|
||||||
|
HashSet<string> 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(weightedAttachmentByPrice, traderId);
|
var countOfAttachmentsToRemove = GetAttachmentCountToRemove(
|
||||||
|
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<string, double?>(_mathUtil, _cloner);
|
var attachmentsProbabilityArray = new ProbabilityObjectArray<string, double?>(
|
||||||
|
_mathUtil,
|
||||||
|
_cloner
|
||||||
|
);
|
||||||
foreach (var attachmentTpl in weightedAttachmentByPrice)
|
foreach (var attachmentTpl in weightedAttachmentByPrice)
|
||||||
{
|
{
|
||||||
attachmentsProbabilityArray.Add(
|
attachmentsProbabilityArray.Add(
|
||||||
@@ -472,7 +505,10 @@ public class InsuranceController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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((int) countOfAttachmentsToRemove, false);
|
var attachmentIdsToRemove = attachmentsProbabilityArray.Draw(
|
||||||
|
(int)countOfAttachmentsToRemove,
|
||||||
|
false
|
||||||
|
);
|
||||||
foreach (var attachmentId in attachmentIdsToRemove)
|
foreach (var attachmentId in attachmentIdsToRemove)
|
||||||
{
|
{
|
||||||
toDelete.Add(attachmentId);
|
toDelete.Add(attachmentId);
|
||||||
@@ -492,7 +528,11 @@ public class InsuranceController(
|
|||||||
/// <param name="attachmentIdsToRemove"></param>
|
/// <param name="attachmentIdsToRemove"></param>
|
||||||
/// <param name="attachments"></param>
|
/// <param name="attachments"></param>
|
||||||
/// <param name="attachmentPrices"></param>
|
/// <param name="attachmentPrices"></param>
|
||||||
protected void LogAttachmentsBeingRemoved(List<string> attachmentIdsToRemove, List<Item> attachments, Dictionary<string, double> attachmentPrices)
|
protected void LogAttachmentsBeingRemoved(
|
||||||
|
List<string> attachmentIdsToRemove,
|
||||||
|
List<Item> attachments,
|
||||||
|
Dictionary<string, double> attachmentPrices
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var index = 1;
|
var index = 1;
|
||||||
foreach (var attachmentId in attachmentIdsToRemove)
|
foreach (var attachmentId in attachmentIdsToRemove)
|
||||||
@@ -500,8 +540,8 @@ public class InsuranceController(
|
|||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
$"Attachment {index} Id: {attachmentId} Tpl: {attachments.FirstOrDefault(x => x.Id == attachmentId)?.Template} - " +
|
$"Attachment {index} Id: {attachmentId} Tpl: {attachments.FirstOrDefault(x => x.Id == attachmentId)?.Template} - "
|
||||||
$"Price: {attachmentPrices[attachmentId]}"
|
+ $"Price: {attachmentPrices[attachmentId]}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,7 +561,10 @@ public class InsuranceController(
|
|||||||
// Get a dictionary of item tpls + their rouble price
|
// Get a dictionary of item tpls + their rouble price
|
||||||
foreach (var attachment in attachments)
|
foreach (var attachment in attachments)
|
||||||
{
|
{
|
||||||
var price = _ragfairPriceService.GetDynamicItemPrice(attachment.Template, Money.ROUBLES);
|
var price = _ragfairPriceService.GetDynamicItemPrice(
|
||||||
|
attachment.Template,
|
||||||
|
Money.ROUBLES
|
||||||
|
);
|
||||||
if (price is not null)
|
if (price is not null)
|
||||||
{
|
{
|
||||||
result[attachment.Id] = Math.Round(price ?? 0);
|
result[attachment.Id] = Math.Round(price ?? 0);
|
||||||
@@ -539,7 +582,10 @@ 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(Dictionary<string, double> weightedAttachmentByPrice, string? traderId)
|
protected double GetAttachmentCountToRemove(
|
||||||
|
Dictionary<string, double> weightedAttachmentByPrice,
|
||||||
|
string? traderId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
const int removeCount = 0;
|
const int removeCount = 0;
|
||||||
|
|
||||||
@@ -550,7 +596,9 @@ 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 => attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken)
|
.Where(attachment =>
|
||||||
|
attachment.Value >= _insuranceConfig.MinAttachmentRoublePriceToBeTaken
|
||||||
|
)
|
||||||
.Count(_ => RollForDelete(traderId) ?? false);
|
.Count(_ => RollForDelete(traderId) ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +637,12 @@ 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 (traderDialogMessages.TryGetValue("insuranceFailed", out var insuranceFailedTemplates))
|
if (
|
||||||
|
traderDialogMessages.TryGetValue(
|
||||||
|
"insuranceFailed",
|
||||||
|
out var insuranceFailedTemplates
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
insurance.MessageTemplateId = _randomUtil.GetArrayValue(insuranceFailedTemplates);
|
insurance.MessageTemplateId = _randomUtil.GetArrayValue(insuranceFailedTemplates);
|
||||||
}
|
}
|
||||||
@@ -615,8 +668,15 @@ 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(insurance.SystemData?.Location, labsId, StringComparison.OrdinalIgnoreCase) &&
|
return string.Equals(
|
||||||
!(_databaseService.GetLocation(labsId)?.Base?.Insurance.GetValueOrDefault(false) ?? false);
|
insurance.SystemData?.Location,
|
||||||
|
labsId,
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
&& !(
|
||||||
|
_databaseService.GetLocation(labsId)?.Base?.Insurance.GetValueOrDefault(false)
|
||||||
|
?? false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -625,10 +685,20 @@ public class InsuranceController(
|
|||||||
/// <param name="insurance">The insured items to process</param>
|
/// <param name="insurance">The insured items to process</param>
|
||||||
/// <param name="labsId">OPTIONAL - id of labs location</param>
|
/// <param name="labsId">OPTIONAL - id of labs location</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected bool IsMapLabyrinthAndInsuranceDisabled(Insurance insurance, string labyrinthId = "labyrinth")
|
protected bool IsMapLabyrinthAndInsuranceDisabled(
|
||||||
|
Insurance insurance,
|
||||||
|
string labyrinthId = "labyrinth"
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return string.Equals(insurance.SystemData?.Location, labyrinthId, StringComparison.OrdinalIgnoreCase) &&
|
return string.Equals(
|
||||||
!(_databaseService.GetLocation(labyrinthId)?.Base?.Insurance.GetValueOrDefault(false) ?? false);
|
insurance.SystemData?.Location,
|
||||||
|
labyrinthId,
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
&& !(
|
||||||
|
_databaseService.GetLocation(labyrinthId)?.Base?.Insurance.GetValueOrDefault(false)
|
||||||
|
?? false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -636,7 +706,10 @@ public class InsuranceController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="traderDialogMessages"></param>
|
/// <param name="traderDialogMessages"></param>
|
||||||
/// <param name="insurance"></param>
|
/// <param name="insurance"></param>
|
||||||
protected void HandleLabsInsurance(Dictionary<string, List<string>?>? traderDialogMessages, Insurance insurance)
|
protected void HandleLabsInsurance(
|
||||||
|
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
|
||||||
var responseMesageIds =
|
var responseMesageIds =
|
||||||
@@ -655,7 +728,10 @@ public class InsuranceController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="traderDialogMessages"></param>
|
/// <param name="traderDialogMessages"></param>
|
||||||
/// <param name="insurance"></param>
|
/// <param name="insurance"></param>
|
||||||
protected void HandleLabyrinthInsurance(Dictionary<string, List<string>?>? traderDialogMessages, Insurance insurance)
|
protected void HandleLabyrinthInsurance(
|
||||||
|
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
|
||||||
var responseMessageIds =
|
var responseMessageIds =
|
||||||
@@ -669,7 +745,6 @@ public class InsuranceController(
|
|||||||
insurance.Items = [];
|
insurance.Items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Roll for chance of item being 'lost'
|
/// Roll for chance of item being 'lost'
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -692,11 +767,15 @@ 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 ? $"{_itemHelper.GetItemName(insuredItem.Template)}" : "";
|
var itemName = insuredItem is not null
|
||||||
|
? $"{_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($"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}");
|
_logger.Debug(
|
||||||
|
$"Rolling {itemName} with {trader} - Return {traderReturnChance}% - Roll: {returnChance} - Status: {status}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return roll;
|
return roll;
|
||||||
@@ -709,7 +788,11 @@ 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(PmcData pmcData, InsureRequestData request, string sessionId)
|
public ItemEventRouterResponse Insure(
|
||||||
|
PmcData pmcData,
|
||||||
|
InsureRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionId);
|
var output = _eventOutputHolder.GetOutput(sessionId);
|
||||||
var itemsToInsureCount = request.Items.Count;
|
var itemsToInsureCount = request.Items.Count;
|
||||||
@@ -729,7 +812,7 @@ public class InsuranceController(
|
|||||||
pmcData,
|
pmcData,
|
||||||
inventoryItemsHash[key],
|
inventoryItemsHash[key],
|
||||||
request.TransactionId
|
request.TransactionId
|
||||||
)
|
),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -742,7 +825,7 @@ public class InsuranceController(
|
|||||||
Type = "",
|
Type = "",
|
||||||
ItemId = "",
|
ItemId = "",
|
||||||
Count = 0,
|
Count = 0,
|
||||||
SchemeId = 0
|
SchemeId = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// pay for the item insurance
|
// pay for the item insurance
|
||||||
@@ -757,20 +840,22 @@ public class InsuranceController(
|
|||||||
foreach (var key in request.Items)
|
foreach (var key in request.Items)
|
||||||
{
|
{
|
||||||
pmcData.InsuredItems.Add(
|
pmcData.InsuredItems.Add(
|
||||||
new InsuredItem
|
new InsuredItem { TId = request.TransactionId, ItemId = inventoryItemsHash[key].Id }
|
||||||
{
|
|
||||||
TId = request.TransactionId,
|
|
||||||
ItemId = inventoryItemsHash[key].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(inventoryItemsHash[key].Template))
|
if (
|
||||||
|
_itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(inventoryItemsHash[key].Template)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
InsureSoftInserts(inventoryItemsHash[key], pmcData, request);
|
InsureSoftInserts(inventoryItemsHash[key], pmcData, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_profileHelper.AddSkillPointsToPlayer(pmcData, SkillTypes.Charisma, itemsToInsureCount * 0.01);
|
_profileHelper.AddSkillPointsToPlayer(
|
||||||
|
pmcData,
|
||||||
|
SkillTypes.Charisma,
|
||||||
|
itemsToInsureCount * 0.01
|
||||||
|
);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -781,9 +866,15 @@ 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(Item itemWithSoftInserts, PmcData pmcData, InsureRequestData request)
|
public void InsureSoftInserts(
|
||||||
|
Item itemWithSoftInserts,
|
||||||
|
PmcData pmcData,
|
||||||
|
InsureRequestData request
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var softInsertSlots = pmcData.Inventory.Items.Where(item => item.ParentId == itemWithSoftInserts.Id && _itemHelper.IsSoftInsertId(item.SlotId.ToLower())
|
var softInsertSlots = pmcData.Inventory.Items.Where(item =>
|
||||||
|
item.ParentId == itemWithSoftInserts.Id
|
||||||
|
&& _itemHelper.IsSoftInsertId(item.SlotId.ToLower())
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (var softInsertSlot in softInsertSlots)
|
foreach (var softInsertSlot in softInsertSlots)
|
||||||
@@ -794,11 +885,7 @@ public class InsuranceController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pmcData.InsuredItems.Add(
|
pmcData.InsuredItems.Add(
|
||||||
new InsuredItem
|
new InsuredItem { TId = request.TransactionId, ItemId = softInsertSlot.Id }
|
||||||
{
|
|
||||||
TId = request.TransactionId,
|
|
||||||
ItemId = softInsertSlot.Id
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -830,7 +917,9 @@ public class InsuranceController(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Item with id: {itemId} missing from player inventory, skipping");
|
_logger.Debug(
|
||||||
|
$"Item with id: {itemId} missing from player inventory, skipping"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -838,7 +927,11 @@ public class InsuranceController(
|
|||||||
|
|
||||||
items.TryAdd(
|
items.TryAdd(
|
||||||
inventoryItemsHash[itemId].Template,
|
inventoryItemsHash[itemId].Template,
|
||||||
_insuranceService.GetRoublePriceToInsureItemWithTrader(pmcData, inventoryItemsHash[itemId], trader)
|
_insuranceService.GetRoublePriceToInsureItemWithTrader(
|
||||||
|
pmcData,
|
||||||
|
inventoryItemsHash[itemId],
|
||||||
|
trader
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,12 @@ 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(PmcData pmcData, InventoryMoveRequestData moveRequest, string sessionId,
|
public void MoveItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryMoveRequestData moveRequest,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -57,18 +61,27 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var ownerInventoryItems = _inventoryHelper.GetOwnerInventoryItems(moveRequest, moveRequest.Item, sessionId);
|
var ownerInventoryItems = _inventoryHelper.GetOwnerInventoryItems(
|
||||||
|
moveRequest,
|
||||||
|
moveRequest.Item,
|
||||||
|
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 (moveRequest.FromOwner?.Type == "Trader" && !ownerInventoryItems.IsMail.GetValueOrDefault(false))
|
if (
|
||||||
|
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 => item.Id == moveRequest.Item);
|
var originalItemLocation = ownerInventoryItems.From?.FirstOrDefault(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
|
||||||
@@ -91,9 +104,19 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Item is moving into or out of place of fame dog tag slot
|
// Item is moving into or out of place of fame dog tag slot
|
||||||
if (moveRequest.To?.Container != null &&
|
if (
|
||||||
(moveRequest.To.Container.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase) ||
|
moveRequest.To?.Container != null
|
||||||
originalLocationSlotId.StartsWith("dogtag", StringComparison.OrdinalIgnoreCase)))
|
&& (
|
||||||
|
moveRequest.To.Container.StartsWith(
|
||||||
|
"dogtag",
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
|| originalLocationSlotId.StartsWith(
|
||||||
|
"dogtag",
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_hideoutHelper.ApplyPlaceOfFameDogtagBonus(pmcData);
|
_hideoutHelper.ApplyPlaceOfFameDogtagBonus(pmcData);
|
||||||
}
|
}
|
||||||
@@ -129,13 +152,21 @@ 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(PmcData pmcData, PinOrLockItemRequest request, string sessionId,
|
public void PinOrLock(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
PinOrLockItemRequest request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item => item.Id == request.Item);
|
var itemToAdjust = pmcData.Inventory!.Items!.FirstOrDefault(item =>
|
||||||
|
item.Id == request.Item
|
||||||
|
);
|
||||||
if (itemToAdjust is null)
|
if (itemToAdjust is null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Unable find item: {request.Item} to: {request.State} on player {sessionId}to: ");
|
_logger.Error(
|
||||||
|
$"Unable find item: {request.Item} to: {request.State} on player {sessionId}to: "
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -165,7 +196,11 @@ 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(PmcData pmcData, RedeemProfileRequestData request, string sessionId)
|
public void RedeemProfileReward(
|
||||||
|
PmcData pmcData,
|
||||||
|
RedeemProfileRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var fullProfile = _profileHelper.GetFullProfile(sessionId);
|
var fullProfile = _profileHelper.GetFullProfile(sessionId);
|
||||||
foreach (var rewardEvent in request.Events)
|
foreach (var rewardEvent in request.Events)
|
||||||
@@ -173,21 +208,28 @@ 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 => message.Id == rewardEvent.MessageId);
|
var mail = dialog.Messages.FirstOrDefault(message =>
|
||||||
var mailEvent =
|
message.Id == rewardEvent.MessageId
|
||||||
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($"Set trader {mailEvent.Entity}: Sales Sum to: {mailEvent.Value}");
|
_logger.Success(
|
||||||
|
$"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($"Set trader {mailEvent.Entity}: Standing to: {mailEvent.Value}");
|
_logger.Success(
|
||||||
|
$"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;
|
||||||
@@ -197,7 +239,9 @@ public class InventoryController(
|
|||||||
break;
|
break;
|
||||||
case "SkillPoints":
|
case "SkillPoints":
|
||||||
{
|
{
|
||||||
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x => x.Id == Enum.Parse<SkillTypes>(mailEvent.Entity));
|
var profileSkill = pmcData.Skills.Common.FirstOrDefault(x =>
|
||||||
|
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}");
|
||||||
@@ -233,7 +277,9 @@ 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 => area.Type == hideoutAreaType);
|
var desiredArea = pmcData.Hideout.Areas.FirstOrDefault(area =>
|
||||||
|
area.Type == hideoutAreaType
|
||||||
|
);
|
||||||
if (desiredArea is not null)
|
if (desiredArea is not null)
|
||||||
{
|
{
|
||||||
desiredArea.Level = (int?)newValue;
|
desiredArea.Level = (int?)newValue;
|
||||||
@@ -254,7 +300,10 @@ 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(IEnumerable<string> itemTpls, SptProfile fullProfile)
|
protected void FlagItemsAsInspectedAndRewardXp(
|
||||||
|
IEnumerable<string> itemTpls,
|
||||||
|
SptProfile fullProfile
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var itemTpl in itemTpls)
|
foreach (var itemTpl in itemTpls)
|
||||||
{
|
{
|
||||||
@@ -262,16 +311,23 @@ public class InventoryController(
|
|||||||
if (!item.Key)
|
if (!item.Key)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("inventory-unable_to_inspect_item_not_in_db", itemTpl)
|
_localisationService.GetText(
|
||||||
|
"inventory-unable_to_inspect_item_not_in_db",
|
||||||
|
itemTpl
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fullProfile.CharacterData.PmcData.Info.Experience += item.Value.Properties.ExamineExperience;
|
fullProfile.CharacterData.PmcData.Info.Experience += item.Value
|
||||||
|
.Properties
|
||||||
|
.ExamineExperience;
|
||||||
fullProfile.CharacterData.PmcData.Encyclopedia[itemTpl] = false;
|
fullProfile.CharacterData.PmcData.Encyclopedia[itemTpl] = false;
|
||||||
|
|
||||||
fullProfile.CharacterData.ScavData.Info.Experience += item.Value.Properties.ExamineExperience;
|
fullProfile.CharacterData.ScavData.Info.Experience += item.Value
|
||||||
|
.Properties
|
||||||
|
.ExamineExperience;
|
||||||
fullProfile.CharacterData.ScavData.Encyclopedia[itemTpl] = false;
|
fullProfile.CharacterData.ScavData.Encyclopedia[itemTpl] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,8 +347,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>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void OpenRandomLootContainer(PmcData pmcData, OpenRandomLootContainerRequestData request, string sessionId,
|
public void OpenRandomLootContainer(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
OpenRandomLootContainerRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Container player opened in their inventory
|
// Container player opened in their inventory
|
||||||
var openedItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
|
var openedItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == request.Item);
|
||||||
@@ -305,7 +365,7 @@ public class InventoryController(
|
|||||||
{
|
{
|
||||||
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_VIOLET_OPEN,
|
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_VIOLET_OPEN,
|
||||||
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_BLUE_OPEN,
|
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_BLUE_OPEN,
|
||||||
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_GREEN_OPEN
|
ItemTpl.RANDOMLOOTCONTAINER_ARENA_WEAPONCRATE_GREEN_OPEN,
|
||||||
};
|
};
|
||||||
// Temp fix for unlocked weapon crate hideout craft
|
// Temp fix for unlocked weapon crate hideout craft
|
||||||
if (isSealedWeaponBox || unlockedWeaponCrates.Contains(containerDetailsDb.Value.Id))
|
if (isSealedWeaponBox || unlockedWeaponCrates.Contains(containerDetailsDb.Value.Id))
|
||||||
@@ -320,10 +380,14 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var rewardContainerDetails = _inventoryHelper.GetRandomLootContainerRewardDetails(openedItem.Template);
|
var rewardContainerDetails = _inventoryHelper.GetRandomLootContainerRewardDetails(
|
||||||
|
openedItem.Template
|
||||||
|
);
|
||||||
if (rewardContainerDetails?.RewardCount == null)
|
if (rewardContainerDetails?.RewardCount == null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Unable to add loot to container: {openedItem.Template}, no rewards found");
|
_logger.Error(
|
||||||
|
$"Unable to add loot to container: {openedItem.Template}, no rewards found"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -344,7 +408,7 @@ public class InventoryController(
|
|||||||
ItemsWithModsToAdd = rewards,
|
ItemsWithModsToAdd = rewards,
|
||||||
FoundInRaid = foundInRaid,
|
FoundInRaid = foundInRaid,
|
||||||
Callback = null,
|
Callback = null,
|
||||||
UseSortingTable = true
|
UseSortingTable = true,
|
||||||
};
|
};
|
||||||
_inventoryHelper.AddItemsToStash(sessionId, addItemsRequest, pmcData, output);
|
_inventoryHelper.AddItemsToStash(sessionId, addItemsRequest, pmcData, output);
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
@@ -364,8 +428,12 @@ 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(PmcData pmcData, InventoryEditMarkerRequestData request, string sessionId,
|
public void EditMapMarker(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryEditMarkerRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var mapItem = _mapMarkerService.EditMarkerOnMap(pmcData, request);
|
var mapItem = _mapMarkerService.EditMarkerOnMap(pmcData, request);
|
||||||
|
|
||||||
@@ -380,8 +448,12 @@ public class InventoryController(
|
|||||||
/// <param name="request">Delete marker request</param>
|
/// <param name="request">Delete 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 DeleteMapMarker(PmcData pmcData, InventoryDeleteMarkerRequestData request, string sessionId,
|
public void DeleteMapMarker(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryDeleteMarkerRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var mapItem = _mapMarkerService.DeleteMarkerFromMap(pmcData, request);
|
var mapItem = _mapMarkerService.DeleteMarkerFromMap(pmcData, request);
|
||||||
|
|
||||||
@@ -389,8 +461,12 @@ public class InventoryController(
|
|||||||
output.ProfileChanges[sessionId].Items.ChangedItems.Add(mapItem);
|
output.ProfileChanges[sessionId].Items.ChangedItems.Add(mapItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateMapMarker(PmcData pmcData, InventoryCreateMarkerRequestData request, string sessionId,
|
public void CreateMapMarker(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryCreateMarkerRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var adjustedMapItem = _mapMarkerService.CreateMarkerOnMap(pmcData, request);
|
var adjustedMapItem = _mapMarkerService.CreateMarkerOnMap(pmcData, request);
|
||||||
|
|
||||||
@@ -405,16 +481,25 @@ 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(PmcData pmcData, InventorySortRequestData request, string sessionId,
|
public void SortInventory(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventorySortRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var change in request.ChangedItems)
|
foreach (var change in request.ChangedItems)
|
||||||
{
|
{
|
||||||
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item => item.Id == change.Id);
|
var inventoryItem = pmcData.Inventory.Items.FirstOrDefault(item =>
|
||||||
|
item.Id == change.Id
|
||||||
|
);
|
||||||
if (inventoryItem is null)
|
if (inventoryItem is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("inventory-unable_to_sort_inventory_restart_game", change.Id)
|
_localisationService.GetText(
|
||||||
|
"inventory-unable_to_sort_inventory_restart_game",
|
||||||
|
change.Id
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -440,8 +525,11 @@ 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(PmcData pmcData, InventoryReadEncyclopediaRequestData request,
|
public ItemEventRouterResponse ReadEncyclopedia(
|
||||||
string sessionId)
|
PmcData pmcData,
|
||||||
|
InventoryReadEncyclopediaRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var id in request.Ids)
|
foreach (var id in request.Ids)
|
||||||
{
|
{
|
||||||
@@ -458,8 +546,12 @@ 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(PmcData pmcData, InventoryExamineRequestData request, string sessionId,
|
public void ExamineItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryExamineRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
string? itemId = null;
|
string? itemId = null;
|
||||||
if (request.FromOwner is not null)
|
if (request.FromOwner is not null)
|
||||||
@@ -470,7 +562,12 @@ public class InventoryController(
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("inventory-examine_item_does_not_exist", request.Item));
|
_logger.Error(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"inventory-examine_item_does_not_exist",
|
||||||
|
request.Item
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +613,10 @@ 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.GetRawFenceAssorts().Items.FirstOrDefault(x => x.Id == request.Item)?.Template;
|
return _fenceService
|
||||||
|
.GetRawFenceAssorts()
|
||||||
|
.Items.FirstOrDefault(x => x.Id == request.Item)
|
||||||
|
?.Template;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.FromOwner.Type == "Trader")
|
if (request.FromOwner.Type == "Trader")
|
||||||
@@ -539,18 +639,23 @@ 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 = _ragfairOfferService.GetOfferByOfferId(request.Item) ??
|
var offer =
|
||||||
_ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id);
|
_ragfairOfferService.GetOfferByOfferId(request.Item)
|
||||||
|
?? _ragfairOfferService.GetOfferByOfferId(request.FromOwner.Id);
|
||||||
|
|
||||||
// Try find examine item inside offer items array
|
// Try find examine item inside offer items array
|
||||||
var matchingItem = offer.Items.FirstOrDefault(offerItem => offerItem.Id == request.Item);
|
var matchingItem = offer.Items.FirstOrDefault(offerItem =>
|
||||||
|
offerItem.Id == request.Item
|
||||||
|
);
|
||||||
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(_localisationService.GetText("inventory-unable_to_find_item", request.Item));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("inventory-unable_to_find_item", request.Item)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get hideout item
|
// get hideout item
|
||||||
@@ -565,7 +670,9 @@ 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 => x.Value.Messages.Any(m => m.Id == request.FromOwner.Id));
|
var dialogue = mail.FirstOrDefault(x =>
|
||||||
|
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
|
||||||
@@ -590,8 +697,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>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
public void UnBindItem(PmcData pmcData, InventoryBindRequestData request, string sessionId,
|
public void UnBindItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryBindRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Remove kvp from requested fast panel index
|
// Remove kvp from requested fast panel index
|
||||||
|
|
||||||
@@ -607,8 +718,12 @@ 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(PmcData pmcData, InventoryBindRequestData bindRequest, string sessionId,
|
public void BindItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryBindRequestData bindRequest,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Remove link
|
// Remove link
|
||||||
if (pmcData.Inventory.FastPanel.ContainsKey(bindRequest.Index))
|
if (pmcData.Inventory.FastPanel.ContainsKey(bindRequest.Index))
|
||||||
@@ -627,7 +742,11 @@ 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(PmcData pmcData, InventoryTagRequestData request, string sessionId)
|
public ItemEventRouterResponse TagItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryTagRequestData request,
|
||||||
|
string 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)
|
||||||
@@ -636,20 +755,13 @@ public class InventoryController(
|
|||||||
$"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
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
{
|
|
||||||
Warnings = []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Null guard
|
// Null guard
|
||||||
itemToTag.Upd ??= new Upd();
|
itemToTag.Upd ??= new Upd();
|
||||||
|
|
||||||
itemToTag.Upd.Tag = new UpdTag
|
itemToTag.Upd.Tag = new UpdTag { Color = request.TagColor, Name = request.TagName };
|
||||||
{
|
|
||||||
Color = request.TagColor,
|
|
||||||
Name = request.TagName
|
|
||||||
};
|
|
||||||
|
|
||||||
return _eventOutputHolder.GetOutput(sessionId);
|
return _eventOutputHolder.GetOutput(sessionId);
|
||||||
}
|
}
|
||||||
@@ -661,7 +773,11 @@ 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(PmcData pmcData, InventoryToggleRequestData request, string sessionId)
|
public ItemEventRouterResponse ToggleItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryToggleRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// May need to reassign to scav profile
|
// May need to reassign to scav profile
|
||||||
var playerData = pmcData;
|
var playerData = pmcData;
|
||||||
@@ -677,23 +793,22 @@ public class InventoryController(
|
|||||||
{
|
{
|
||||||
_itemHelper.AddUpdObjectToItem(
|
_itemHelper.AddUpdObjectToItem(
|
||||||
itemToToggle,
|
itemToToggle,
|
||||||
_localisationService.GetText("inventory-item_to_toggle_missing_upd", itemToToggle.Id)
|
_localisationService.GetText(
|
||||||
|
"inventory-item_to_toggle_missing_upd",
|
||||||
|
itemToToggle.Id
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
itemToToggle.Upd.Togglable = new UpdTogglable
|
itemToToggle.Upd.Togglable = new UpdTogglable { On = request.Value };
|
||||||
{
|
|
||||||
On = request.Value
|
|
||||||
};
|
|
||||||
|
|
||||||
return _eventOutputHolder.GetOutput(sessionId);
|
return _eventOutputHolder.GetOutput(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Warning(_localisationService.GetText("inventory-unable_to_toggle_item_not_found", request.Item));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("inventory-unable_to_toggle_item_not_found", request.Item)
|
||||||
|
);
|
||||||
|
|
||||||
return new ItemEventRouterResponse
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
{
|
|
||||||
Warnings = []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -703,7 +818,11 @@ 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(PmcData pmcData, InventoryFoldRequestData request, string sessionId)
|
public ItemEventRouterResponse FoldItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventoryFoldRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// May need to reassign to scav profile
|
// May need to reassign to scav profile
|
||||||
var playerData = pmcData;
|
var playerData = pmcData;
|
||||||
@@ -714,27 +833,26 @@ public class InventoryController(
|
|||||||
playerData = _profileHelper.GetScavProfile(sessionId);
|
playerData = _profileHelper.GetScavProfile(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemToFold = playerData.Inventory.Items.FirstOrDefault(item => item?.Id == request.Item);
|
var itemToFold = playerData.Inventory.Items.FirstOrDefault(item =>
|
||||||
|
item?.Id == request.Item
|
||||||
|
);
|
||||||
if (itemToFold is null)
|
if (itemToFold is null)
|
||||||
{
|
{
|
||||||
// Item not found
|
// Item not found
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("inventory-unable_to_fold_item_not_found_in_inventory", request.Item)
|
_localisationService.GetText(
|
||||||
|
"inventory-unable_to_fold_item_not_found_in_inventory",
|
||||||
|
request.Item
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return new ItemEventRouterResponse
|
return new ItemEventRouterResponse { Warnings = [] };
|
||||||
{
|
|
||||||
Warnings = []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item may not have upd object
|
// Item may not have upd object
|
||||||
_itemHelper.AddUpdObjectToItem(itemToFold);
|
_itemHelper.AddUpdObjectToItem(itemToFold);
|
||||||
|
|
||||||
itemToFold.Upd.Foldable = new UpdFoldable
|
itemToFold.Upd.Foldable = new UpdFoldable { Folded = request.Value };
|
||||||
{
|
|
||||||
Folded = request.Value
|
|
||||||
};
|
|
||||||
|
|
||||||
return _eventOutputHolder.GetOutput(sessionId);
|
return _eventOutputHolder.GetOutput(sessionId);
|
||||||
}
|
}
|
||||||
@@ -748,7 +866,11 @@ 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(PmcData pmcData, InventorySwapRequestData request, string sessionId)
|
public ItemEventRouterResponse SwapItem(
|
||||||
|
PmcData pmcData,
|
||||||
|
InventorySwapRequestData request,
|
||||||
|
string 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;
|
||||||
@@ -763,11 +885,7 @@ public class InventoryController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"inventory-unable_to_find_item_to_swap",
|
"inventory-unable_to_find_item_to_swap",
|
||||||
new
|
new { item1Id = request.Item, item2Id = request.Item2 }
|
||||||
{
|
|
||||||
item1Id = request.Item,
|
|
||||||
item2Id = request.Item2
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -778,11 +896,7 @@ public class InventoryController(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"inventory-unable_to_find_item_to_swap",
|
"inventory-unable_to_find_item_to_swap",
|
||||||
new
|
new { item1Id = request.Item2, item2Id = request.Item }
|
||||||
{
|
|
||||||
item1Id = request.Item2,
|
|
||||||
item2Id = request.Item
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -827,11 +941,19 @@ 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(PmcData pmcData, InventoryTransferRequestData request, string sessionId,
|
public void TransferItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryTransferRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// TODO - check GetOwnerInventoryItems() call still works
|
// TODO - check GetOwnerInventoryItems() call still works
|
||||||
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionId);
|
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -855,10 +977,7 @@ public class InventoryController(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceItem.Upd ??= new Upd
|
sourceItem.Upd ??= new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
var sourceStackCount = sourceItem.Upd.StackObjectsCount;
|
var sourceStackCount = sourceItem.Upd.StackObjectsCount;
|
||||||
if (sourceStackCount > request.Count)
|
if (sourceStackCount > request.Count)
|
||||||
@@ -872,10 +991,7 @@ public class InventoryController(
|
|||||||
sourceItem.Upd.StackObjectsCount = sourceStackCount - 1;
|
sourceItem.Upd.StackObjectsCount = sourceStackCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
destinationItem.Upd ??= new Upd
|
destinationItem.Upd ??= new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
var destinationStackCount = destinationItem.Upd.StackObjectsCount;
|
var destinationStackCount = destinationItem.Upd.StackObjectsCount;
|
||||||
destinationItem.Upd.StackObjectsCount = destinationStackCount + request.Count;
|
destinationItem.Upd.StackObjectsCount = destinationStackCount + request.Count;
|
||||||
@@ -889,17 +1005,26 @@ 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(PmcData pmcData, InventoryMergeRequestData request, string sessionID,
|
public void MergeItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryMergeRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.Item, sessionID);
|
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
|
||||||
|
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 = $"Unable to merge stacks as source item: {request.With} cannot be found";
|
var errorMessage =
|
||||||
|
$"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);
|
||||||
@@ -911,7 +1036,8 @@ 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 = $"Unable to merge stacks as destination item: {request.With} cannot be found";
|
var errorMessage =
|
||||||
|
$"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);
|
||||||
@@ -922,18 +1048,12 @@ public class InventoryController(
|
|||||||
if (destinationItem.Upd?.StackObjectsCount is null)
|
if (destinationItem.Upd?.StackObjectsCount is null)
|
||||||
// No stackcount on destination, add one
|
// No stackcount on destination, add one
|
||||||
{
|
{
|
||||||
destinationItem.Upd = new Upd
|
destinationItem.Upd = new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourceItem.Upd is null)
|
if (sourceItem.Upd is null)
|
||||||
{
|
{
|
||||||
sourceItem.Upd = new Upd
|
sourceItem.Upd = new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else if (sourceItem.Upd.StackObjectsCount is null)
|
else if (sourceItem.Upd.StackObjectsCount is null)
|
||||||
// Items pulled out of raid can have no stack count if the stack should be 1
|
// Items pulled out of raid can have no stack count if the stack should be 1
|
||||||
@@ -942,26 +1062,22 @@ 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 (!sourceItem.Upd.SpawnedInSession.GetValueOrDefault(false) &&
|
if (
|
||||||
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 +=
|
destinationItem.Upd.StackObjectsCount += sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
|
||||||
sourceItem.Upd.StackObjectsCount; // Add source stackcount to destination
|
output.ProfileChanges[sessionID].Items.DeletedItems.Add(new Item { Id = sourceItem.Id }); // Inform client source item being deleted
|
||||||
output.ProfileChanges[sessionID]
|
|
||||||
.Items.DeletedItems.Add(
|
|
||||||
new Item
|
|
||||||
{
|
|
||||||
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 = $"Unable to find item: {sourceItem.Id} to remove from sender inventory";
|
var errorMessage =
|
||||||
|
$"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);
|
||||||
@@ -979,11 +1095,19 @@ 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(PmcData pmcData, InventorySplitRequestData request, string sessionID,
|
public void SplitItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventorySplitRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Changes made to result apply to character inventory
|
// Changes made to result apply to character inventory
|
||||||
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(request, request.NewItem, sessionID);
|
var inventoryItems = _inventoryHelper.GetOwnerInventoryItems(
|
||||||
|
request,
|
||||||
|
request.NewItem,
|
||||||
|
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")
|
||||||
@@ -996,7 +1120,8 @@ 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 = $"Unable to split stack as source item: {request.SplitItem} cannot be found";
|
var errorMessage =
|
||||||
|
$"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);
|
||||||
@@ -1012,13 +1137,14 @@ public class InventoryController(
|
|||||||
itemToSplit.Upd.StackObjectsCount -= request.Count;
|
itemToSplit.Upd.StackObjectsCount -= request.Count;
|
||||||
|
|
||||||
// Inform client of change
|
// Inform client of change
|
||||||
output.ProfileChanges[sessionID]
|
output
|
||||||
|
.ProfileChanges[sessionID]
|
||||||
.Items.NewItems.Add(
|
.Items.NewItems.Add(
|
||||||
new Item
|
new Item
|
||||||
{
|
{
|
||||||
Id = request.NewItem,
|
Id = request.NewItem,
|
||||||
Template = itemToSplit.Template,
|
Template = itemToSplit.Template,
|
||||||
Upd = updatedUpd
|
Upd = updatedUpd,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1031,7 +1157,7 @@ public class InventoryController(
|
|||||||
ParentId = request.Container.Id,
|
ParentId = request.Container.Id,
|
||||||
SlotId = request.Container.ContainerName,
|
SlotId = request.Container.ContainerName,
|
||||||
Location = request.Container.Location,
|
Location = request.Container.Location,
|
||||||
Upd = updatedUpd
|
Upd = updatedUpd,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1044,8 +1170,12 @@ 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(PmcData pmcData, InventoryRemoveRequestData request, string sessionId,
|
public void DiscardItem(
|
||||||
ItemEventRouterResponse output)
|
PmcData pmcData,
|
||||||
|
InventoryRemoveRequestData request,
|
||||||
|
string sessionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (request.FromOwner?.Type == "Mail")
|
if (request.FromOwner?.Type == "Mail")
|
||||||
{
|
{
|
||||||
@@ -1054,7 +1184,8 @@ public class InventoryController(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var profileToRemoveItemFrom = request.FromOwner is null || request.FromOwner?.Id == pmcData.Id
|
var profileToRemoveItemFrom =
|
||||||
|
request.FromOwner is null || request.FromOwner?.Id == pmcData.Id
|
||||||
? pmcData
|
? pmcData
|
||||||
: _profileHelper.GetFullProfile(sessionId).CharacterData.ScavData;
|
: _profileHelper.GetFullProfile(sessionId).CharacterData.ScavData;
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,11 @@ public class LauncherController(
|
|||||||
public ConnectResponse Connect()
|
public ConnectResponse Connect()
|
||||||
{
|
{
|
||||||
// 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.GetProfileTemplates()
|
var profileTemplates = _databaseService
|
||||||
.Where(profile => !_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key))
|
.GetProfileTemplates()
|
||||||
|
.Where(profile =>
|
||||||
|
!_coreConfig.Features.CreateNewProfileTypesBlacklist.Contains(profile.Key)
|
||||||
|
)
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
|
|
||||||
return new ConnectResponse
|
return new ConnectResponse
|
||||||
@@ -46,7 +49,7 @@ public class LauncherController(
|
|||||||
BackendUrl = _httpServerHelper.GetBackendUrl(),
|
BackendUrl = _httpServerHelper.GetBackendUrl(),
|
||||||
Name = _coreConfig.ServerName,
|
Name = _coreConfig.ServerName,
|
||||||
Editions = profileTemplates.Select(x => x.Key).ToList(),
|
Editions = profileTemplates.Select(x => x.Key).ToList(),
|
||||||
ProfileDescriptions = GetProfileDescriptions(profileTemplates)
|
ProfileDescriptions = GetProfileDescriptions(profileTemplates),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +58,9 @@ 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(Dictionary<string, ProfileSides> profileTemplates)
|
protected Dictionary<string, string> GetProfileDescriptions(
|
||||||
|
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)
|
||||||
@@ -72,7 +77,11 @@ public class LauncherController(
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Info? Find(string? sessionId)
|
public Info? Find(string? sessionId)
|
||||||
{
|
{
|
||||||
return sessionId is not null && _saveServer.GetProfiles().TryGetValue(sessionId, out var profile) ? profile.ProfileInfo : null;
|
return
|
||||||
|
sessionId is not null
|
||||||
|
&& _saveServer.GetProfiles().TryGetValue(sessionId, out var profile)
|
||||||
|
? profile.ProfileInfo
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -126,7 +135,7 @@ public class LauncherController(
|
|||||||
Username = info.Username,
|
Username = info.Username,
|
||||||
Password = info.Password,
|
Password = info.Password,
|
||||||
IsWiped = true,
|
IsWiped = true,
|
||||||
Edition = info.Edition
|
Edition = info.Edition,
|
||||||
};
|
};
|
||||||
_saveServer.CreateProfile(newProfileDetails);
|
_saveServer.CreateProfile(newProfileDetails);
|
||||||
|
|
||||||
@@ -229,7 +238,10 @@ 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(sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD", sptMod => sptMod.ModMetadata);
|
return _loadedMods.ToDictionary(
|
||||||
|
sptMod => sptMod.ModMetadata?.Name ?? "UNKNOWN MOD",
|
||||||
|
sptMod => sptMod.ModMetadata
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -48,7 +48,10 @@ public class LauncherV2Controller(
|
|||||||
|
|
||||||
foreach (var profileKvP in dbProfiles)
|
foreach (var profileKvP in dbProfiles)
|
||||||
{
|
{
|
||||||
result.TryAdd(profileKvP.Key, _localisationService.GetText(profileKvP.Value.DescriptionLocaleKey));
|
result.TryAdd(
|
||||||
|
profileKvP.Key,
|
||||||
|
_localisationService.GetText(profileKvP.Value.DescriptionLocaleKey)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -174,7 +177,7 @@ public class LauncherV2Controller(
|
|||||||
Username = info.Username,
|
Username = info.Username,
|
||||||
Password = info.Password,
|
Password = info.Password,
|
||||||
IsWiped = true,
|
IsWiped = true,
|
||||||
Edition = info.Edition
|
Edition = info.Edition,
|
||||||
};
|
};
|
||||||
|
|
||||||
_saveServer.CreateProfile(newProfileDetails);
|
_saveServer.CreateProfile(newProfileDetails);
|
||||||
@@ -204,7 +207,10 @@ public class LauncherV2Controller(
|
|||||||
{
|
{
|
||||||
foreach (var profile in _saveServer.GetProfiles())
|
foreach (var profile in _saveServer.GetProfiles())
|
||||||
{
|
{
|
||||||
if (info.Username == profile.Value.ProfileInfo!.Username && info.Password == profile.Value.ProfileInfo.Password)
|
if (
|
||||||
|
info.Username == profile.Value.ProfileInfo!.Username
|
||||||
|
&& info.Password == profile.Value.ProfileInfo.Password
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return profile.Key;
|
return profile.Key;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using SPTarkov.Server.Core.Services;
|
|||||||
using SPTarkov.Server.Core.Utils.Cloners;
|
using SPTarkov.Server.Core.Utils.Cloners;
|
||||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||||
|
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
@@ -54,7 +53,7 @@ public class LocationController(
|
|||||||
return new LocationsGenerateAllResponse
|
return new LocationsGenerateAllResponse
|
||||||
{
|
{
|
||||||
Locations = locationResult,
|
Locations = locationResult,
|
||||||
Paths = locationsFromDb.Base!.Paths
|
Paths = locationsFromDb.Base!.Paths,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ public class MatchController(
|
|||||||
RaidMode = "Online",
|
RaidMode = "Online",
|
||||||
Mode = "deathmatch",
|
Mode = "deathmatch",
|
||||||
ShortId = null,
|
ShortId = null,
|
||||||
AdditionalInfo = null
|
AdditionalInfo = null,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@@ -85,11 +85,7 @@ public class MatchController(
|
|||||||
/// <returns>MatchGroupStatusResponse</returns>
|
/// <returns>MatchGroupStatusResponse</returns>
|
||||||
public MatchGroupStatusResponse GetGroupStatus(MatchGroupStatusRequest request)
|
public MatchGroupStatusResponse GetGroupStatus(MatchGroupStatusRequest request)
|
||||||
{
|
{
|
||||||
return new MatchGroupStatusResponse
|
return new MatchGroupStatusResponse { Players = [], MaxPveCountExceeded = false };
|
||||||
{
|
|
||||||
Players = [],
|
|
||||||
MaxPveCountExceeded = false
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -138,7 +134,10 @@ 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(string sessionId, StartLocalRaidRequestData request)
|
public StartLocalRaidResponseData StartLocalRaid(
|
||||||
|
string sessionId,
|
||||||
|
StartLocalRaidRequestData request
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _locationLifecycleService.StartLocalRaid(sessionId, request);
|
return _locationLifecycleService.StartLocalRaid(sessionId, request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ using SPTarkov.Server.Core.Routers;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class NoteController(
|
public class NoteController(EventOutputHolder _eventOutputHolder)
|
||||||
EventOutputHolder _eventOutputHolder
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -20,13 +18,10 @@ public class NoteController(
|
|||||||
public ItemEventRouterResponse AddNote(
|
public ItemEventRouterResponse AddNote(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
NoteActionRequest request,
|
NoteActionRequest request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var newNote = new Note
|
var newNote = new Note { Time = request.Note.Time, Text = request.Note.Text };
|
||||||
{
|
|
||||||
Time = request.Note.Time,
|
|
||||||
Text = request.Note.Text
|
|
||||||
};
|
|
||||||
pmcData.Notes.DataNotes.Add(newNote);
|
pmcData.Notes.DataNotes.Add(newNote);
|
||||||
|
|
||||||
return _eventOutputHolder.GetOutput(sessionId);
|
return _eventOutputHolder.GetOutput(sessionId);
|
||||||
@@ -41,7 +36,8 @@ public class NoteController(
|
|||||||
public ItemEventRouterResponse EditNote(
|
public ItemEventRouterResponse EditNote(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
NoteActionRequest request,
|
NoteActionRequest request,
|
||||||
string sessionId)
|
string 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;
|
||||||
@@ -59,7 +55,8 @@ public class NoteController(
|
|||||||
public ItemEventRouterResponse DeleteNote(
|
public ItemEventRouterResponse DeleteNote(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
NoteActionRequest request,
|
NoteActionRequest request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
pmcData.Notes?.DataNotes?.RemoveAt(request.Index!.Value);
|
pmcData.Notes?.DataNotes?.RemoveAt(request.Index!.Value);
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class NotifierController(
|
|||||||
ChannelId = sessionId,
|
ChannelId = sessionId,
|
||||||
Url = "",
|
Url = "",
|
||||||
NotifierServer = GetServer(sessionId),
|
NotifierServer = GetServer(sessionId),
|
||||||
WebSocket = _notifierHelper.GetWebSocketServer(sessionId)
|
WebSocket = _notifierHelper.GetWebSocketServer(sessionId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,7 @@ public class PresetController(
|
|||||||
|
|
||||||
// Get root items tpl
|
// Get root items tpl
|
||||||
var tpl = preset.Items.FirstOrDefault()?.Template;
|
var tpl = preset.Items.FirstOrDefault()?.Template;
|
||||||
result.TryAdd(tpl, new PresetCacheDetails
|
result.TryAdd(tpl, new PresetCacheDetails { PresetIds = [] });
|
||||||
{
|
|
||||||
PresetIds = []
|
|
||||||
});
|
|
||||||
|
|
||||||
result.TryGetValue(tpl, out var details);
|
result.TryGetValue(tpl, out var details);
|
||||||
details.PresetIds.Add(presetId);
|
details.PresetIds.Add(presetId);
|
||||||
|
|||||||
@@ -23,8 +23,7 @@ public class PrestigeController(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sessionId">Session/Player id</param>
|
/// <param name="sessionId">Session/Player id</param>
|
||||||
/// <returns>Prestige</returns>
|
/// <returns>Prestige</returns>
|
||||||
public Prestige GetPrestige(
|
public Prestige GetPrestige(string sessionId)
|
||||||
string sessionId)
|
|
||||||
{
|
{
|
||||||
return _databaseService.GetTemplates().Prestige;
|
return _databaseService.GetTemplates().Prestige;
|
||||||
}
|
}
|
||||||
@@ -59,9 +58,7 @@ public class PrestigeController(
|
|||||||
/// </list>
|
/// </list>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task ObtainPrestige(
|
public async Task ObtainPrestige(string sessionId, ObtainPrestigeRequestList request)
|
||||||
string sessionId,
|
|
||||||
ObtainPrestigeRequestList request)
|
|
||||||
{
|
{
|
||||||
var profile = _profileHelper.GetFullProfile(sessionId);
|
var profile = _profileHelper.GetFullProfile(sessionId);
|
||||||
if (profile is not null)
|
if (profile is not null)
|
||||||
@@ -69,7 +66,7 @@ public class PrestigeController(
|
|||||||
var pendingPrestige = new PendingPrestige
|
var pendingPrestige = new PendingPrestige
|
||||||
{
|
{
|
||||||
PrestigeLevel = profile.CharacterData.PmcData.Info.PrestigeLevel + 1,
|
PrestigeLevel = profile.CharacterData.PmcData.Info.PrestigeLevel + 1,
|
||||||
Items = request
|
Items = request,
|
||||||
};
|
};
|
||||||
|
|
||||||
profile.SptData.PendingPrestige = pendingPrestige;
|
profile.SptData.PendingPrestige = pendingPrestige;
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ public class ProfileController(
|
|||||||
var profile = _saveServer.GetProfile(sessionId);
|
var profile = _saveServer.GetProfile(sessionId);
|
||||||
if (profile?.CharacterData == null)
|
if (profile?.CharacterData == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"Unable to find character data for id: {sessionId}. Profile may be corrupt");
|
throw new Exception(
|
||||||
|
$"Unable to find character data for id: {sessionId}. Profile may be corrupt"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmc = profile.CharacterData.PmcData;
|
var pmc = profile.CharacterData.PmcData;
|
||||||
@@ -81,7 +83,7 @@ public class ProfileController(
|
|||||||
MaxLevel = maxLvl,
|
MaxLevel = maxLvl,
|
||||||
Edition = profile.ProfileInfo?.Edition ?? "",
|
Edition = profile.ProfileInfo?.Edition ?? "",
|
||||||
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
|
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
|
||||||
SptData = _profileHelper.GetDefaultSptDataObject()
|
SptData = _profileHelper.GetDefaultSptDataObject(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +95,13 @@ 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 = currentLevel == 0 ? 0 : _profileHelper.GetExperience(currentLevel.Value),
|
PreviousExperience =
|
||||||
|
currentLevel == 0 ? 0 : _profileHelper.GetExperience(currentLevel.Value),
|
||||||
NextLevel = xpToNextLevel,
|
NextLevel = xpToNextLevel,
|
||||||
MaxLevel = maxLvl,
|
MaxLevel = maxLvl,
|
||||||
Edition = profile.ProfileInfo?.Edition ?? "",
|
Edition = profile.ProfileInfo?.Edition ?? "",
|
||||||
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
|
ProfileId = profile.ProfileInfo?.ProfileId ?? "",
|
||||||
SptData = profile.SptData
|
SptData = profile.SptData,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +121,10 @@ 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(ProfileCreateRequestData request, string sessionId)
|
public virtual async ValueTask<string> CreateProfile(
|
||||||
|
ProfileCreateRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return await _createProfileService.CreateProfile(sessionId, request);
|
return await _createProfileService.CreateProfile(sessionId, request);
|
||||||
}
|
}
|
||||||
@@ -140,7 +146,10 @@ 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(ValidateNicknameRequestData request, string sessionId)
|
public virtual NicknameValidationResult ValidateNickname(
|
||||||
|
ValidateNicknameRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (request.Nickname?.Length < 3)
|
if (request.Nickname?.Length < 3)
|
||||||
{
|
{
|
||||||
@@ -162,13 +171,13 @@ 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(ProfileChangeNicknameRequestData request, string sessionId)
|
public virtual NicknameValidationResult ChangeNickname(
|
||||||
|
ProfileChangeNicknameRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = ValidateNickname(
|
var output = ValidateNickname(
|
||||||
new ValidateNicknameRequestData
|
new ValidateNicknameRequestData { Nickname = request.Nickname },
|
||||||
{
|
|
||||||
Nickname = request.Nickname
|
|
||||||
},
|
|
||||||
sessionId
|
sessionId
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -200,7 +209,10 @@ 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(SearchProfilesRequestData request, string sessionID)
|
public virtual List<SearchFriendResponse> SearchProfiles(
|
||||||
|
SearchProfilesRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var result = new List<SearchFriendResponse>();
|
var result = new List<SearchFriendResponse>();
|
||||||
|
|
||||||
@@ -241,7 +253,7 @@ public class ProfileController(
|
|||||||
Status = "Free",
|
Status = "Free",
|
||||||
Sid = "",
|
Sid = "",
|
||||||
Ip = "",
|
Ip = "",
|
||||||
Port = 0
|
Port = 0,
|
||||||
},
|
},
|
||||||
new ProfileStatusData
|
new ProfileStatusData
|
||||||
{
|
{
|
||||||
@@ -250,9 +262,9 @@ public class ProfileController(
|
|||||||
Status = "Free",
|
Status = "Free",
|
||||||
Sid = "",
|
Sid = "",
|
||||||
Ip = "",
|
Ip = "",
|
||||||
Port = 0
|
Port = 0,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
@@ -264,13 +276,21 @@ 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(string sessionId, GetOtherProfileRequest request)
|
public virtual GetOtherProfileResponse GetOtherProfile(
|
||||||
|
string 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 (profileToView?.CharacterData?.PmcData is null || profileToView.CharacterData.ScavData is null)
|
if (
|
||||||
|
profileToView?.CharacterData?.PmcData is null
|
||||||
|
|| profileToView.CharacterData.ScavData is null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to get profile: {request.AccountId} to show, falling back to own profile");
|
_logger.Warning(
|
||||||
|
$"Unable to get profile: {request.AccountId} to show, falling back to own profile"
|
||||||
|
);
|
||||||
profileToView = _profileHelper.GetFullProfile(sessionId);
|
profileToView = _profileHelper.GetFullProfile(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,12 +303,17 @@ 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 => hideoutKeys.Contains(x.Id));
|
var hideoutRootItems = profileToViewPmc.Inventory.Items.Where(x =>
|
||||||
|
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 = _itemHelper.FindAndReturnChildrenAsItems(profileToViewPmc.Inventory.Items, rootItems.Id);
|
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(
|
||||||
|
profileToViewPmc.Inventory.Items,
|
||||||
|
rootItems.Id
|
||||||
|
);
|
||||||
itemsToReturn.AddRange(itemWithChildren);
|
itemsToReturn.AddRange(itemWithChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,10 +326,12 @@ 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)(profileToViewPmc.Info.MemberCategory ?? MemberCategory.Default),
|
MemberCategory = (int)(
|
||||||
|
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,
|
||||||
},
|
},
|
||||||
Customization = new OtherProfileCustomization
|
Customization = new OtherProfileCustomization
|
||||||
{
|
{
|
||||||
@@ -312,13 +339,13 @@ public class ProfileController(
|
|||||||
Body = profileToViewPmc.Customization.Body,
|
Body = profileToViewPmc.Customization.Body,
|
||||||
Feet = profileToViewPmc.Customization.Feet,
|
Feet = profileToViewPmc.Customization.Feet,
|
||||||
Hands = profileToViewPmc.Customization.Hands,
|
Hands = profileToViewPmc.Customization.Hands,
|
||||||
Dogtag = profileToViewPmc.Customization.DogTag
|
Dogtag = profileToViewPmc.Customization.DogTag,
|
||||||
},
|
},
|
||||||
Skills = profileToViewPmc.Skills,
|
Skills = profileToViewPmc.Skills,
|
||||||
Equipment = new OtherProfileEquipment
|
Equipment = new OtherProfileEquipment
|
||||||
{
|
{
|
||||||
Id = profileToViewPmc.Inventory.Equipment,
|
Id = profileToViewPmc.Inventory.Equipment,
|
||||||
Items = profileToViewPmc.Inventory.Items
|
Items = profileToViewPmc.Inventory.Items,
|
||||||
},
|
},
|
||||||
Achievements = profileToViewPmc.Achievements,
|
Achievements = profileToViewPmc.Achievements,
|
||||||
FavoriteItems = _profileHelper.GetOtherProfileFavorites(profileToViewPmc),
|
FavoriteItems = _profileHelper.GetOtherProfileFavorites(profileToViewPmc),
|
||||||
@@ -327,21 +354,21 @@ public class ProfileController(
|
|||||||
Eft = new OtherProfileSubStats
|
Eft = new OtherProfileSubStats
|
||||||
{
|
{
|
||||||
TotalInGameTime = profileToViewPmc.Stats.Eft.TotalInGameTime,
|
TotalInGameTime = profileToViewPmc.Stats.Eft.TotalInGameTime,
|
||||||
OverAllCounters = profileToViewPmc.Stats.Eft.OverallCounters
|
OverAllCounters = profileToViewPmc.Stats.Eft.OverallCounters,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
ScavStats = new OtherProfileStats
|
ScavStats = new OtherProfileStats
|
||||||
{
|
{
|
||||||
Eft = new OtherProfileSubStats
|
Eft = new OtherProfileSubStats
|
||||||
{
|
{
|
||||||
TotalInGameTime = profileToViewScav.Stats.Eft.TotalInGameTime,
|
TotalInGameTime = profileToViewScav.Stats.Eft.TotalInGameTime,
|
||||||
OverAllCounters = profileToViewScav.Stats.Eft.OverallCounters
|
OverAllCounters = profileToViewScav.Stats.Eft.OverallCounters,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
Hideout = profileToViewPmc.Hideout,
|
Hideout = profileToViewPmc.Hideout,
|
||||||
CustomizationStash = profileToViewPmc.Inventory.HideoutCustomizationStashId,
|
CustomizationStash = profileToViewPmc.Inventory.HideoutCustomizationStashId,
|
||||||
HideoutAreaStashes = profileToViewPmc.Inventory.HideoutAreaStashes,
|
HideoutAreaStashes = profileToViewPmc.Inventory.HideoutAreaStashes,
|
||||||
Items = itemsToReturn
|
Items = itemsToReturn,
|
||||||
};
|
};
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ using SPTarkov.Server.Core.Utils;
|
|||||||
using SPTarkov.Server.Core.Utils.Cloners;
|
using SPTarkov.Server.Core.Utils.Cloners;
|
||||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||||
|
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
@@ -63,13 +62,19 @@ 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(PmcData pmcData, AcceptQuestRequestData acceptedQuest, string sessionID)
|
public ItemEventRouterResponse AcceptQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
AcceptQuestRequestData acceptedQuest,
|
||||||
|
string 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 => x.QId == acceptedQuest.QuestId);
|
var existingQuestStatus = pmcData.Quests.FirstOrDefault(x =>
|
||||||
|
x.QId == acceptedQuest.QuestId
|
||||||
|
);
|
||||||
if (existingQuestStatus is not null)
|
if (existingQuestStatus is not null)
|
||||||
{
|
{
|
||||||
// Update existing
|
// Update existing
|
||||||
@@ -81,7 +86,11 @@ public class QuestController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add new quest to server profile
|
// Add new quest to server profile
|
||||||
var newQuest = _questHelper.GetQuestReadyForProfile(pmcData, QuestStatusEnum.Started, acceptedQuest);
|
var newQuest = _questHelper.GetQuestReadyForProfile(
|
||||||
|
pmcData,
|
||||||
|
QuestStatusEnum.Started,
|
||||||
|
acceptedQuest
|
||||||
|
);
|
||||||
pmcData.Quests.Add(newQuest);
|
pmcData.Quests.Add(newQuest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,10 +103,10 @@ public class QuestController(
|
|||||||
AddTaskConditionCountersToProfile(
|
AddTaskConditionCountersToProfile(
|
||||||
questFromDb.Conditions.AvailableForFinish,
|
questFromDb.Conditions.AvailableForFinish,
|
||||||
pmcData,
|
pmcData,
|
||||||
acceptedQuest.QuestId);
|
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.StartedMessageText,
|
||||||
@@ -120,7 +129,9 @@ public class QuestController(
|
|||||||
MessageType.QuestStart,
|
MessageType.QuestStart,
|
||||||
messageId,
|
messageId,
|
||||||
startedQuestRewardItems.ToList(),
|
startedQuestRewardItems.ToList(),
|
||||||
_timeUtil.GetHoursAsSeconds((int) _questHelper.GetMailItemRedeemTimeHoursForProfile(pmcData))
|
_timeUtil.GetHoursAsSeconds(
|
||||||
|
(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
|
||||||
@@ -142,7 +153,11 @@ public class QuestController(
|
|||||||
/// <param name="questConditions">Conditions to iterate over and possibly add to profile</param>
|
/// <param name="questConditions">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(List<QuestCondition> questConditions, PmcData pmcData, string questId)
|
protected void AddTaskConditionCountersToProfile(
|
||||||
|
List<QuestCondition> questConditions,
|
||||||
|
PmcData pmcData,
|
||||||
|
string questId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var condition in questConditions)
|
foreach (var condition in questConditions)
|
||||||
{
|
{
|
||||||
@@ -161,7 +176,7 @@ public class QuestController(
|
|||||||
Id = condition.Id,
|
Id = condition.Id,
|
||||||
SourceId = questId,
|
SourceId = questId,
|
||||||
Type = condition.ConditionType,
|
Type = condition.ConditionType,
|
||||||
Value = 0
|
Value = 0,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -178,7 +193,11 @@ 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(PmcData pmcData, CompleteQuestRequestData request, string sessionId)
|
public ItemEventRouterResponse CompleteQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
CompleteQuestRequestData request,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _questHelper.CompleteQuest(pmcData, request, sessionId);
|
return _questHelper.CompleteQuest(pmcData, request, sessionId);
|
||||||
}
|
}
|
||||||
@@ -191,7 +210,11 @@ 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(PmcData pmcData, HandoverQuestRequestData request, string sessionID)
|
public ItemEventRouterResponse HandoverQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
HandoverQuestRequestData request,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var quest = _questHelper.GetQuestFromDb(request.QuestId, pmcData);
|
var quest = _questHelper.GetQuestFromDb(request.QuestId, pmcData);
|
||||||
List<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
|
List<string> handoverQuestTypes = ["HandoverItem", "WeaponAssembly"];
|
||||||
@@ -202,7 +225,11 @@ public class QuestController(
|
|||||||
|
|
||||||
// Decrement number of items handed in
|
// Decrement number of items handed in
|
||||||
QuestCondition? handoverRequirements = null;
|
QuestCondition? handoverRequirements = null;
|
||||||
foreach (var condition in quest.Conditions.AvailableForFinish.Where(condition => condition.Id == request.ConditionId))
|
foreach (
|
||||||
|
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))
|
||||||
@@ -228,7 +255,7 @@ public class QuestController(
|
|||||||
questId = request.QuestId,
|
questId = request.QuestId,
|
||||||
conditionId = request.ConditionId,
|
conditionId = request.ConditionId,
|
||||||
profileCounter = counter.Value,
|
profileCounter = counter.Value,
|
||||||
value = handedInCount
|
value = handedInCount,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -242,14 +269,25 @@ public class QuestController(
|
|||||||
|
|
||||||
if (isItemHandoverQuest && handedInCount == 0)
|
if (isItemHandoverQuest && handedInCount == 0)
|
||||||
{
|
{
|
||||||
return ShowRepeatableQuestInvalidConditionError(request.QuestId, request.ConditionId, output);
|
return ShowRepeatableQuestInvalidConditionError(
|
||||||
|
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 => item.Id == itemHandover.Id);
|
var matchingItemInProfile = pmcData.Inventory.Items.FirstOrDefault(item =>
|
||||||
if (!(matchingItemInProfile is not null && handoverRequirements.Target.List.Contains(matchingItemInProfile.Template)))
|
item.Id == itemHandover.Id
|
||||||
|
);
|
||||||
|
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(
|
||||||
@@ -261,7 +299,10 @@ public class QuestController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the right quantity of given items
|
// Remove the right quantity of given items
|
||||||
var itemCountToRemove = Math.Min(itemHandover.Count ?? 0, handedInCount - totalItemCountToRemove);
|
var itemCountToRemove = Math.Min(
|
||||||
|
itemHandover.Count ?? 0,
|
||||||
|
handedInCount - totalItemCountToRemove
|
||||||
|
);
|
||||||
totalItemCountToRemove += itemCountToRemove;
|
totalItemCountToRemove += itemCountToRemove;
|
||||||
if (itemHandover.Count - itemCountToRemove > 0)
|
if (itemHandover.Count - itemCountToRemove > 0)
|
||||||
{
|
{
|
||||||
@@ -283,17 +324,16 @@ public class QuestController(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remove item with children
|
// Remove item with children
|
||||||
var toRemove = _itemHelper.FindAndReturnChildrenByItems(pmcData.Inventory.Items, itemHandover.Id);
|
var toRemove = _itemHelper.FindAndReturnChildrenByItems(
|
||||||
|
pmcData.Inventory.Items,
|
||||||
|
itemHandover.Id
|
||||||
|
);
|
||||||
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.ProfileChanges[sessionID]
|
output
|
||||||
.Items.DeletedItems.Add(
|
.ProfileChanges[sessionID]
|
||||||
new Item
|
.Items.DeletedItems.Add(new Item { Id = itemHandover.Id });
|
||||||
{
|
|
||||||
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)
|
||||||
@@ -344,15 +384,15 @@ public class QuestController(
|
|||||||
/// <param name="conditionId">Relevant condition id that failed</param>
|
/// <param name="conditionId">Relevant condition id that failed</param>
|
||||||
/// <param name="output">Client response</param>
|
/// <param name="output">Client response</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
protected ItemEventRouterResponse ShowRepeatableQuestInvalidConditionError(string questId, string conditionId, ItemEventRouterResponse output)
|
protected ItemEventRouterResponse ShowRepeatableQuestInvalidConditionError(
|
||||||
|
string questId,
|
||||||
|
string conditionId,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var errorMessage = _localisationService.GetText(
|
var errorMessage = _localisationService.GetText(
|
||||||
"repeatable-quest_handover_failed_condition_invalid",
|
"repeatable-quest_handover_failed_condition_invalid",
|
||||||
new
|
new { questId, conditionId }
|
||||||
{
|
|
||||||
questId,
|
|
||||||
conditionId
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
_logger.Error(errorMessage);
|
_logger.Error(errorMessage);
|
||||||
|
|
||||||
@@ -367,8 +407,12 @@ public class QuestController(
|
|||||||
/// <param name="handoverRequirements">Quest handover requirements</param>
|
/// <param name="handoverRequirements">Quest handover requirements</param>
|
||||||
/// <param name="output">Response to send to user</param>
|
/// <param name="output">Response to send to user</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
protected ItemEventRouterResponse ShowQuestItemHandoverMatchError(HandoverQuestRequestData handoverQuestRequest, Item? itemHandedOver,
|
protected ItemEventRouterResponse ShowQuestItemHandoverMatchError(
|
||||||
QuestCondition? handoverRequirements, ItemEventRouterResponse output)
|
HandoverQuestRequestData handoverQuestRequest,
|
||||||
|
Item? itemHandedOver,
|
||||||
|
QuestCondition? handoverRequirements,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var errorMessage = _localisationService.GetText(
|
var errorMessage = _localisationService.GetText(
|
||||||
"quest-handover_wrong_item",
|
"quest-handover_wrong_item",
|
||||||
@@ -376,7 +420,7 @@ public class QuestController(
|
|||||||
{
|
{
|
||||||
questId = handoverQuestRequest.QuestId,
|
questId = handoverQuestRequest.QuestId,
|
||||||
handedInTpl = itemHandedOver?.Template ?? "UNKNOWN",
|
handedInTpl = itemHandedOver?.Template ?? "UNKNOWN",
|
||||||
requiredTpl = handoverRequirements.Target.List.FirstOrDefault()
|
requiredTpl = handoverRequirements.Target.List.FirstOrDefault(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
_logger.Error(errorMessage);
|
_logger.Error(errorMessage);
|
||||||
@@ -392,7 +436,12 @@ 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(PmcData pmcData, string conditionId, string questId, double counterValue)
|
protected void UpdateProfileTaskConditionCounterValue(
|
||||||
|
PmcData pmcData,
|
||||||
|
string conditionId,
|
||||||
|
string questId,
|
||||||
|
double counterValue
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (pmcData.TaskConditionCounters.GetValueOrDefault(conditionId) != null)
|
if (pmcData.TaskConditionCounters.GetValueOrDefault(conditionId) != null)
|
||||||
{
|
{
|
||||||
@@ -401,13 +450,16 @@ public class QuestController(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmcData.TaskConditionCounters.Add(conditionId, new TaskConditionCounter
|
pmcData.TaskConditionCounters.Add(
|
||||||
|
conditionId,
|
||||||
|
new TaskConditionCounter
|
||||||
{
|
{
|
||||||
Id = conditionId,
|
Id = conditionId,
|
||||||
SourceId = questId,
|
SourceId = questId,
|
||||||
Type = "HandoverItem",
|
Type = "HandoverItem",
|
||||||
Value = counterValue
|
Value = counterValue,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -418,7 +470,12 @@ public class QuestController(
|
|||||||
/// <param name="sessionID">Session/Player id</param>
|
/// <param name="sessionID">Session/Player id</param>
|
||||||
/// <param name="output"></param>
|
/// <param name="output"></param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
public ItemEventRouterResponse FailQuest(PmcData pmcData, FailQuestRequestData request, string sessionID, ItemEventRouterResponse output)
|
public ItemEventRouterResponse FailQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
FailQuestRequestData request,
|
||||||
|
string sessionID,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_questHelper.FailQuest(pmcData, request, sessionID, output);
|
_questHelper.FailQuest(pmcData, request, sessionID, output);
|
||||||
|
|
||||||
|
|||||||
@@ -114,8 +114,9 @@ public class RagfairController
|
|||||||
// Check profile is capable of creating offers
|
// Check profile is capable of creating offers
|
||||||
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 >= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
|
&& pmcProfile.Info.Level
|
||||||
|
>= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_ragfairOfferHelper.ProcessOffersOnProfile(sessionId);
|
_ragfairOfferHelper.ProcessOffersOnProfile(sessionId);
|
||||||
@@ -139,16 +140,25 @@ public class RagfairController
|
|||||||
{
|
{
|
||||||
Offers = [],
|
Offers = [],
|
||||||
OffersCount = searchRequest.Limit,
|
OffersCount = searchRequest.Limit,
|
||||||
SelectedCategory = searchRequest.HandbookId
|
SelectedCategory = searchRequest.HandbookId,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get all offers ready for sorting/filtering below
|
// Get all offers ready for sorting/filtering below
|
||||||
result.Offers = GetOffersForSearchType(searchRequest, itemsToAdd, traderAssorts, profile.CharacterData.PmcData);
|
result.Offers = GetOffersForSearchType(
|
||||||
|
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(profile.CharacterData.PmcData, searchRequest, result.Offers);
|
result.Categories = GetSpecificCategories(
|
||||||
|
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
|
||||||
@@ -171,7 +181,11 @@ public class RagfairController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update trader offers' values, Lock quest-linked offers + adjust offer buy limits
|
// Update trader offers' values, Lock quest-linked offers + adjust offer buy limits
|
||||||
foreach (var traderOffer in result.Offers.Where(offer => _ragfairOfferHelper.OfferIsFromTrader(offer)))
|
foreach (
|
||||||
|
var traderOffer in result.Offers.Where(offer =>
|
||||||
|
_ragfairOfferHelper.OfferIsFromTrader(offer)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// For the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked
|
// For the items, check the barter schemes. The method getDisplayableAssorts sets a flag sptQuestLocked
|
||||||
// to true if the quest is not completed yet
|
// to true if the quest is not completed yet
|
||||||
@@ -239,11 +253,7 @@ public class RagfairController
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"ragfair-unable_to_adjust_stack_count_assort_not_found",
|
"ragfair-unable_to_adjust_stack_count_assort_not_found",
|
||||||
new
|
new { offerId = offer.Items.First().Id, traderId = offer.User.Id }
|
||||||
{
|
|
||||||
offerId = offer.Items.First().Id,
|
|
||||||
traderId = offer.User.Id
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -313,12 +323,16 @@ 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<string, int> GetSpecificCategories(PmcData pmcProfile, SearchRequestData searchRequest,
|
protected Dictionary<string, int> GetSpecificCategories(
|
||||||
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))
|
||||||
{
|
{
|
||||||
@@ -340,7 +354,11 @@ public class RagfairController
|
|||||||
return new Dictionary<string, int>();
|
return new Dictionary<string, int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _ragfairServer.GetAllActiveCategories(playerHasFleaUnlocked, searchRequest, offerPool);
|
return _ragfairServer.GetAllActiveCategories(
|
||||||
|
playerHasFleaUnlocked,
|
||||||
|
searchRequest,
|
||||||
|
offerPool
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -371,14 +389,22 @@ public class RagfairController
|
|||||||
/// <param name="traderAssorts">Trader assorts</param>
|
/// <param name="traderAssorts">Trader assorts</param>
|
||||||
/// <param name="pmcProfile"></param>
|
/// <param name="pmcProfile"></param>
|
||||||
/// <returns>Array of offers</returns>
|
/// <returns>Array of offers</returns>
|
||||||
protected List<RagfairOffer> GetOffersForSearchType(SearchRequestData searchRequest, List<string> itemsToAdd,
|
protected List<RagfairOffer> GetOffersForSearchType(
|
||||||
|
SearchRequestData searchRequest,
|
||||||
|
List<string> itemsToAdd,
|
||||||
Dictionary<string, TraderAssort> traderAssorts,
|
Dictionary<string, TraderAssort> traderAssorts,
|
||||||
PmcData pmcProfile)
|
PmcData pmcProfile
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Searching for items in preset menu
|
// Searching for items in preset menu
|
||||||
if (searchRequest.BuildCount > 0)
|
if (searchRequest.BuildCount > 0)
|
||||||
{
|
{
|
||||||
return _ragfairOfferHelper.GetOffersForBuild(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
return _ragfairOfferHelper.GetOffersForBuild(
|
||||||
|
searchRequest,
|
||||||
|
itemsToAdd,
|
||||||
|
traderAssorts,
|
||||||
|
pmcProfile
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchRequest.NeededSearchId?.Length > 0)
|
if (searchRequest.NeededSearchId?.Length > 0)
|
||||||
@@ -387,7 +413,12 @@ public class RagfairController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Searching for general items
|
// Searching for general items
|
||||||
return _ragfairOfferHelper.GetValidOffers(searchRequest, itemsToAdd, traderAssorts, pmcProfile);
|
return _ragfairOfferHelper.GetValidOffers(
|
||||||
|
searchRequest,
|
||||||
|
itemsToAdd,
|
||||||
|
traderAssorts,
|
||||||
|
pmcProfile
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -396,8 +427,10 @@ 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(GetMarketPriceRequestData getPriceRequest,
|
public GetItemPriceResult GetItemMinAvgMaxFleaPriceValues(
|
||||||
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);
|
||||||
@@ -415,7 +448,7 @@ public class RagfairController
|
|||||||
{
|
{
|
||||||
Avg = Math.Round(average),
|
Avg = Math.Round(average),
|
||||||
Min = minMax.Min,
|
Min = minMax.Min,
|
||||||
Max = minMax.Max
|
Max = minMax.Max,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,11 +464,15 @@ public class RagfairController
|
|||||||
{
|
{
|
||||||
Avg = tplPrice,
|
Avg = tplPrice,
|
||||||
Min = tplPrice,
|
Min = tplPrice,
|
||||||
Max = tplPrice
|
Max = tplPrice,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetAveragePriceFromOffers(List<RagfairOffer> offers, MinMax<double> minMax, bool ignoreTraderOffers)
|
protected double GetAveragePriceFromOffers(
|
||||||
|
List<RagfairOffer> offers,
|
||||||
|
MinMax<double> minMax,
|
||||||
|
bool ignoreTraderOffers
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var sum = 0d;
|
var sum = 0d;
|
||||||
var totalOfferCount = 0;
|
var totalOfferCount = 0;
|
||||||
@@ -488,14 +525,21 @@ 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(PmcData pmcData, AddOfferRequestData offerRequest, string sessionID)
|
public ItemEventRouterResponse AddPlayerOffer(
|
||||||
|
PmcData pmcData,
|
||||||
|
AddOfferRequestData offerRequest,
|
||||||
|
string 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(output, "Unable to add offer, check server for error");
|
return _httpResponseUtil.AppendErrorToOutput(
|
||||||
|
output,
|
||||||
|
"Unable to add offer, check server for error"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var typeOfOffer = GetOfferType(offerRequest);
|
var typeOfOffer = GetOfferType(offerRequest);
|
||||||
@@ -540,7 +584,9 @@ public class RagfairController
|
|||||||
|
|
||||||
if (offerRequest.Requirements is null)
|
if (offerRequest.Requirements is null)
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements"));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("ragfair-unable_to_place_offer_with_no_requirements")
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -588,8 +634,12 @@ public class RagfairController
|
|||||||
/// <param name="fullProfile">Full profile of player</param>
|
/// <param name="fullProfile">Full profile of player</param>
|
||||||
/// <param name="output">output Response to send to client</param>
|
/// <param name="output">output Response to send to client</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
protected ItemEventRouterResponse CreateMultiOffer(string sessionID, AddOfferRequestData offerRequest,
|
protected ItemEventRouterResponse CreateMultiOffer(
|
||||||
SptProfile fullProfile, ItemEventRouterResponse output)
|
string sessionID,
|
||||||
|
AddOfferRequestData offerRequest,
|
||||||
|
SptProfile fullProfile,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var pmcData = fullProfile.CharacterData.PmcData;
|
var pmcData = fullProfile.CharacterData.PmcData;
|
||||||
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used to commented out for now // Does not count stack size, only items
|
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used to commented out for now // Does not count stack size, only items
|
||||||
@@ -625,17 +675,18 @@ public class RagfairController
|
|||||||
var rootOfferItem = offer.Items.First(x => x.Id == firstOfferItemId);
|
var rootOfferItem = offer.Items.First(x => x.Id == firstOfferItemId);
|
||||||
|
|
||||||
// Average offer price for single item (or whole weapon)
|
// Average offer price for single item (or whole weapon)
|
||||||
var averages =
|
var averages = GetItemMinAvgMaxFleaPriceValues(
|
||||||
GetItemMinAvgMaxFleaPriceValues(
|
new GetMarketPriceRequestData { TemplateId = offer.Items[0].Template }
|
||||||
new GetMarketPriceRequestData
|
|
||||||
{
|
|
||||||
TemplateId = offer.Items[0].Template
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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 (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(rootOfferItem.Template, out var itemPriceModifer))
|
if (
|
||||||
|
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
||||||
|
rootOfferItem.Template,
|
||||||
|
out var itemPriceModifer
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
averageOfferPrice *= itemPriceModifer;
|
averageOfferPrice *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -700,8 +751,12 @@ public class RagfairController
|
|||||||
/// <param name="fullProfile">Full profile of player</param>
|
/// <param name="fullProfile">Full profile of player</param>
|
||||||
/// <param name="output">Response to send to client</param>
|
/// <param name="output">Response to send to client</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
protected ItemEventRouterResponse CreatePackOffer(string sessionID, AddOfferRequestData offerRequest,
|
protected ItemEventRouterResponse CreatePackOffer(
|
||||||
SptProfile fullProfile, ItemEventRouterResponse output)
|
string sessionID,
|
||||||
|
AddOfferRequestData offerRequest,
|
||||||
|
SptProfile fullProfile,
|
||||||
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var pmcData = fullProfile.CharacterData.PmcData;
|
var pmcData = fullProfile.CharacterData.PmcData;
|
||||||
// var itemsToListCount = offerRequest.Items.Count; // TODO: Wasn't used so commented out for now // Does not count stack size, only items
|
// var itemsToListCount = offerRequest.Items.Count; // TODO: Wasn't used so commented out for now // Does not count stack size, only items
|
||||||
@@ -730,22 +785,29 @@ public class RagfairController
|
|||||||
firstListingRootItem.Upd.StackObjectsCount = stackCountTotal;
|
firstListingRootItem.Upd.StackObjectsCount = stackCountTotal;
|
||||||
|
|
||||||
// Create flea object
|
// Create flea object
|
||||||
var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstListingAndChildren, true);
|
var offer = CreatePlayerOffer(
|
||||||
|
sessionID,
|
||||||
|
offerRequest.Requirements,
|
||||||
|
firstListingAndChildren,
|
||||||
|
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
|
||||||
|
|
||||||
// Single price for an item
|
// Single price for an item
|
||||||
var averages = GetItemMinAvgMaxFleaPriceValues(
|
var averages = GetItemMinAvgMaxFleaPriceValues(
|
||||||
new GetMarketPriceRequestData
|
new GetMarketPriceRequestData { TemplateId = firstListingRootItem.Template }
|
||||||
{
|
|
||||||
TemplateId = firstListingRootItem.Template
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
var singleItemPrice = averages.Avg;
|
var singleItemPrice = averages.Avg;
|
||||||
|
|
||||||
// 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 (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(newRootOfferItem.Template, out var itemPriceModifer))
|
if (
|
||||||
|
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
||||||
|
newRootOfferItem.Template,
|
||||||
|
out var itemPriceModifer
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
singleItemPrice *= itemPriceModifer;
|
singleItemPrice *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -767,7 +829,11 @@ 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(sellChancePercent, (int) stackCountTotal, true);
|
offer.SellResults = _ragfairSellHelper.RollForSale(
|
||||||
|
sellChancePercent,
|
||||||
|
(int)stackCountTotal,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// Subtract flea market fee from stash
|
// Subtract flea market fee from stash
|
||||||
if (_ragfairConfig.Sell.Fees)
|
if (_ragfairConfig.Sell.Fees)
|
||||||
@@ -809,22 +875,30 @@ public class RagfairController
|
|||||||
/// <param name="fullProfile">Full profile of player</param>
|
/// <param name="fullProfile">Full profile of player</param>
|
||||||
/// <param name="output">Response to send to client</param>
|
/// <param name="output">Response to send to client</param>
|
||||||
/// <returns>ItemEventRouterResponse</returns>
|
/// <returns>ItemEventRouterResponse</returns>
|
||||||
protected ItemEventRouterResponse CreateSingleOffer(string sessionID, AddOfferRequestData offerRequest,
|
protected ItemEventRouterResponse CreateSingleOffer(
|
||||||
|
string sessionID,
|
||||||
|
AddOfferRequestData offerRequest,
|
||||||
SptProfile fullProfile,
|
SptProfile fullProfile,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var pmcData = fullProfile.CharacterData.PmcData;
|
var pmcData = fullProfile.CharacterData.PmcData;
|
||||||
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used so commented out for now // Does not count stack size, only items
|
// var itemsToListCount = offerRequest.Items.Count; // Wasn't used so commented out for now // Does not count stack size, only items
|
||||||
|
|
||||||
// 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 (inventoryItemsToSell.Items is null || !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage))
|
if (
|
||||||
|
inventoryItemsToSell.Items is null
|
||||||
|
|| !string.IsNullOrEmpty(inventoryItemsToSell.ErrorMessage)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_httpResponseUtil.AppendErrorToOutput(output, inventoryItemsToSell.ErrorMessage);
|
_httpResponseUtil.AppendErrorToOutput(output, inventoryItemsToSell.ErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Total count of items summed using their stack counts
|
// Total count of items summed using their stack counts
|
||||||
var stackCountTotal = _ragfairOfferHelper.GetTotalStackCountSize(inventoryItemsToSell.Items);
|
var stackCountTotal = _ragfairOfferHelper.GetTotalStackCountSize(
|
||||||
|
inventoryItemsToSell.Items
|
||||||
|
);
|
||||||
|
|
||||||
// Checks are done, create offer
|
// Checks are done, create offer
|
||||||
var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements);
|
var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements);
|
||||||
@@ -841,17 +915,18 @@ public class RagfairController
|
|||||||
var qualityMultiplier = _itemHelper.GetItemQualityModifierForItems(offer.Items, true);
|
var qualityMultiplier = _itemHelper.GetItemQualityModifierForItems(offer.Items, true);
|
||||||
|
|
||||||
// Average offer price for single item (or whole weapon)
|
// Average offer price for single item (or whole weapon)
|
||||||
var averages =
|
var averages = GetItemMinAvgMaxFleaPriceValues(
|
||||||
GetItemMinAvgMaxFleaPriceValues(
|
new GetMarketPriceRequestData { TemplateId = offerRootItem.Template }
|
||||||
new GetMarketPriceRequestData
|
|
||||||
{
|
|
||||||
TemplateId = offerRootItem.Template
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
var averageOfferPriceSingleItem = averages.Avg;
|
var averageOfferPriceSingleItem = averages.Avg;
|
||||||
|
|
||||||
// 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 (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(offerRootItem.Template, out var itemPriceModifer))
|
if (
|
||||||
|
_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(
|
||||||
|
offerRootItem.Template,
|
||||||
|
out var itemPriceModifer
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
averageOfferPriceSingleItem *= itemPriceModifer;
|
averageOfferPriceSingleItem *= itemPriceModifer;
|
||||||
}
|
}
|
||||||
@@ -916,10 +991,13 @@ public class RagfairController
|
|||||||
double requirementsPriceInRub,
|
double requirementsPriceInRub,
|
||||||
int itemStackCount,
|
int itemStackCount,
|
||||||
AddOfferRequestData offerRequest,
|
AddOfferRequestData offerRequest,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// 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 storedClientTaxValue = _ragfairTaxService.GetStoredClientOfferTaxValueById(offerRequest.Items[0]);
|
var storedClientTaxValue = _ragfairTaxService.GetStoredClientOfferTaxValueById(
|
||||||
|
offerRequest.Items[0]
|
||||||
|
);
|
||||||
var tax = storedClientTaxValue is not null
|
var tax = storedClientTaxValue is not null
|
||||||
? storedClientTaxValue.Fee
|
? storedClientTaxValue.Fee
|
||||||
: _ragfairTaxService.CalculateTax(
|
: _ragfairTaxService.CalculateTax(
|
||||||
@@ -932,7 +1010,9 @@ public class RagfairController
|
|||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}");
|
_logger.Debug(
|
||||||
|
$"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
|
||||||
@@ -960,8 +1040,12 @@ 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(string sessionId, List<Requirement> requirements, List<Item> items,
|
protected RagfairOffer CreatePlayerOffer(
|
||||||
bool sellInOnePiece)
|
string 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 =>
|
||||||
@@ -974,18 +1058,16 @@ public class RagfairController
|
|||||||
Template = item.Template,
|
Template = item.Template,
|
||||||
ParentId = isChild ? item.ParentId : "hideout",
|
ParentId = isChild ? item.ParentId : "hideout",
|
||||||
SlotId = isChild ? item.SlotId : "hideout",
|
SlotId = isChild ? item.SlotId : "hideout",
|
||||||
Upd = item.Upd
|
Upd = item.Upd,
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
var formattedRequirements = requirements.Select(item => new BarterScheme
|
var formattedRequirements = requirements.Select(item => new BarterScheme
|
||||||
{
|
{
|
||||||
Template = item.Template,
|
Template = item.Template,
|
||||||
Count = item.Count,
|
Count = item.Count,
|
||||||
OnlyFunctional = item.OnlyFunctional
|
OnlyFunctional = item.OnlyFunctional,
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return _ragfairOfferGenerator.CreateAndAddFleaOffer(
|
return _ragfairOfferGenerator.CreateAndAddFleaOffer(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -1007,16 +1089,20 @@ public class RagfairController
|
|||||||
{
|
{
|
||||||
return requirements.Sum(requirement =>
|
return requirements.Sum(requirement =>
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(requirement.Template) || !requirement.Count.HasValue || requirement.Count == 0)
|
if (
|
||||||
|
string.IsNullOrEmpty(requirement.Template)
|
||||||
|
|| !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 * requirement.Count.Value;
|
: _itemHelper.GetDynamicItemPrice(requirement.Template).Value
|
||||||
}
|
* requirement.Count.Value;
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1025,8 +1111,10 @@ public class RagfairController
|
|||||||
/// <param name="pmcData">Players PMC profile</param>
|
/// <param name="pmcData">Players PMC profile</param>
|
||||||
/// <param name="itemIdsFromFleaOfferRequest">Request</param>
|
/// <param name="itemIdsFromFleaOfferRequest">Request</param>
|
||||||
/// <returns>GetItemsToListOnFleaFromInventoryResult</returns>
|
/// <returns>GetItemsToListOnFleaFromInventoryResult</returns>
|
||||||
protected GetItemsToListOnFleaFromInventoryResult GetItemsToListOnFleaFromInventory(PmcData pmcData,
|
protected GetItemsToListOnFleaFromInventoryResult GetItemsToListOnFleaFromInventory(
|
||||||
List<string> itemIdsFromFleaOfferRequest)
|
PmcData pmcData,
|
||||||
|
List<string> itemIdsFromFleaOfferRequest
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<List<Item>> itemsToReturn = [];
|
List<List<Item>> itemsToReturn = [];
|
||||||
var errorMessage = string.Empty;
|
var errorMessage = string.Empty;
|
||||||
@@ -1039,40 +1127,38 @@ public class RagfairController
|
|||||||
{
|
{
|
||||||
errorMessage = _localisationService.GetText(
|
errorMessage = _localisationService.GetText(
|
||||||
"ragfair-unable_to_find_item_in_inventory",
|
"ragfair-unable_to_find_item_in_inventory",
|
||||||
new
|
new { id = itemId }
|
||||||
{
|
|
||||||
id = itemId
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
_logger.Error(errorMessage);
|
_logger.Error(errorMessage);
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult
|
return new GetItemsToListOnFleaFromInventoryResult
|
||||||
{
|
{
|
||||||
Items = itemsToReturn,
|
Items = itemsToReturn,
|
||||||
ErrorMessage = errorMessage
|
ErrorMessage = errorMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_itemHelper.FixItemStackCount(rootItem);
|
_itemHelper.FixItemStackCount(rootItem);
|
||||||
|
|
||||||
itemsToReturn.Add(_itemHelper.FindAndReturnChildrenAsItems(pmcData.Inventory.Items, itemId));
|
itemsToReturn.Add(
|
||||||
|
_itemHelper.FindAndReturnChildrenAsItems(pmcData.Inventory.Items, itemId)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemsToReturn?.Count == 0)
|
if (itemsToReturn?.Count == 0)
|
||||||
{
|
{
|
||||||
errorMessage = _localisationService.GetText("ragfair-unable_to_find_requested_items_in_inventory");
|
errorMessage = _localisationService.GetText(
|
||||||
|
"ragfair-unable_to_find_requested_items_in_inventory"
|
||||||
|
);
|
||||||
_logger.Error(errorMessage);
|
_logger.Error(errorMessage);
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult
|
return new GetItemsToListOnFleaFromInventoryResult { ErrorMessage = errorMessage };
|
||||||
{
|
|
||||||
ErrorMessage = errorMessage
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GetItemsToListOnFleaFromInventoryResult
|
return new GetItemsToListOnFleaFromInventoryResult
|
||||||
{
|
{
|
||||||
Items = itemsToReturn,
|
Items = itemsToReturn,
|
||||||
ErrorMessage = errorMessage
|
ErrorMessage = errorMessage,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,11 +1180,7 @@ public class RagfairController
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"ragfair-unable_to_remove_offer_not_found_in_profile",
|
"ragfair-unable_to_remove_offer_not_found_in_profile",
|
||||||
new
|
new { profileId = sessionId, offerId }
|
||||||
{
|
|
||||||
profileId = sessionId,
|
|
||||||
offerId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1109,13 +1191,7 @@ public class RagfairController
|
|||||||
if (playerOffer is null)
|
if (playerOffer is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText("ragfair-offer_not_found_in_profile", new { offerId })
|
||||||
"ragfair-offer_not_found_in_profile",
|
|
||||||
new
|
|
||||||
{
|
|
||||||
offerId
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return _httpResponseUtil.AppendErrorToOutput(
|
return _httpResponseUtil.AppendErrorToOutput(
|
||||||
@@ -1133,7 +1209,9 @@ public class RagfairController
|
|||||||
playerOffer.EndTime = (long?)Math.Round((double)newEndTime);
|
playerOffer.EndTime = (long?)Math.Round((double)newEndTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug($"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}");
|
_logger.Debug(
|
||||||
|
$"Flagged player offer: {offerId} for expiry in: {TimeSpan.FromTicks(playerOffer.EndTime.Value).ToString()}"
|
||||||
|
);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -1144,7 +1222,10 @@ 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(ExtendOfferRequestData extendRequest, string sessionId)
|
public ItemEventRouterResponse ExtendOffer(
|
||||||
|
ExtendOfferRequestData extendRequest,
|
||||||
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionId);
|
var output = _eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -1158,10 +1239,7 @@ public class RagfairController
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"ragfair-offer_not_found_in_profile",
|
"ragfair-offer_not_found_in_profile",
|
||||||
new
|
new { offerId = extendRequest.OfferId }
|
||||||
{
|
|
||||||
offerId = extendRequest.OfferId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return _httpResponseUtil.AppendErrorToOutput(
|
return _httpResponseUtil.AppendErrorToOutput(
|
||||||
@@ -1179,7 +1257,8 @@ public class RagfairController
|
|||||||
var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false);
|
var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false);
|
||||||
if (!sellInOncePiece)
|
if (!sellInOncePiece)
|
||||||
{
|
{
|
||||||
count = (int) playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
|
count = (int)
|
||||||
|
playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tax = _ragfairTaxService.CalculateTax(
|
var tax = _ragfairTaxService.CalculateTax(
|
||||||
@@ -1213,7 +1292,10 @@ 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(CurrencyType currency, double value)
|
protected ProcessBuyTradeRequestData CreateBuyTradeRequestObject(
|
||||||
|
CurrencyType currency,
|
||||||
|
double value
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ProcessBuyTradeRequestData
|
return new ProcessBuyTradeRequestData
|
||||||
{
|
{
|
||||||
@@ -1224,13 +1306,13 @@ public class RagfairController
|
|||||||
new IdWithCount
|
new IdWithCount
|
||||||
{
|
{
|
||||||
Id = _paymentHelper.GetCurrency(currency),
|
Id = _paymentHelper.GetCurrency(currency),
|
||||||
Count = Math.Round(value)
|
Count = Math.Round(value),
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
Type = "",
|
Type = "",
|
||||||
ItemId = "",
|
ItemId = "",
|
||||||
Count = 0,
|
Count = 0,
|
||||||
SchemeId = 0
|
SchemeId = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1258,16 +1340,8 @@ public class RagfairController
|
|||||||
|
|
||||||
public record GetItemsToListOnFleaFromInventoryResult
|
public record GetItemsToListOnFleaFromInventoryResult
|
||||||
{
|
{
|
||||||
public List<List<Item>>? Items
|
public List<List<Item>>? Items { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string? ErrorMessage
|
public string? ErrorMessage { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using SPTarkov.Server.Core.Services;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class RepairController(
|
public class RepairController(EventOutputHolder _eventOutputHolder, RepairService _repairService)
|
||||||
EventOutputHolder _eventOutputHolder,
|
|
||||||
RepairService _repairService
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle TraderRepair event
|
/// Handle TraderRepair event
|
||||||
@@ -24,14 +21,20 @@ public class RepairController(
|
|||||||
public ItemEventRouterResponse TraderRepair(
|
public ItemEventRouterResponse TraderRepair(
|
||||||
string sessionID,
|
string sessionID,
|
||||||
TraderRepairActionDataRequest body,
|
TraderRepairActionDataRequest body,
|
||||||
PmcData pmcData)
|
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 body.RepairItems)
|
foreach (var repairItem in body.RepairItems)
|
||||||
{
|
{
|
||||||
var repairDetails = _repairService.RepairItemByTrader(sessionID, pmcData, repairItem, body.TId);
|
var repairDetails = _repairService.RepairItemByTrader(
|
||||||
|
sessionID,
|
||||||
|
pmcData,
|
||||||
|
repairItem,
|
||||||
|
body.TId
|
||||||
|
);
|
||||||
|
|
||||||
_repairService.PayForRepair(
|
_repairService.PayForRepair(
|
||||||
sessionID,
|
sessionID,
|
||||||
@@ -68,7 +71,8 @@ public class RepairController(
|
|||||||
public ItemEventRouterResponse RepairWithKit(
|
public ItemEventRouterResponse RepairWithKit(
|
||||||
string sessionId,
|
string sessionId,
|
||||||
RepairActionDataRequest body,
|
RepairActionDataRequest body,
|
||||||
PmcData pmcData)
|
PmcData pmcData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionId);
|
var output = _eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ 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(PmcData pmcData, AcceptQuestRequestData acceptedQuest, string sessionID)
|
public ItemEventRouterResponse AcceptRepeatableQuest(
|
||||||
|
PmcData pmcData,
|
||||||
|
AcceptQuestRequestData acceptedQuest,
|
||||||
|
string 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(
|
||||||
@@ -74,11 +78,16 @@ public class RepeatableQuestController(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
throw new Exception(_localisationService.GetText("repeatable-unable_to_accept_quest_see_log"));
|
throw new Exception(
|
||||||
|
_localisationService.GetText("repeatable-unable_to_accept_quest_see_log")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some scav quests need to be added to scav profile for them to show up in-raid
|
// Some scav quests need to be added to scav profile for them to show up in-raid
|
||||||
if (repeatableQuestProfile.Side == "Scav" && _questTypes.Contains(repeatableQuestProfile.Type.ToString()))
|
if (
|
||||||
|
repeatableQuestProfile.Side == "Scav"
|
||||||
|
&& _questTypes.Contains(repeatableQuestProfile.Type.ToString())
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var fullProfile = _profileHelper.GetFullProfile(sessionID);
|
var fullProfile = _profileHelper.GetFullProfile(sessionID);
|
||||||
|
|
||||||
@@ -98,8 +107,11 @@ 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(PmcData pmcData, RepeatableQuestChangeRequest changeRequest,
|
public ItemEventRouterResponse ChangeRepeatableQuest(
|
||||||
string sessionID)
|
PmcData pmcData,
|
||||||
|
RepeatableQuestChangeRequest changeRequest,
|
||||||
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionID);
|
var output = _eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -112,7 +124,9 @@ 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 = _localisationService.GetText("quest-unable_to_find_repeatable_to_replace");
|
var message = _localisationService.GetText(
|
||||||
|
"quest-unable_to_find_repeatable_to_replace"
|
||||||
|
);
|
||||||
_logger.Error(message);
|
_logger.Error(message);
|
||||||
|
|
||||||
return _httpResponseUtil.AppendErrorToOutput(output, message);
|
return _httpResponseUtil.AppendErrorToOutput(output, message);
|
||||||
@@ -125,8 +139,8 @@ public class RepeatableQuestController(
|
|||||||
var replacedQuestTraderId = questToReplace.TraderId;
|
var replacedQuestTraderId = questToReplace.TraderId;
|
||||||
|
|
||||||
// Update active quests to exclude the quest we're replacing
|
// Update active quests to exclude the quest we're replacing
|
||||||
repeatablesOfTypeInProfile.ActiveQuests = repeatablesOfTypeInProfile.ActiveQuests.Where(quest => quest.Id != changeRequest.QuestId
|
repeatablesOfTypeInProfile.ActiveQuests = repeatablesOfTypeInProfile
|
||||||
)
|
.ActiveQuests.Where(quest => quest.Id != changeRequest.QuestId)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Save for later cost calculations
|
// Save for later cost calculations
|
||||||
@@ -138,7 +152,8 @@ public class RepeatableQuestController(
|
|||||||
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 => config.Name == repeatablesOfTypeInProfile.Name
|
var repeatableConfig = _questConfig.RepeatableQuests.FirstOrDefault(config =>
|
||||||
|
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
|
||||||
@@ -148,7 +163,10 @@ 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(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
|
var allowedQuestTypes = GenerateQuestPool(
|
||||||
|
repeatableConfig,
|
||||||
|
pmcData.Info.Level.GetValueOrDefault(1)
|
||||||
|
);
|
||||||
var newRepeatableQuest = AttemptToGenerateRepeatableQuest(
|
var newRepeatableQuest = AttemptToGenerateRepeatableQuest(
|
||||||
sessionID,
|
sessionID,
|
||||||
pmcData,
|
pmcData,
|
||||||
@@ -186,7 +204,7 @@ public class RepeatableQuestController(
|
|||||||
repeatablesOfTypeInProfile.ChangeRequirement[newRepeatableQuest.Id] = new ChangeRequirement
|
repeatablesOfTypeInProfile.ChangeRequirement[newRepeatableQuest.Id] = new ChangeRequirement
|
||||||
{
|
{
|
||||||
ChangeCost = newRepeatableQuest.ChangeCost,
|
ChangeCost = newRepeatableQuest.ChangeCost,
|
||||||
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost)
|
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if we should charge player for replacing quest
|
// Check if we should charge player for replacing quest
|
||||||
@@ -201,12 +219,22 @@ public class RepeatableQuestController(
|
|||||||
var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId];
|
var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId];
|
||||||
traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost;
|
traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost;
|
||||||
|
|
||||||
var charismaBonus = _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0;
|
var charismaBonus =
|
||||||
|
_profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0;
|
||||||
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) Math.Truncate(cost.Count.Value * (1 - Math.Truncate(charismaBonus / 100) * 0.001));
|
cost.Count = (int)
|
||||||
_paymentService.AddPaymentToOutput(pmcData, cost.TemplateId, cost.Count.Value, sessionID, output);
|
Math.Truncate(
|
||||||
|
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;
|
||||||
@@ -265,8 +293,11 @@ 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(SptProfile? fullProfile, PmcDataRepeatableQuest repeatableSubType,
|
protected bool UseFreeRefreshIfAvailable(
|
||||||
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)
|
||||||
@@ -305,8 +336,10 @@ 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(PmcDataRepeatableQuest repeatablesOfTypeInProfile,
|
protected void CleanUpRepeatableChangeRequirements(
|
||||||
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
|
||||||
@@ -329,8 +362,12 @@ public class RepeatableQuestController(
|
|||||||
/// <param name="questTypePool">What type/level range of quests can be generated for player</param>
|
/// <param name="questTypePool">What type/level range of quests can be generated for player</param>
|
||||||
/// <param name="repeatableConfig">Config for the quest type to generate</param>
|
/// <param name="repeatableConfig">Config for the quest type to generate</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected RepeatableQuest? AttemptToGenerateRepeatableQuest(string sessionId, PmcData pmcData,
|
protected RepeatableQuest? AttemptToGenerateRepeatableQuest(
|
||||||
QuestTypePool questTypePool, RepeatableQuestConfig repeatableConfig)
|
string sessionId,
|
||||||
|
PmcData pmcData,
|
||||||
|
QuestTypePool questTypePool,
|
||||||
|
RepeatableQuestConfig repeatableConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
const int maxAttempts = 10;
|
const int maxAttempts = 10;
|
||||||
RepeatableQuest? newRepeatableQuest = null;
|
RepeatableQuest? newRepeatableQuest = null;
|
||||||
@@ -356,7 +393,12 @@ public class RepeatableQuestController(
|
|||||||
|
|
||||||
if (attempts > maxAttempts)
|
if (attempts > maxAttempts)
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("quest-repeatable_generation_failed_please_report", attempts));
|
_logger.Error(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"quest-repeatable_generation_failed_please_report",
|
||||||
|
attempts
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRepeatableQuest;
|
return newRepeatableQuest;
|
||||||
@@ -370,7 +412,10 @@ public class RepeatableQuestController(
|
|||||||
protected void RemoveQuestFromProfile(SptProfile fullProfile, string questToReplaceId)
|
protected void RemoveQuestFromProfile(SptProfile fullProfile, string 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(questToReplaceId, fullProfile.CharacterData.PmcData.Quests);
|
_questHelper.FindAndRemoveQuestFromArrayIfExists(
|
||||||
|
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)
|
||||||
@@ -393,8 +438,9 @@ 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 =
|
var questToReplace = repeatablesInProfile.ActiveQuests?.FirstOrDefault(repeatable =>
|
||||||
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
|
||||||
{
|
{
|
||||||
@@ -404,7 +450,7 @@ public class RepeatableQuestController(
|
|||||||
return new GetRepeatableByIdResult
|
return new GetRepeatableByIdResult
|
||||||
{
|
{
|
||||||
Quest = questToReplace,
|
Quest = questToReplace,
|
||||||
RepeatableType = repeatablesInProfile
|
RepeatableType = repeatablesInProfile,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +489,10 @@ 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(repeatableConfig, pmcData);
|
var generatedRepeatables = GetRepeatableQuestSubTypeFromProfile(
|
||||||
|
repeatableConfig,
|
||||||
|
pmcData
|
||||||
|
);
|
||||||
var repeatableTypeLower = repeatableConfig.Name.ToLower();
|
var repeatableTypeLower = repeatableConfig.Name.ToLower();
|
||||||
|
|
||||||
var canAccessRepeatables = CanProfileAccessRepeatableQuests(repeatableConfig, pmcData);
|
var canAccessRepeatables = CanProfileAccessRepeatableQuests(repeatableConfig, pmcData);
|
||||||
@@ -483,7 +532,10 @@ 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(repeatableConfig, pmcData.Info.Level.GetValueOrDefault(1));
|
var questTypePool = GenerateQuestPool(
|
||||||
|
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++)
|
||||||
@@ -535,7 +587,9 @@ public class RepeatableQuestController(
|
|||||||
new ChangeRequirement
|
new ChangeRequirement
|
||||||
{
|
{
|
||||||
ChangeCost = quest.ChangeCost,
|
ChangeCost = quest.ChangeCost,
|
||||||
ChangeStandingCost = _randomUtil.GetArrayValue(repeatableConfig.StandingChangeCost) // Randomise standing loss to replace
|
ChangeStandingCost = _randomUtil.GetArrayValue(
|
||||||
|
repeatableConfig.StandingChangeCost
|
||||||
|
), // Randomise standing loss to replace
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -553,7 +607,7 @@ public class RepeatableQuestController(
|
|||||||
InactiveQuests = generatedRepeatables.InactiveQuests,
|
InactiveQuests = generatedRepeatables.InactiveQuests,
|
||||||
ChangeRequirement = generatedRepeatables.ChangeRequirement,
|
ChangeRequirement = generatedRepeatables.ChangeRequirement,
|
||||||
FreeChanges = generatedRepeatables.FreeChanges,
|
FreeChanges = generatedRepeatables.FreeChanges,
|
||||||
FreeChangesAvailable = generatedRepeatables.FreeChangesAvailable
|
FreeChangesAvailable = generatedRepeatables.FreeChangesAvailable,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -567,11 +621,14 @@ 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(RepeatableQuestConfig repeatableConfig,
|
protected PmcDataRepeatableQuest GetRepeatableQuestSubTypeFromProfile(
|
||||||
PmcData pmcData)
|
RepeatableQuestConfig repeatableConfig,
|
||||||
|
PmcData pmcData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Get from profile, add if missing
|
// Get from profile, add if missing
|
||||||
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable => repeatable.Name == repeatableConfig.Name
|
var repeatableQuestDetails = pmcData.RepeatableQuests.FirstOrDefault(repeatable =>
|
||||||
|
repeatable.Name == repeatableConfig.Name
|
||||||
);
|
);
|
||||||
var hasAccess = _profileHelper.HasAccessToRepeatableFreeRefreshSystem(pmcData);
|
var hasAccess = _profileHelper.HasAccessToRepeatableFreeRefreshSystem(pmcData);
|
||||||
|
|
||||||
@@ -586,7 +643,7 @@ public class RepeatableQuestController(
|
|||||||
InactiveQuests = [],
|
InactiveQuests = [],
|
||||||
EndTime = 0,
|
EndTime = 0,
|
||||||
FreeChanges = hasAccess ? repeatableConfig.FreeChanges : 0,
|
FreeChanges = hasAccess ? repeatableConfig.FreeChanges : 0,
|
||||||
FreeChangesAvailable = hasAccess ? repeatableConfig.FreeChangesAvailable : 0
|
FreeChangesAvailable = hasAccess ? repeatableConfig.FreeChangesAvailable : 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add base object that holds repeatable data to profile
|
// Add base object that holds repeatable data to profile
|
||||||
@@ -610,10 +667,16 @@ 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(RepeatableQuestConfig repeatableConfig, PmcData pmcData)
|
protected bool CanProfileAccessRepeatableQuests(
|
||||||
|
RepeatableQuestConfig repeatableConfig,
|
||||||
|
PmcData pmcData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// PMC and daily quests not unlocked yet
|
// PMC and daily quests not unlocked yet
|
||||||
if (repeatableConfig.Side == "Pmc" && !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig))
|
if (
|
||||||
|
repeatableConfig.Side == "Pmc"
|
||||||
|
&& !PlayerHasDailyPmcQuestsUnlocked(pmcData, repeatableConfig)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -638,7 +701,10 @@ 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(PmcData pmcData, RepeatableQuestConfig repeatableConfig)
|
protected static bool PlayerHasDailyPmcQuestsUnlocked(
|
||||||
|
PmcData pmcData,
|
||||||
|
RepeatableQuestConfig repeatableConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return pmcData.Info.Level >= repeatableConfig.MinPlayerLevel;
|
return pmcData.Info.Level >= repeatableConfig.MinPlayerLevel;
|
||||||
}
|
}
|
||||||
@@ -650,9 +716,11 @@ 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?.Hideout?.Areas?.FirstOrDefault(hideoutArea => hideoutArea.Type == HideoutAreas.IntelligenceCenter)
|
return pmcData
|
||||||
?.Level >=
|
?.Hideout?.Areas?.FirstOrDefault(hideoutArea =>
|
||||||
1;
|
hideoutArea.Type == HideoutAreas.IntelligenceCenter
|
||||||
|
)
|
||||||
|
?.Level >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -660,12 +728,17 @@ 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(PmcDataRepeatableQuest generatedRepeatables, PmcData pmcData)
|
protected void ProcessExpiredQuests(
|
||||||
|
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 => quest.QId == activeQuest.Id);
|
var questStatusInProfile = pmcData.Quests.FirstOrDefault(quest =>
|
||||||
|
quest.QId == activeQuest.Id
|
||||||
|
);
|
||||||
if (questStatusInProfile is null)
|
if (questStatusInProfile is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -723,8 +796,15 @@ 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(pmcLevel, repeatableConfig);
|
var eliminationConfig = _repeatableQuestHelper.GetEliminationConfigByPmcLevel(
|
||||||
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(_mathUtil, _cloner, eliminationConfig.Targets);
|
pmcLevel,
|
||||||
|
repeatableConfig
|
||||||
|
);
|
||||||
|
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(
|
||||||
|
_mathUtil,
|
||||||
|
_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)
|
||||||
@@ -734,10 +814,7 @@ public class RepeatableQuestController(
|
|||||||
{
|
{
|
||||||
questPool.Pool.Elimination.Targets.Add(
|
questPool.Pool.Elimination.Targets.Add(
|
||||||
target.Key,
|
target.Key,
|
||||||
new TargetLocation
|
new TargetLocation { Locations = ["any"] }
|
||||||
{
|
|
||||||
Locations = ["any"]
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -747,16 +824,16 @@ public class RepeatableQuestController(
|
|||||||
var possibleLocations = repeatableConfig.Locations.Keys;
|
var possibleLocations = repeatableConfig.Locations.Keys;
|
||||||
var allowedLocations =
|
var allowedLocations =
|
||||||
target.Key == "Savage"
|
target.Key == "Savage"
|
||||||
? possibleLocations.Where(location => location != ELocationName.laboratory
|
? possibleLocations.Where(location => location != ELocationName.laboratory) // Exclude labs for Savage targets.
|
||||||
) // Exclude labs for Savage targets.
|
|
||||||
: possibleLocations;
|
: possibleLocations;
|
||||||
|
|
||||||
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(),
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return questPool;
|
return questPool;
|
||||||
@@ -776,17 +853,17 @@ public class RepeatableQuestController(
|
|||||||
{
|
{
|
||||||
Exploration = new ExplorationPool
|
Exploration = new ExplorationPool
|
||||||
{
|
{
|
||||||
Locations = new Dictionary<ELocationName, List<string>>()
|
Locations = new Dictionary<ELocationName, List<string>>(),
|
||||||
},
|
},
|
||||||
Elimination = new EliminationPool
|
Elimination = new EliminationPool
|
||||||
{
|
{
|
||||||
Targets = new Dictionary<string, TargetLocation>()
|
Targets = new Dictionary<string, TargetLocation>(),
|
||||||
},
|
},
|
||||||
Pickup = new ExplorationPool
|
Pickup = new ExplorationPool
|
||||||
{
|
{
|
||||||
Locations = new Dictionary<ELocationName, List<string>>()
|
Locations = new Dictionary<ELocationName, List<string>>(),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,23 +882,25 @@ public class RepeatableQuestController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add elite bonus to daily quests
|
// Add elite bonus to daily quests
|
||||||
if (string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase) &&
|
if (
|
||||||
_profileHelper.HasEliteSkillLevel(SkillTypes.Charisma, fullProfile.CharacterData.PmcData))
|
string.Equals(repeatableConfig.Name, "daily", StringComparison.OrdinalIgnoreCase)
|
||||||
|
&& _profileHelper.HasEliteSkillLevel(
|
||||||
|
SkillTypes.Charisma,
|
||||||
|
fullProfile.CharacterData.PmcData
|
||||||
|
)
|
||||||
|
)
|
||||||
// Elite charisma skill gives extra daily quest(s)
|
// Elite charisma skill gives extra daily quest(s)
|
||||||
{
|
{
|
||||||
questCount += _databaseService
|
questCount += _databaseService
|
||||||
.GetGlobals()
|
.GetGlobals()
|
||||||
.Configuration
|
.Configuration.SkillsSettings.Charisma.BonusSettings.EliteBonusSettings.RepeatableQuestExtraCount.GetValueOrDefault(
|
||||||
.SkillsSettings
|
0
|
||||||
.Charisma
|
);
|
||||||
.BonusSettings
|
|
||||||
.EliteBonusSettings
|
|
||||||
.RepeatableQuestExtraCount
|
|
||||||
.GetValueOrDefault(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any extra repeatable quests the profile has unlocked
|
// Add any extra repeatable quests the profile has unlocked
|
||||||
questCount += (int) fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
|
questCount += (int)
|
||||||
|
fullProfile.SptData.ExtraRepeatableQuests.GetValueOrDefault(repeatableConfig.Id, 0);
|
||||||
|
|
||||||
return questCount;
|
return questCount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ public class TradeController(
|
|||||||
public ItemEventRouterResponse ConfirmTrading(
|
public ItemEventRouterResponse ConfirmTrading(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
ProcessBaseTradeRequestData request,
|
ProcessBaseTradeRequestData request,
|
||||||
string sessionID)
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionID);
|
var output = _eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -76,7 +77,11 @@ 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(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
|
return _httpResponseUtil.AppendErrorToOutput(
|
||||||
|
output,
|
||||||
|
errorMessage,
|
||||||
|
BackendErrorCodes.RagfairUnavailable
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -89,7 +94,8 @@ public class TradeController(
|
|||||||
public ItemEventRouterResponse ConfirmRagfairTrading(
|
public ItemEventRouterResponse ConfirmRagfairTrading(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
ProcessRagfairTradeRequestData request,
|
ProcessRagfairTradeRequestData request,
|
||||||
string sessionID)
|
string sessionID
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionID);
|
var output = _eventOutputHolder.GetOutput(sessionID);
|
||||||
|
|
||||||
@@ -111,7 +117,11 @@ 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(output, errorMessage, BackendErrorCodes.OfferOutOfStock);
|
return _httpResponseUtil.AppendErrorToOutput(
|
||||||
|
output,
|
||||||
|
errorMessage,
|
||||||
|
BackendErrorCodes.OfferOutOfStock
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_ragfairOfferHelper.OfferIsFromTrader(fleaOffer))
|
if (_ragfairOfferHelper.OfferIsFromTrader(fleaOffer))
|
||||||
@@ -146,18 +156,24 @@ public class TradeController(
|
|||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
RagfairOffer fleaOffer,
|
RagfairOffer fleaOffer,
|
||||||
OfferRequest requestOffer,
|
OfferRequest requestOffer,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Skip buying items when player doesn't have needed loyalty
|
// Skip buying items when player doesn't have needed loyalty
|
||||||
if (PlayerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData))
|
if (PlayerLacksTraderLoyaltyLevelToBuyOffer(fleaOffer, pmcData))
|
||||||
{
|
{
|
||||||
var errorMessage = $"Unable to buy item: {fleaOffer.Items[0].Template} from trader: {fleaOffer.User.Id} as loyalty level too low, skipping";
|
var errorMessage =
|
||||||
|
$"Unable to buy item: {fleaOffer.Items[0].Template} from trader: {fleaOffer.User.Id} as loyalty level too low, skipping";
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(errorMessage);
|
_logger.Debug(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
_httpResponseUtil.AppendErrorToOutput(output, errorMessage, BackendErrorCodes.RagfairUnavailable);
|
_httpResponseUtil.AppendErrorToOutput(
|
||||||
|
output,
|
||||||
|
errorMessage,
|
||||||
|
BackendErrorCodes.RagfairUnavailable
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -171,9 +187,15 @@ public class TradeController(
|
|||||||
ItemId = fleaOffer.Root,
|
ItemId = fleaOffer.Root,
|
||||||
Count = requestOffer.Count,
|
Count = requestOffer.Count,
|
||||||
SchemeId = 0,
|
SchemeId = 0,
|
||||||
SchemeItems = requestOffer.Items
|
SchemeItems = requestOffer.Items,
|
||||||
};
|
};
|
||||||
_tradeHelper.BuyItem(pmcData, buyData, sessionId, _traderConfig.PurchasesAreFoundInRaid, output);
|
_tradeHelper.BuyItem(
|
||||||
|
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);
|
||||||
@@ -192,7 +214,8 @@ public class TradeController(
|
|||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
RagfairOffer fleaOffer,
|
RagfairOffer fleaOffer,
|
||||||
OfferRequest requestOffer,
|
OfferRequest requestOffer,
|
||||||
ItemEventRouterResponse output)
|
ItemEventRouterResponse output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var buyData = new ProcessBuyTradeRequestData
|
var buyData = new ProcessBuyTradeRequestData
|
||||||
{
|
{
|
||||||
@@ -202,11 +225,17 @@ public class TradeController(
|
|||||||
ItemId = fleaOffer.Id, // Store ragfair offerId in buyRequestData.item_id
|
ItemId = fleaOffer.Id, // Store ragfair offerId in buyRequestData.item_id
|
||||||
Count = requestOffer.Count,
|
Count = requestOffer.Count,
|
||||||
SchemeId = 0,
|
SchemeId = 0,
|
||||||
SchemeItems = requestOffer.Items
|
SchemeItems = requestOffer.Items,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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(pmcData, buyData, sessionId, _ragfairConfig.Dynamic.PurchasesAreFoundInRaid, output);
|
_tradeHelper.BuyItem(
|
||||||
|
pmcData,
|
||||||
|
buyData,
|
||||||
|
sessionId,
|
||||||
|
_ragfairConfig.Dynamic.PurchasesAreFoundInRaid,
|
||||||
|
output
|
||||||
|
);
|
||||||
if (output.Warnings?.Count > 0)
|
if (output.Warnings?.Count > 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -234,9 +263,7 @@ public class TradeController(
|
|||||||
/// <param name="offerId">id of the offer</param>
|
/// <param name="offerId">id of the offer</param>
|
||||||
/// <param name="offerOwnerId">Owner id</param>
|
/// <param name="offerOwnerId">Owner id</param>
|
||||||
/// <returns>true if offer was made by a player</returns>
|
/// <returns>true if offer was made by a player</returns>
|
||||||
protected bool IsPlayerOffer(
|
protected bool IsPlayerOffer(string offerId, string? offerOwnerId)
|
||||||
string offerId,
|
|
||||||
string? offerOwnerId)
|
|
||||||
{
|
{
|
||||||
// No ownerId, not player offer
|
// No ownerId, not player offer
|
||||||
if (offerOwnerId is null)
|
if (offerOwnerId is null)
|
||||||
@@ -261,9 +288,7 @@ public class TradeController(
|
|||||||
/// <param name="fleaOffer">Flea offer being bought</param>
|
/// <param name="fleaOffer">Flea offer being bought</param>
|
||||||
/// <param name="pmcData">Player profile</param>
|
/// <param name="pmcData">Player profile</param>
|
||||||
/// <returns>True if player can buy offer</returns>
|
/// <returns>True if player can buy offer</returns>
|
||||||
protected bool PlayerLacksTraderLoyaltyLevelToBuyOffer(
|
protected bool PlayerLacksTraderLoyaltyLevelToBuyOffer(RagfairOffer fleaOffer, PmcData pmcData)
|
||||||
RagfairOffer fleaOffer,
|
|
||||||
PmcData pmcData)
|
|
||||||
{
|
{
|
||||||
return fleaOffer.LoyaltyLevel > pmcData.TradersInfo[fleaOffer.User.Id].LoyaltyLevel;
|
return fleaOffer.LoyaltyLevel > pmcData.TradersInfo[fleaOffer.User.Id].LoyaltyLevel;
|
||||||
}
|
}
|
||||||
@@ -278,7 +303,8 @@ public class TradeController(
|
|||||||
public ItemEventRouterResponse SellScavItemsToFence(
|
public ItemEventRouterResponse SellScavItemsToFence(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
SellScavItemsToFenceRequestData request,
|
SellScavItemsToFenceRequestData request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var output = _eventOutputHolder.GetOutput(sessionId);
|
var output = _eventOutputHolder.GetOutput(sessionId);
|
||||||
|
|
||||||
@@ -293,10 +319,7 @@ public class TradeController(
|
|||||||
/// <param name="sessionId">Session id</param>
|
/// <param name="sessionId">Session id</param>
|
||||||
/// <param name="roublesToSend">amount of roubles to send</param>
|
/// <param name="roublesToSend">amount of roubles to send</param>
|
||||||
/// <param name="trader">Trader to sell items to</param>
|
/// <param name="trader">Trader to sell items to</param>
|
||||||
protected void MailMoneyToPlayer(
|
protected void MailMoneyToPlayer(string sessionId, int roublesToSend, string trader)
|
||||||
string sessionId,
|
|
||||||
int roublesToSend,
|
|
||||||
string trader)
|
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
@@ -308,10 +331,7 @@ public class TradeController(
|
|||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = Money.ROUBLES,
|
Template = Money.ROUBLES,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = roublesToSend },
|
||||||
{
|
|
||||||
StackObjectsCount = roublesToSend
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure money is properly split to follow its max stack size limit
|
// Ensure money is properly split to follow its max stack size limit
|
||||||
@@ -322,7 +342,11 @@ public class TradeController(
|
|||||||
sessionId,
|
sessionId,
|
||||||
trader,
|
trader,
|
||||||
MessageType.MessageWithItems,
|
MessageType.MessageWithItems,
|
||||||
_randomUtil.GetArrayValue(_databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items) ? items : new List<string>()),
|
_randomUtil.GetArrayValue(
|
||||||
|
_databaseService.GetTrader(trader).Dialogue.TryGetValue("soldItems", out var items)
|
||||||
|
? items
|
||||||
|
: new List<string>()
|
||||||
|
),
|
||||||
curencyReward.SelectMany(x => x).ToList(),
|
curencyReward.SelectMany(x => x).ToList(),
|
||||||
_timeUtil.GetHoursAsSeconds(72)
|
_timeUtil.GetHoursAsSeconds(72)
|
||||||
);
|
);
|
||||||
@@ -340,7 +364,8 @@ public class TradeController(
|
|||||||
string parentItemId,
|
string parentItemId,
|
||||||
List<Item> items,
|
List<Item> items,
|
||||||
Dictionary<string, int?> handbookPrices,
|
Dictionary<string, int?> handbookPrices,
|
||||||
TraderBase traderDetails)
|
TraderBase traderDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(items, parentItemId);
|
var itemWithChildren = _itemHelper.FindAndReturnChildrenAsItems(items, parentItemId);
|
||||||
|
|
||||||
@@ -348,14 +373,25 @@ 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 (!(itemDetails.Key && _itemHelper.IsOfBaseclasses(itemDetails.Value.Id, traderDetails.ItemsBuy.Category)))
|
if (
|
||||||
|
!(
|
||||||
|
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) ((handbookPrices[itemToSell.Template] ?? 0) * (itemToSell.Upd?.StackObjectsCount ?? 1));
|
totalPrice += (int)(
|
||||||
|
(handbookPrices[itemToSell.Template] ?? 0)
|
||||||
|
* (itemToSell.Upd?.StackObjectsCount ?? 1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return totalPrice;
|
return totalPrice;
|
||||||
|
|||||||
@@ -67,8 +67,9 @@ public class TraderController(
|
|||||||
_traderPurchasePersisterService.RemoveStalePurchasesFromProfiles(traderId);
|
_traderPurchasePersisterService.RemoveStalePurchasesFromProfiles(traderId);
|
||||||
|
|
||||||
// Set to next hour on clock or current time + 60 minutes
|
// Set to next hour on clock or current time + 60 minutes
|
||||||
trader.Base.NextResupply =
|
trader.Base.NextResupply = traderResetStartsWithServer
|
||||||
traderResetStartsWithServer ? (int) _traderHelper.GetNextUpdateTimestamp(trader.Base.Id) : (int) nextHourTimestamp;
|
? (int)_traderHelper.GetNextUpdateTimestamp(trader.Base.Id)
|
||||||
|
: (int)nextHourTimestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,10 +86,7 @@ public class TraderController(
|
|||||||
var barterSchemeItem = kvp.Value?.FirstOrDefault()?.FirstOrDefault();
|
var barterSchemeItem = kvp.Value?.FirstOrDefault()?.FirstOrDefault();
|
||||||
if (barterSchemeItem != null && _paymentHelper.IsMoneyTpl(barterSchemeItem.Template))
|
if (barterSchemeItem != null && _paymentHelper.IsMoneyTpl(barterSchemeItem.Template))
|
||||||
{
|
{
|
||||||
barterSchemeItem.Count += Math.Round(
|
barterSchemeItem.Count += Math.Round(barterSchemeItem?.Count * multiplier ?? 0D, 2);
|
||||||
barterSchemeItem?.Count * multiplier ?? 0D,
|
|
||||||
2
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,8 +201,8 @@ public class TraderController(
|
|||||||
{
|
{
|
||||||
{ "5449016a4bdc2d6f028b456f", handbookPrices[Money.ROUBLES] },
|
{ "5449016a4bdc2d6f028b456f", handbookPrices[Money.ROUBLES] },
|
||||||
{ "569668774bdc2da2298b4568", handbookPrices[Money.EUROS] },
|
{ "569668774bdc2da2298b4568", handbookPrices[Money.EUROS] },
|
||||||
{ "5696686a4bdc2da3298b456a", handbookPrices[Money.DOLLARS] }
|
{ "5696686a4bdc2da3298b456a", handbookPrices[Money.DOLLARS] },
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ public class WeatherController(
|
|||||||
{
|
{
|
||||||
protected WeatherConfig _weatherConfig = _configServer.GetConfig<WeatherConfig>();
|
protected WeatherConfig _weatherConfig = _configServer.GetConfig<WeatherConfig>();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle client/weather
|
/// Handle client/weather
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -36,7 +35,7 @@ public class WeatherController(
|
|||||||
Time = "",
|
Time = "",
|
||||||
Date = "",
|
Date = "",
|
||||||
Weather = null,
|
Weather = null,
|
||||||
Season = Season.AUTUMN
|
Season = Season.AUTUMN,
|
||||||
};
|
};
|
||||||
|
|
||||||
_weatherGenerator.CalculateGameTime(result);
|
_weatherGenerator.CalculateGameTime(result);
|
||||||
@@ -55,7 +54,7 @@ public class WeatherController(
|
|||||||
var result = new GetLocalWeatherResponseData
|
var result = new GetLocalWeatherResponseData
|
||||||
{
|
{
|
||||||
Season = _seasonalEventService.GetActiveWeatherSeason(),
|
Season = _seasonalEventService.GetActiveWeatherSeason(),
|
||||||
Weather = []
|
Weather = [],
|
||||||
};
|
};
|
||||||
|
|
||||||
result.Weather.AddRange(_raidWeatherService.GetUpcomingWeather());
|
result.Weather.AddRange(_raidWeatherService.GetUpcomingWeather());
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ using SPTarkov.Server.Core.Routers;
|
|||||||
namespace SPTarkov.Server.Core.Controllers;
|
namespace SPTarkov.Server.Core.Controllers;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class WishlistController(
|
public class WishlistController(EventOutputHolder _eventOutputHolder)
|
||||||
EventOutputHolder _eventOutputHolder
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle AddToWishList
|
/// Handle AddToWishList
|
||||||
@@ -21,7 +19,8 @@ public class WishlistController(
|
|||||||
public ItemEventRouterResponse AddToWishList(
|
public ItemEventRouterResponse AddToWishList(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
AddToWishlistRequest request,
|
AddToWishlistRequest request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var item in request.Items)
|
foreach (var item in request.Items)
|
||||||
{
|
{
|
||||||
@@ -41,7 +40,8 @@ public class WishlistController(
|
|||||||
public ItemEventRouterResponse RemoveFromWishList(
|
public ItemEventRouterResponse RemoveFromWishList(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
RemoveFromWishlistRequest request,
|
RemoveFromWishlistRequest request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var itemId in request.Items)
|
foreach (var itemId in request.Items)
|
||||||
{
|
{
|
||||||
@@ -61,7 +61,8 @@ public class WishlistController(
|
|||||||
public ItemEventRouterResponse ChangeWishListItemCategory(
|
public ItemEventRouterResponse ChangeWishListItemCategory(
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
ChangeWishlistItemCategoryRequest request,
|
ChangeWishlistItemCategoryRequest request,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
pmcData.WishList.Dictionary[request.Item] = request.Category.Value;
|
pmcData.WishList.Dictionary[request.Item] = request.Category.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,10 @@ public abstract class Router
|
|||||||
{
|
{
|
||||||
if (partialMatch)
|
if (partialMatch)
|
||||||
{
|
{
|
||||||
return GetInternalHandledRoutes()
|
return GetInternalHandledRoutes().Where(r => r.dynamic).Any(r => url.Contains(r.route));
|
||||||
.Where(r => r.dynamic)
|
|
||||||
.Any(r => url.Contains(r.route));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetInternalHandledRoutes()
|
return GetInternalHandledRoutes().Where(r => !r.dynamic).Any(r => r.route == url);
|
||||||
.Where(r => !r.dynamic)
|
|
||||||
.Any(r => r.route == url);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +50,12 @@ public abstract class StaticRouter : Router
|
|||||||
_jsonUtil = jsonUtil;
|
_jsonUtil = jsonUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<object> HandleStatic(string url, string? body, string sessionID, string output)
|
public async ValueTask<object> HandleStatic(
|
||||||
|
string url,
|
||||||
|
string? body,
|
||||||
|
string sessionID,
|
||||||
|
string output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var action = _actions.Single(route => route.url == url);
|
var action = _actions.Single(route => route.url == url);
|
||||||
var type = action.bodyType;
|
var type = action.bodyType;
|
||||||
@@ -84,7 +85,12 @@ public abstract class DynamicRouter : Router
|
|||||||
_jsonUtil = jsonUtil;
|
_jsonUtil = jsonUtil;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<object> HandleDynamic(string url, string? body, string sessionID, string output)
|
public async ValueTask<object> HandleDynamic(
|
||||||
|
string url,
|
||||||
|
string? body,
|
||||||
|
string sessionID,
|
||||||
|
string output
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var action = actions.First(r => url.Contains(r.url));
|
var action = actions.First(r => url.Contains(r.url));
|
||||||
var type = action.bodyType;
|
var type = action.bodyType;
|
||||||
@@ -107,11 +113,13 @@ public abstract class DynamicRouter : Router
|
|||||||
// So instead I added the definition
|
// So instead I added the definition
|
||||||
public abstract class ItemEventRouterDefinition : Router
|
public abstract class ItemEventRouterDefinition : Router
|
||||||
{
|
{
|
||||||
public abstract ValueTask<ItemEventRouterResponse> HandleItemEvent(string url,
|
public abstract ValueTask<ItemEventRouterResponse> HandleItemEvent(
|
||||||
|
string url,
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
BaseInteractionRequestData body,
|
BaseInteractionRequestData body,
|
||||||
string sessionID,
|
string sessionID,
|
||||||
ItemEventRouterResponse output);
|
ItemEventRouterResponse output
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class SaveLoadRouter : Router
|
public abstract class SaveLoadRouter : Router
|
||||||
|
|||||||
@@ -8,11 +8,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ServiceLocator
|
public static class ServiceLocator
|
||||||
{
|
{
|
||||||
public static IServiceProvider ServiceProvider
|
public static IServiceProvider ServiceProvider { get; private set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetServiceProvider(IServiceProvider provider)
|
internal static void SetServiceProvider(IServiceProvider provider)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
using SPTarkov.Server.Core.Constants;
|
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Constants;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Common;
|
using SPTarkov.Server.Core.Models.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
@@ -16,7 +16,6 @@ using BodyPart = SPTarkov.Server.Core.Models.Eft.Common.Tables.BodyPart;
|
|||||||
using BodyParts = SPTarkov.Server.Core.Constants.BodyParts;
|
using BodyParts = SPTarkov.Server.Core.Constants.BodyParts;
|
||||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||||
|
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Generators;
|
namespace SPTarkov.Server.Core.Generators;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
@@ -50,7 +49,13 @@ 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(string sessionId, string role, string difficulty, BotType botTemplate, PmcData profile)
|
public PmcData GeneratePlayerScav(
|
||||||
|
string sessionId,
|
||||||
|
string role,
|
||||||
|
string difficulty,
|
||||||
|
BotType botTemplate,
|
||||||
|
PmcData profile
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var bot = GetCloneOfBotBase();
|
var bot = GetCloneOfBotBase();
|
||||||
bot.Info.Settings.BotDifficulty = difficulty;
|
bot.Info.Settings.BotDifficulty = difficulty;
|
||||||
@@ -66,7 +71,7 @@ public class BotGenerator(
|
|||||||
BotRelativeLevelDeltaMin = 0,
|
BotRelativeLevelDeltaMin = 0,
|
||||||
BotCountToGenerate = 1,
|
BotCountToGenerate = 1,
|
||||||
BotDifficulty = difficulty,
|
BotDifficulty = difficulty,
|
||||||
IsPlayerScav = true
|
IsPlayerScav = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
bot = GenerateBot(sessionId, bot, botTemplate, botGenDetails);
|
bot = GenerateBot(sessionId, bot, botTemplate, botGenDetails);
|
||||||
@@ -105,7 +110,7 @@ public class BotGenerator(
|
|||||||
WishList = bot.WishList,
|
WishList = bot.WishList,
|
||||||
MoneyTransferLimitData = bot.MoneyTransferLimitData,
|
MoneyTransferLimitData = bot.MoneyTransferLimitData,
|
||||||
IsPmc = bot.IsPmc,
|
IsPmc = bot.IsPmc,
|
||||||
Prestige = new Dictionary<string, long>()
|
Prestige = new Dictionary<string, long>(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +120,10 @@ 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(string sessionId, BotGenerationDetails? botGenerationDetails)
|
public BotBase PrepareAndGenerateBot(
|
||||||
|
string 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
|
||||||
@@ -124,13 +132,16 @@ public class BotGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Get raw json data for bot (Cloned)
|
// Get raw json data for bot (Cloned)
|
||||||
var botRole = botGenerationDetails.IsPmc ?? false
|
var botRole =
|
||||||
|
botGenerationDetails.IsPmc ?? false
|
||||||
? preparedBotBase.Info.Side // Use side to get usec.json or bear.json when bot will be PMC
|
? preparedBotBase.Info.Side // Use side to get usec.json or bear.json when bot will be PMC
|
||||||
: botGenerationDetails.Role;
|
: botGenerationDetails.Role;
|
||||||
var botJsonTemplateClone = _cloner.Clone(_botHelper.GetBotTemplate(botRole));
|
var botJsonTemplateClone = _cloner.Clone(_botHelper.GetBotTemplate(botRole));
|
||||||
if (botJsonTemplateClone is null)
|
if (botJsonTemplateClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Unable to retrieve: {botRole} bot template, cannot generate bot of this type");
|
_logger.Error(
|
||||||
|
$"Unable to retrieve: {botRole} bot template, cannot generate bot of this type"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenerateBot(sessionId, preparedBotBase, botJsonTemplateClone, botGenerationDetails);
|
return GenerateBot(sessionId, preparedBotBase, botJsonTemplateClone, botGenerationDetails);
|
||||||
@@ -174,7 +185,8 @@ public class BotGenerator(
|
|||||||
string sessionId,
|
string sessionId,
|
||||||
BotBase bot,
|
BotBase bot,
|
||||||
BotType botJsonTemplate,
|
BotType botJsonTemplate,
|
||||||
BotGenerationDetails botGenerationDetails)
|
BotGenerationDetails botGenerationDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var botRoleLowercase = botGenerationDetails.Role.ToLower();
|
var botRoleLowercase = botGenerationDetails.Role.ToLower();
|
||||||
var botLevel = _botLevelGenerator.GenerateBotLevel(
|
var botLevel = _botLevelGenerator.GenerateBotLevel(
|
||||||
@@ -207,7 +219,10 @@ public class BotGenerator(
|
|||||||
: string.Empty;
|
: 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.GetValueOrDefault(false) && ShouldSimulatePlayerScav(botRoleLowercase))
|
if (
|
||||||
|
!botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)
|
||||||
|
&& ShouldSimulatePlayerScav(botRoleLowercase)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_botNameService.AddRandomPmcNameToBotMainProfileNicknameProperty(bot);
|
_botNameService.AddRandomPmcNameToBotMainProfileNicknameProperty(bot);
|
||||||
SetRandomisedGameVersionAndCategory(bot.Info);
|
SetRandomisedGameVersionAndCategory(bot.Info);
|
||||||
@@ -228,7 +243,12 @@ public class BotGenerator(
|
|||||||
RemoveBlacklistedLootFromBotTemplate(botJsonTemplate.BotInventory);
|
RemoveBlacklistedLootFromBotTemplate(botJsonTemplate.BotInventory);
|
||||||
|
|
||||||
// Remove hideout data if bot is not a PMC or pscav - match what live sends
|
// Remove hideout data if bot is not a PMC or pscav - match what live sends
|
||||||
if (!(botGenerationDetails.IsPmc.GetValueOrDefault(false) || botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)))
|
if (
|
||||||
|
!(
|
||||||
|
botGenerationDetails.IsPmc.GetValueOrDefault(false)
|
||||||
|
|| botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
bot.Hideout = null;
|
bot.Hideout = null;
|
||||||
}
|
}
|
||||||
@@ -250,9 +270,15 @@ public class BotGenerator(
|
|||||||
botGenerationDetails.BotDifficulty,
|
botGenerationDetails.BotDifficulty,
|
||||||
botGenerationDetails.Role
|
botGenerationDetails.Role
|
||||||
);
|
);
|
||||||
bot.Info.Settings.UseSimpleAnimator = botJsonTemplate.BotExperience.UseSimpleAnimator ?? false;
|
bot.Info.Settings.UseSimpleAnimator =
|
||||||
bot.Info.Voice = _weightedRandomHelper.GetWeightedValue(botJsonTemplate.BotAppearance.Voice);
|
botJsonTemplate.BotExperience.UseSimpleAnimator ?? false;
|
||||||
bot.Health = GenerateHealth(botJsonTemplate.BotHealth, botGenerationDetails.IsPlayerScav.GetValueOrDefault(false));
|
bot.Info.Voice = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
botJsonTemplate.BotAppearance.Voice
|
||||||
|
);
|
||||||
|
bot.Health = GenerateHealth(
|
||||||
|
botJsonTemplate.BotHealth,
|
||||||
|
botGenerationDetails.IsPlayerScav.GetValueOrDefault(false)
|
||||||
|
);
|
||||||
bot.Skills = GenerateSkills(botJsonTemplate.BotSkills);
|
bot.Skills = GenerateSkills(botJsonTemplate.BotSkills);
|
||||||
bot.Info.PrestigeLevel = 0;
|
bot.Info.PrestigeLevel = 0;
|
||||||
|
|
||||||
@@ -308,7 +334,8 @@ public class BotGenerator(
|
|||||||
/// <returns>True if name should be simulated pscav</returns>
|
/// <returns>True if name should be simulated pscav</returns>
|
||||||
public bool ShouldSimulatePlayerScav(string botRole)
|
public bool ShouldSimulatePlayerScav(string botRole)
|
||||||
{
|
{
|
||||||
return botRole == Roles.Assault && _randomUtil.GetChance100(_botConfig.ChanceAssaultScavHasPlayerScavName);
|
return botRole == Roles.Assault
|
||||||
|
&& _randomUtil.GetChance100(_botConfig.ChanceAssaultScavHasPlayerScavName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -318,13 +345,19 @@ 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>
|
||||||
public int GetExperienceRewardForKillByDifficulty(Dictionary<string, MinMax<int>> experiences, string botDifficulty, string role)
|
public int GetExperienceRewardForKillByDifficulty(
|
||||||
|
Dictionary<string, MinMax<int>> experiences,
|
||||||
|
string botDifficulty,
|
||||||
|
string role
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!experiences.TryGetValue(botDifficulty.ToLower(), out var result))
|
if (!experiences.TryGetValue(botDifficulty.ToLower(), out var result))
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Unable to find experience: {botDifficulty} for {role} bot, falling back to `normal`");
|
_logger.Debug(
|
||||||
|
$"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);
|
||||||
@@ -332,7 +365,6 @@ public class BotGenerator(
|
|||||||
|
|
||||||
// Some bots have -1/-1, shortcut result
|
// Some bots have -1/-1, shortcut result
|
||||||
|
|
||||||
|
|
||||||
if (result.Max == -1)
|
if (result.Max == -1)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@@ -348,11 +380,17 @@ 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>
|
||||||
public double GetStandingChangeForKillByDifficulty(Dictionary<string, double> standingsForKill, string botDifficulty, string role)
|
public double GetStandingChangeForKillByDifficulty(
|
||||||
|
Dictionary<string, double> standingsForKill,
|
||||||
|
string botDifficulty,
|
||||||
|
string role
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!standingsForKill.TryGetValue(botDifficulty.ToLower(), out var result))
|
if (!standingsForKill.TryGetValue(botDifficulty.ToLower(), out var result))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to find standing for kill value for: {role} {botDifficulty}, falling back to `normal`");
|
_logger.Warning(
|
||||||
|
$"Unable to find standing for kill value for: {role} {botDifficulty}, falling back to `normal`"
|
||||||
|
);
|
||||||
|
|
||||||
return standingsForKill["normal"];
|
return standingsForKill["normal"];
|
||||||
}
|
}
|
||||||
@@ -367,11 +405,17 @@ 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>
|
||||||
public double GetAggressorBonusByDifficulty(Dictionary<string, double> aggressorBonuses, string botDifficulty, string role)
|
public double GetAggressorBonusByDifficulty(
|
||||||
|
Dictionary<string, double> aggressorBonuses,
|
||||||
|
string botDifficulty,
|
||||||
|
string role
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!aggressorBonuses.TryGetValue(botDifficulty.ToLower(), out var result))
|
if (!aggressorBonuses.TryGetValue(botDifficulty.ToLower(), out var result))
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to find aggressor bonus for kill value for: {role} {botDifficulty}, falling back to `normal`");
|
_logger.Warning(
|
||||||
|
$"Unable to find aggressor bonus for kill value for: {role} {botDifficulty}, falling back to `normal`"
|
||||||
|
);
|
||||||
|
|
||||||
return aggressorBonuses["normal"];
|
return aggressorBonuses["normal"];
|
||||||
}
|
}
|
||||||
@@ -384,7 +428,10 @@ public class BotGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="botJsonTemplate">Bot data to adjust</param>
|
/// <param name="botJsonTemplate">Bot data to adjust</param>
|
||||||
/// <param name="botGenerationDetails">Generation details of bot</param>
|
/// <param name="botGenerationDetails">Generation details of bot</param>
|
||||||
public void FilterBlacklistedGear(BotType botJsonTemplate, BotGenerationDetails botGenerationDetails)
|
public void FilterBlacklistedGear(
|
||||||
|
BotType botJsonTemplate,
|
||||||
|
BotGenerationDetails botGenerationDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var blacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
|
var blacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
|
||||||
_botGeneratorHelper.GetBotEquipmentRole(botGenerationDetails.Role),
|
_botGeneratorHelper.GetBotEquipmentRole(botGenerationDetails.Role),
|
||||||
@@ -433,8 +480,9 @@ public class BotGenerator(
|
|||||||
// Remove blacklisted loot from loot containers
|
// Remove blacklisted loot from loot containers
|
||||||
foreach (var lootContainerKey in lootContainersToFilter)
|
foreach (var lootContainerKey in lootContainersToFilter)
|
||||||
{
|
{
|
||||||
var propInfo = props
|
var propInfo = props.FirstOrDefault(x =>
|
||||||
.FirstOrDefault(x => string.Equals(x.Name, lootContainerKey, StringComparison.CurrentCultureIgnoreCase));
|
string.Equals(x.Name, lootContainerKey, StringComparison.CurrentCultureIgnoreCase)
|
||||||
|
);
|
||||||
var prop = (Dictionary<string, double>?)propInfo.GetValue(botInventory.Items);
|
var prop = (Dictionary<string, double>?)propInfo.GetValue(botInventory.Items);
|
||||||
|
|
||||||
// No container, skip
|
// No container, skip
|
||||||
@@ -446,7 +494,8 @@ public class BotGenerator(
|
|||||||
var newProp = prop.Where(tpl =>
|
var newProp = prop.Where(tpl =>
|
||||||
{
|
{
|
||||||
return !_itemFilterService.IsLootableItemBlacklisted(tpl.Key);
|
return !_itemFilterService.IsLootableItemBlacklisted(tpl.Key);
|
||||||
}).ToDictionary();
|
})
|
||||||
|
.ToDictionary();
|
||||||
propInfo.SetValue(botInventory.Items, newProp);
|
propInfo.SetValue(botInventory.Items, newProp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,7 +506,11 @@ 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>
|
||||||
public void SetBotAppearance(BotBase bot, Appearance appearance, BotGenerationDetails botGenerationDetails)
|
public void SetBotAppearance(
|
||||||
|
BotBase bot,
|
||||||
|
Appearance appearance,
|
||||||
|
BotGenerationDetails botGenerationDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Choose random values by weight
|
// Choose random values by weight
|
||||||
bot.Customization.Head = _weightedRandomHelper.GetWeightedValue<string>(appearance.Head);
|
bot.Customization.Head = _weightedRandomHelper.GetWeightedValue<string>(appearance.Head);
|
||||||
@@ -468,8 +521,11 @@ public class BotGenerator(
|
|||||||
var chosenBodyTemplate = _databaseService.GetCustomization()[bot.Customization.Body];
|
var chosenBodyTemplate = _databaseService.GetCustomization()[bot.Customization.Body];
|
||||||
|
|
||||||
// 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 => c.Key == chosenBodyTemplate?.Name.Trim());
|
var chosenBody = bodyGlobalDictDb.FirstOrDefault(c =>
|
||||||
bot.Customization.Hands = chosenBody.Value?.IsNotRandom ?? false
|
c.Key == chosenBodyTemplate?.Name.Trim()
|
||||||
|
);
|
||||||
|
bot.Customization.Hands =
|
||||||
|
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
|
||||||
: _weightedRandomHelper.GetWeightedValue<string>(appearance.Hands); // Hands can be random, choose any from weighted dict
|
: _weightedRandomHelper.GetWeightedValue<string>(appearance.Hands); // Hands can be random, choose any from weighted dict
|
||||||
}
|
}
|
||||||
@@ -491,93 +547,121 @@ public class BotGenerator(
|
|||||||
Hydration = new CurrentMinMax
|
Hydration = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(healthObj.Hydration.Min, healthObj.Hydration.Max),
|
Current = _randomUtil.GetDouble(healthObj.Hydration.Min, healthObj.Hydration.Max),
|
||||||
Maximum = healthObj.Hydration.Max
|
Maximum = healthObj.Hydration.Max,
|
||||||
},
|
},
|
||||||
Energy = new CurrentMinMax
|
Energy = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(healthObj.Energy.Min, healthObj.Energy.Max),
|
Current = _randomUtil.GetDouble(healthObj.Energy.Min, healthObj.Energy.Max),
|
||||||
Maximum = healthObj.Energy.Max
|
Maximum = healthObj.Energy.Max,
|
||||||
},
|
},
|
||||||
Temperature = new CurrentMinMax
|
Temperature = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(healthObj.Temperature.Min, healthObj.Temperature.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = healthObj.Temperature.Max
|
healthObj.Temperature.Min,
|
||||||
|
healthObj.Temperature.Max
|
||||||
|
),
|
||||||
|
Maximum = healthObj.Temperature.Max,
|
||||||
},
|
},
|
||||||
BodyParts = new Dictionary<string, BodyPartHealth>
|
BodyParts = new Dictionary<string, BodyPartHealth>
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
BodyParts.Head, new BodyPartHealth
|
BodyParts.Head,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.Head.Min, bodyParts.Head.Max),
|
Current = _randomUtil.GetDouble(bodyParts.Head.Min, bodyParts.Head.Max),
|
||||||
Maximum = Math.Round(bodyParts.Head.Max)
|
Maximum = Math.Round(bodyParts.Head.Max),
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.Chest, new BodyPartHealth
|
BodyParts.Chest,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.Chest.Min, bodyParts.Chest.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.Chest.Max)
|
bodyParts.Chest.Min,
|
||||||
}
|
bodyParts.Chest.Max
|
||||||
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.Chest.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.Stomach, new BodyPartHealth
|
BodyParts.Stomach,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.Stomach.Min, bodyParts.Stomach.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.Stomach.Max)
|
bodyParts.Stomach.Min,
|
||||||
}
|
bodyParts.Stomach.Max
|
||||||
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.Stomach.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.LeftArm, new BodyPartHealth
|
BodyParts.LeftArm,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.LeftArm.Min, bodyParts.LeftArm.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.LeftArm.Max)
|
bodyParts.LeftArm.Min,
|
||||||
}
|
bodyParts.LeftArm.Max
|
||||||
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.LeftArm.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.RightArm, new BodyPartHealth
|
BodyParts.RightArm,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.RightArm.Min, bodyParts.RightArm.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.RightArm.Max)
|
bodyParts.RightArm.Min,
|
||||||
}
|
bodyParts.RightArm.Max
|
||||||
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.RightArm.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.LeftLeg, new BodyPartHealth
|
BodyParts.LeftLeg,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.LeftLeg.Min, bodyParts.LeftLeg.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.LeftLeg.Max)
|
bodyParts.LeftLeg.Min,
|
||||||
}
|
bodyParts.LeftLeg.Max
|
||||||
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.LeftLeg.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BodyParts.RightLeg, new BodyPartHealth
|
BodyParts.RightLeg,
|
||||||
|
new BodyPartHealth
|
||||||
{
|
{
|
||||||
Health = new CurrentMinMax
|
Health = new CurrentMinMax
|
||||||
{
|
{
|
||||||
Current = _randomUtil.GetDouble(bodyParts.RightLeg.Min, bodyParts.RightLeg.Max),
|
Current = _randomUtil.GetDouble(
|
||||||
Maximum = Math.Round(bodyParts.RightLeg.Max)
|
bodyParts.RightLeg.Min,
|
||||||
}
|
bodyParts.RightLeg.Max
|
||||||
}
|
),
|
||||||
|
Maximum = Math.Round(bodyParts.RightLeg.Max),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
},
|
||||||
UpdateTime = 0, // 0 for player-scav too
|
UpdateTime = 0, // 0 for player-scav too
|
||||||
Immortal = false
|
Immortal = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return health;
|
return health;
|
||||||
@@ -602,7 +686,11 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
double? hpTotal = 0;
|
double? hpTotal = 0;
|
||||||
|
|
||||||
foreach (var prop in props.Where(property => !property.Name.Equals("extensiondata", StringComparison.OrdinalIgnoreCase)))
|
foreach (
|
||||||
|
var prop in props.Where(property =>
|
||||||
|
!property.Name.Equals("extensiondata", StringComparison.OrdinalIgnoreCase)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var value = (MinMax<double>)prop.GetValue(bodyPart);
|
var value = (MinMax<double>)prop.GetValue(bodyPart);
|
||||||
hpTotal += value.Max;
|
hpTotal += value.Max;
|
||||||
@@ -630,7 +718,7 @@ public class BotGenerator(
|
|||||||
{
|
{
|
||||||
Common = GetCommonSkillsWithRandomisedProgressValue(botSkills.Common),
|
Common = GetCommonSkillsWithRandomisedProgressValue(botSkills.Common),
|
||||||
Mastering = GetMasteringSkillsWithRandomisedProgressValue(botSkills.Mastering),
|
Mastering = GetMasteringSkillsWithRandomisedProgressValue(botSkills.Mastering),
|
||||||
Points = 0
|
Points = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return skillsToReturn;
|
return skillsToReturn;
|
||||||
@@ -641,7 +729,9 @@ 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>
|
||||||
public List<CommonSkill> GetCommonSkillsWithRandomisedProgressValue(Dictionary<string, MinMax<double>>? skills)
|
public List<CommonSkill> GetCommonSkillsWithRandomisedProgressValue(
|
||||||
|
Dictionary<string, MinMax<double>>? skills
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (skills is null)
|
if (skills is null)
|
||||||
{
|
{
|
||||||
@@ -663,10 +753,9 @@ public class BotGenerator(
|
|||||||
Id = Enum.Parse<SkillTypes>(kvp.Key),
|
Id = Enum.Parse<SkillTypes>(kvp.Key),
|
||||||
Progress = _randomUtil.GetDouble(skill.Min, skill.Max),
|
Progress = _randomUtil.GetDouble(skill.Min, skill.Max),
|
||||||
PointsEarnedDuringSession = 0,
|
PointsEarnedDuringSession = 0,
|
||||||
LastAccess = 0
|
LastAccess = 0,
|
||||||
};
|
};
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.Where(baseSkill => baseSkill != null)
|
.Where(baseSkill => baseSkill != null)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
@@ -676,7 +765,9 @@ 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>
|
||||||
public List<MasterySkill> GetMasteringSkillsWithRandomisedProgressValue(Dictionary<string, MinMax<double>>? skills)
|
public List<MasterySkill> GetMasteringSkillsWithRandomisedProgressValue(
|
||||||
|
Dictionary<string, MinMax<double>>? skills
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (skills is null)
|
if (skills is null)
|
||||||
{
|
{
|
||||||
@@ -697,10 +788,9 @@ public class BotGenerator(
|
|||||||
return new MasterySkill
|
return new MasterySkill
|
||||||
{
|
{
|
||||||
Id = kvp.Key,
|
Id = kvp.Key,
|
||||||
Progress = _randomUtil.GetDouble(skill.Min, skill.Max)
|
Progress = _randomUtil.GetDouble(skill.Min, skill.Max),
|
||||||
};
|
};
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.Where(baseSkill => baseSkill != null)
|
.Where(baseSkill => baseSkill != null)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
@@ -716,7 +806,9 @@ public class BotGenerator(
|
|||||||
var botId = _hashUtil.Generate();
|
var botId = _hashUtil.Generate();
|
||||||
|
|
||||||
bot.Id = botId;
|
bot.Id = botId;
|
||||||
bot.Aid = botGenerationDetails.IsPmc.GetValueOrDefault(false) ? _hashUtil.GenerateAccountId() : 0;
|
bot.Aid = botGenerationDetails.IsPmc.GetValueOrDefault(false)
|
||||||
|
? _hashUtil.GenerateAccountId()
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -788,7 +880,9 @@ 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(_pmcConfig.AccountTypeWeight);
|
botInfo.MemberCategory = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
_pmcConfig.AccountTypeWeight
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,10 +905,7 @@ public class BotGenerator(
|
|||||||
Template = GetDogtagTplByGameVersionAndSide(bot.Info.Side, bot.Info.GameVersion),
|
Template = GetDogtagTplByGameVersionAndSide(bot.Info.Side, bot.Info.GameVersion),
|
||||||
ParentId = bot.Inventory.Equipment,
|
ParentId = bot.Inventory.Equipment,
|
||||||
SlotId = Slots.Dogtag,
|
SlotId = Slots.Dogtag,
|
||||||
Upd = new Upd
|
Upd = new Upd { SpawnedInSession = true },
|
||||||
{
|
|
||||||
SpawnedInSession = true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bot.Inventory.Items.Add(inventoryItem);
|
bot.Inventory.Items.Add(inventoryItem);
|
||||||
|
|||||||
@@ -47,12 +47,16 @@ public class BotInventoryGenerator(
|
|||||||
EquipmentSlots.TacticalVest,
|
EquipmentSlots.TacticalVest,
|
||||||
EquipmentSlots.FaceCover,
|
EquipmentSlots.FaceCover,
|
||||||
EquipmentSlots.Headwear,
|
EquipmentSlots.Headwear,
|
||||||
EquipmentSlots.Earpiece
|
EquipmentSlots.Earpiece,
|
||||||
];
|
];
|
||||||
|
|
||||||
private readonly BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
|
private readonly BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
|
||||||
|
|
||||||
private readonly HashSet<string> _slotsToCheck = [EquipmentSlots.Pockets.ToString(), EquipmentSlots.SecuredContainer.ToString()];
|
private readonly HashSet<string> _slotsToCheck =
|
||||||
|
[
|
||||||
|
EquipmentSlots.Pockets.ToString(),
|
||||||
|
EquipmentSlots.SecuredContainer.ToString(),
|
||||||
|
];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add equipment/weapons/loot to bot
|
/// Add equipment/weapons/loot to bot
|
||||||
@@ -64,7 +68,14 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="botLevel">Level of bot being generated</param>
|
/// <param name="botLevel">Level of bot being generated</param>
|
||||||
/// <param name="chosenGameVersion">Game version for bot, only really applies for PMCs</param>
|
/// <param name="chosenGameVersion">Game version for bot, only really applies for PMCs</param>
|
||||||
/// <returns>PmcInventory object with equipment/weapons/loot</returns>
|
/// <returns>PmcInventory object with equipment/weapons/loot</returns>
|
||||||
public BotBaseInventory GenerateInventory(string sessionId, BotType botJsonTemplate, string botRole, bool isPmc, int botLevel, string chosenGameVersion)
|
public BotBaseInventory GenerateInventory(
|
||||||
|
string sessionId,
|
||||||
|
BotType botJsonTemplate,
|
||||||
|
string botRole,
|
||||||
|
bool isPmc,
|
||||||
|
int botLevel,
|
||||||
|
string chosenGameVersion
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var templateInventory = botJsonTemplate.BotInventory;
|
var templateInventory = botJsonTemplate.BotInventory;
|
||||||
var wornItemChances = botJsonTemplate.BotChances;
|
var wornItemChances = botJsonTemplate.BotChances;
|
||||||
@@ -74,7 +85,9 @@ 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.GetProfileActivityRaidData(sessionId)?.RaidConfiguration;
|
var raidConfig = _profileActivityService
|
||||||
|
.GetProfileActivityRaidData(sessionId)
|
||||||
|
?.RaidConfiguration;
|
||||||
|
|
||||||
GenerateAndAddEquipmentToBot(
|
GenerateAndAddEquipmentToBot(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -101,7 +114,14 @@ 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(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
_botLootGenerator.GenerateLoot(
|
||||||
|
sessionId,
|
||||||
|
botJsonTemplate,
|
||||||
|
isPmc,
|
||||||
|
botRole,
|
||||||
|
botInventory,
|
||||||
|
botLevel
|
||||||
|
);
|
||||||
|
|
||||||
return botInventory;
|
return botInventory;
|
||||||
}
|
}
|
||||||
@@ -123,36 +143,16 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Items =
|
Items =
|
||||||
[
|
[
|
||||||
new Item
|
new Item { Id = equipmentId, Template = ItemTpl.INVENTORY_DEFAULT },
|
||||||
{
|
new Item { Id = stashId, Template = ItemTpl.STASH_STANDARD_STASH_10X30 },
|
||||||
Id = equipmentId,
|
new Item { Id = questRaidItemsId, Template = ItemTpl.STASH_QUESTRAID },
|
||||||
Template = ItemTpl.INVENTORY_DEFAULT
|
new Item { Id = questStashItemsId, Template = ItemTpl.STASH_QUESTOFFLINE },
|
||||||
},
|
new Item { Id = sortingTableId, Template = ItemTpl.SORTINGTABLE_SORTING_TABLE },
|
||||||
new Item
|
|
||||||
{
|
|
||||||
Id = stashId,
|
|
||||||
Template = ItemTpl.STASH_STANDARD_STASH_10X30
|
|
||||||
},
|
|
||||||
new Item
|
|
||||||
{
|
|
||||||
Id = questRaidItemsId,
|
|
||||||
Template = ItemTpl.STASH_QUESTRAID
|
|
||||||
},
|
|
||||||
new Item
|
|
||||||
{
|
|
||||||
Id = questStashItemsId,
|
|
||||||
Template = ItemTpl.STASH_QUESTOFFLINE
|
|
||||||
},
|
|
||||||
new Item
|
|
||||||
{
|
|
||||||
Id = sortingTableId,
|
|
||||||
Template = ItemTpl.SORTINGTABLE_SORTING_TABLE
|
|
||||||
},
|
|
||||||
new Item
|
new Item
|
||||||
{
|
{
|
||||||
Id = hideoutCustomizationStashId,
|
Id = hideoutCustomizationStashId,
|
||||||
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION
|
Template = ItemTpl.HIDEOUTAREACONTAINER_CUSTOMIZATION,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
Equipment = equipmentId,
|
Equipment = equipmentId,
|
||||||
Stash = stashId,
|
Stash = stashId,
|
||||||
@@ -162,7 +162,7 @@ public class BotInventoryGenerator(
|
|||||||
HideoutAreaStashes = new Dictionary<string, string>(),
|
HideoutAreaStashes = new Dictionary<string, string>(),
|
||||||
FastPanel = new Dictionary<string, string>(),
|
FastPanel = new Dictionary<string, string>(),
|
||||||
FavoriteItems = [],
|
FavoriteItems = [],
|
||||||
HideoutCustomizationStashId = hideoutCustomizationStashId
|
HideoutCustomizationStashId = hideoutCustomizationStashId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,24 +177,42 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="botLevel">Level of bot</param>
|
/// <param name="botLevel">Level of bot</param>
|
||||||
/// <param name="chosenGameVersion">Game version for bot, only really applies for PMCs</param>
|
/// <param name="chosenGameVersion">Game version for bot, only really applies for PMCs</param>
|
||||||
/// <param name="raidConfig">RadiConfig</param>
|
/// <param name="raidConfig">RadiConfig</param>
|
||||||
public void GenerateAndAddEquipmentToBot(string sessionId, BotTypeInventory templateInventory, Chances wornItemChances, string botRole,
|
public void GenerateAndAddEquipmentToBot(
|
||||||
BotBaseInventory botInventory, int botLevel, string chosenGameVersion, bool isPmc, GetRaidConfigurationRequestData? raidConfig)
|
string sessionId,
|
||||||
|
BotTypeInventory templateInventory,
|
||||||
|
Chances wornItemChances,
|
||||||
|
string botRole,
|
||||||
|
BotBaseInventory botInventory,
|
||||||
|
int botLevel,
|
||||||
|
string chosenGameVersion,
|
||||||
|
bool isPmc,
|
||||||
|
GetRaidConfigurationRequestData? raidConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_botConfig.Equipment.TryGetValue(_botGeneratorHelper.GetBotEquipmentRole(botRole), out var botEquipConfig);
|
_botConfig.Equipment.TryGetValue(
|
||||||
|
_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
|
||||||
if (
|
if (
|
||||||
randomistionDetails?.NighttimeChanges is not null &&
|
randomistionDetails?.NighttimeChanges is not null
|
||||||
raidConfig is not null &&
|
&& raidConfig is not null
|
||||||
_weatherHelper.IsNightTime(raidConfig.TimeVariant, raidConfig.Location)
|
&& _weatherHelper.IsNightTime(raidConfig.TimeVariant, raidConfig.Location)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
foreach (var equipmentSlotKvP in randomistionDetails.NighttimeChanges.EquipmentModsModifiers)
|
foreach (
|
||||||
|
var equipmentSlotKvP in randomistionDetails.NighttimeChanges.EquipmentModsModifiers
|
||||||
|
)
|
||||||
// Never let mod chance go outside 0 - 100
|
// Never let mod chance go outside 0 - 100
|
||||||
{
|
{
|
||||||
randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] = Math.Min(
|
randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] = Math.Min(
|
||||||
Math.Max(randomistionDetails.EquipmentMods[equipmentSlotKvP.Key] + equipmentSlotKvP.Value, 0),
|
Math.Max(
|
||||||
|
randomistionDetails.EquipmentMods[equipmentSlotKvP.Key]
|
||||||
|
+ equipmentSlotKvP.Value,
|
||||||
|
0
|
||||||
|
),
|
||||||
100
|
100
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -204,7 +222,6 @@ public class BotInventoryGenerator(
|
|||||||
var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
|
var pmcProfile = _profileHelper.GetPmcProfile(sessionId);
|
||||||
var botEquipmentRole = _botGeneratorHelper.GetBotEquipmentRole(botRole);
|
var botEquipmentRole = _botGeneratorHelper.GetBotEquipmentRole(botRole);
|
||||||
|
|
||||||
|
|
||||||
// Iterate over all equipment slots of bot, do it in specifc order to reduce conflicts
|
// Iterate over all equipment slots of bot, do it in specifc order to reduce conflicts
|
||||||
// e.g. ArmorVest should be generated after TactivalVest
|
// e.g. ArmorVest should be generated after TactivalVest
|
||||||
// or FACE_COVER before HEADWEAR
|
// or FACE_COVER before HEADWEAR
|
||||||
@@ -228,12 +245,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -244,20 +261,24 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
RootEquipmentSlot = EquipmentSlots.Pockets,
|
RootEquipmentSlot = EquipmentSlots.Pockets,
|
||||||
// Unheard profiles have unique sized pockets
|
// Unheard profiles have unique sized pockets
|
||||||
RootEquipmentPool = GetPocketPoolByGameEdition(chosenGameVersion, templateInventory, isPmc),
|
RootEquipmentPool = GetPocketPoolByGameEdition(
|
||||||
|
chosenGameVersion,
|
||||||
|
templateInventory,
|
||||||
|
isPmc
|
||||||
|
),
|
||||||
ModPool = templateInventory.Mods,
|
ModPool = templateInventory.Mods,
|
||||||
SpawnChances = wornItemChances,
|
SpawnChances = wornItemChances,
|
||||||
BotData = new BotData
|
BotData = new BotData
|
||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE, ItemTpl.POCKETS_LARGE],
|
GenerateModsBlacklist = [ItemTpl.POCKETS_1X4_TUE, ItemTpl.POCKETS_LARGE],
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -272,12 +293,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -292,12 +313,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -312,12 +333,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -332,12 +353,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -372,12 +393,12 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
Inventory = botInventory,
|
Inventory = botInventory,
|
||||||
BotEquipmentConfig = botEquipConfig,
|
BotEquipmentConfig = botEquipConfig,
|
||||||
RandomisationDetails = randomistionDetails,
|
RandomisationDetails = randomistionDetails,
|
||||||
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1
|
GeneratingPlayerLevel = pmcProfile?.Info?.Level ?? 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -389,13 +410,14 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="templateInventory"></param>
|
/// <param name="templateInventory"></param>
|
||||||
/// <param name="isPmc">is bot a PMC</param>
|
/// <param name="isPmc">is bot a PMC</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected Dictionary<string, double> GetPocketPoolByGameEdition(string chosenGameVersion, BotTypeInventory templateInventory, bool isPmc)
|
protected Dictionary<string, double> GetPocketPoolByGameEdition(
|
||||||
|
string chosenGameVersion,
|
||||||
|
BotTypeInventory templateInventory,
|
||||||
|
bool isPmc
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return chosenGameVersion == GameEditions.UNHEARD && isPmc
|
return chosenGameVersion == GameEditions.UNHEARD && isPmc
|
||||||
? new Dictionary<string, double>
|
? new Dictionary<string, double> { [ItemTpl.POCKETS_1X4_TUE] = 1 }
|
||||||
{
|
|
||||||
[ItemTpl.POCKETS_1X4_TUE] = 1
|
|
||||||
}
|
|
||||||
: templateInventory.Equipment.GetValueOrDefault(EquipmentSlots.Pockets);
|
: templateInventory.Equipment.GetValueOrDefault(EquipmentSlots.Pockets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,7 +426,10 @@ 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(Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment, string botRole)
|
public void FilterRigsToThoseWithProtection(
|
||||||
|
Dictionary<EquipmentSlots, Dictionary<string, 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))
|
||||||
@@ -414,7 +439,9 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Unable to filter to only armored rigs as bot: {botRole} has none in pool");
|
_logger.Debug(
|
||||||
|
$"Unable to filter to only armored rigs as bot: {botRole} has none in pool"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -429,8 +456,11 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="templateEquipment">Equipment to filter TacticalVest by</param>
|
/// <param name="templateEquipment">Equipment to filter TacticalVest by</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>
|
||||||
/// <param name="allowEmptyResult">Should the function return all rigs when 0 unarmored are found</param>
|
/// <param name="allowEmptyResult">Should the function return all rigs when 0 unarmored are found</param>
|
||||||
public void FilterRigsToThoseWithoutProtection(Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment, string botRole,
|
public void FilterRigsToThoseWithoutProtection(
|
||||||
bool allowEmptyResult = true)
|
Dictionary<EquipmentSlots, Dictionary<string, double>> templateEquipment,
|
||||||
|
string botRole,
|
||||||
|
bool allowEmptyResult = true
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest]
|
var tacVestsWithoutArmor = templateEquipment[EquipmentSlots.TacticalVest]
|
||||||
.Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key))
|
.Where(kvp => !_itemHelper.ItemHasSlots(kvp.Key))
|
||||||
@@ -440,7 +470,9 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Unable to filter to only unarmored rigs as bot: {botRole} has none in pool");
|
_logger.Debug(
|
||||||
|
$"Unable to filter to only unarmored rigs as bot: {botRole} has none in pool"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -458,7 +490,9 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
double? spawnChance = _slotsToCheck.Contains(settings.RootEquipmentSlot.ToString())
|
double? spawnChance = _slotsToCheck.Contains(settings.RootEquipmentSlot.ToString())
|
||||||
? 100
|
? 100
|
||||||
: settings.SpawnChances.EquipmentChances.GetValueOrDefault(settings.RootEquipmentSlot.ToString());
|
: settings.SpawnChances.EquipmentChances.GetValueOrDefault(
|
||||||
|
settings.RootEquipmentSlot.ToString()
|
||||||
|
);
|
||||||
|
|
||||||
if (!spawnChance.HasValue)
|
if (!spawnChance.HasValue)
|
||||||
{
|
{
|
||||||
@@ -489,12 +523,16 @@ public class BotInventoryGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chosenItemTpl = _weightedRandomHelper.GetWeightedValue(settings.RootEquipmentPool);
|
var chosenItemTpl = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
settings.RootEquipmentPool
|
||||||
|
);
|
||||||
var dbResult = _itemHelper.GetItem(chosenItemTpl);
|
var dbResult = _itemHelper.GetItem(chosenItemTpl);
|
||||||
|
|
||||||
if (!dbResult.Key)
|
if (!dbResult.Key)
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("bot-missing_item_template", chosenItemTpl));
|
_logger.Error(
|
||||||
|
_localisationService.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}");
|
||||||
@@ -544,7 +582,10 @@ 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(pickedItemDb, settings.BotData.Role)
|
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(
|
||||||
|
pickedItemDb,
|
||||||
|
settings.BotData.Role
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
var botEquipBlacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
|
var botEquipBlacklist = _botEquipmentFilterService.GetBotEquipmentBlacklist(
|
||||||
@@ -553,9 +594,13 @@ public class BotInventoryGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Edge case: Filter the armor items mod pool if bot exists in config dict + config has armor slot
|
// Edge case: Filter the armor items mod pool if bot exists in config dict + config has armor slot
|
||||||
if (_botConfig.Equipment.ContainsKey(settings.BotData.EquipmentRole) &&
|
if (
|
||||||
settings.RandomisationDetails?.RandomisedArmorSlots != null &&
|
_botConfig.Equipment.ContainsKey(settings.BotData.EquipmentRole)
|
||||||
settings.RandomisationDetails.RandomisedArmorSlots.Contains(settings.RootEquipmentSlot.ToString()))
|
&& settings.RandomisationDetails?.RandomisedArmorSlots != null
|
||||||
|
&& settings.RandomisationDetails.RandomisedArmorSlots.Contains(
|
||||||
|
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(
|
||||||
@@ -564,7 +609,9 @@ public class BotInventoryGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemIsOnGenerateModBlacklist = settings.GenerateModsBlacklist != null && settings.GenerateModsBlacklist.Contains(pickedItemDb.Id);
|
var itemIsOnGenerateModBlacklist =
|
||||||
|
settings.GenerateModsBlacklist != null
|
||||||
|
&& 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 (pickedItemDb.Properties?.Slots?.Count > 0 && !itemIsOnGenerateModBlacklist)
|
if (pickedItemDb.Properties?.Slots?.Count > 0 && !itemIsOnGenerateModBlacklist)
|
||||||
{
|
{
|
||||||
@@ -595,7 +642,10 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="itemTpl">Item mod pool is being retrieved and filtered</param>
|
/// <param name="itemTpl">Item mod pool is being retrieved and filtered</param>
|
||||||
/// <param name="equipmentBlacklist">Blacklist to filter mod pool with</param>
|
/// <param name="equipmentBlacklist">Blacklist to filter mod pool with</param>
|
||||||
/// <returns>Filtered pool of mods</returns>
|
/// <returns>Filtered pool of mods</returns>
|
||||||
public Dictionary<string, HashSet<string>> GetFilteredDynamicModsForItem(string itemTpl, Dictionary<string, HashSet<string>> equipmentBlacklist)
|
public Dictionary<string, HashSet<string>> GetFilteredDynamicModsForItem(
|
||||||
|
string itemTpl,
|
||||||
|
Dictionary<string, HashSet<string>> equipmentBlacklist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var modPool = _botEquipmentModPoolService.GetModsForGearSlot(itemTpl);
|
var modPool = _botEquipmentModPoolService.GetModsForGearSlot(itemTpl);
|
||||||
foreach (var modSlot in modPool)
|
foreach (var modSlot in modPool)
|
||||||
@@ -605,14 +655,16 @@ public class BotInventoryGenerator(
|
|||||||
{
|
{
|
||||||
blacklistedMods = [];
|
blacklistedMods = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
// Get mods not on blacklist
|
// Get mods not on blacklist
|
||||||
var filteredMods = modPool[modSlot.Key].Where(slotName => !blacklistedMods.Contains(slotName));
|
var filteredMods = modPool[modSlot.Key]
|
||||||
|
.Where(slotName => !blacklistedMods.Contains(slotName));
|
||||||
if (!filteredMods.Any())
|
if (!filteredMods.Any())
|
||||||
{
|
{
|
||||||
_logger.Warning($"Filtering {modSlot.Key} pool resulting in 0 items, skipping filter");
|
_logger.Warning(
|
||||||
|
$"Filtering {modSlot.Key} pool resulting in 0 items, skipping filter"
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,14 +685,24 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="isPmc">Is the bot being generated as a pmc</param>
|
/// <param name="isPmc">Is the bot being generated as a pmc</param>
|
||||||
/// <param name="itemGenerationLimitsMinMax">Limits for items the bot can have</param>
|
/// <param name="itemGenerationLimitsMinMax">Limits for items the bot can have</param>
|
||||||
/// <param name="botLevel">level of bot having weapon generated</param>
|
/// <param name="botLevel">level of bot having weapon generated</param>
|
||||||
public void GenerateAndAddWeaponsToBot(BotTypeInventory templateInventory, Chances equipmentChances, string sessionId, BotBaseInventory botInventory,
|
public void GenerateAndAddWeaponsToBot(
|
||||||
string botRole, bool isPmc, Generation itemGenerationLimitsMinMax, int botLevel)
|
BotTypeInventory templateInventory,
|
||||||
|
Chances equipmentChances,
|
||||||
|
string sessionId,
|
||||||
|
BotBaseInventory botInventory,
|
||||||
|
string botRole,
|
||||||
|
bool isPmc,
|
||||||
|
Generation itemGenerationLimitsMinMax,
|
||||||
|
int botLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var weaponSlotsToFill = GetDesiredWeaponsForBot(equipmentChances);
|
var weaponSlotsToFill = GetDesiredWeaponsForBot(equipmentChances);
|
||||||
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 (desiredWeapons.ShouldSpawn && templateInventory.Equipment[desiredWeapons.Slot].Any())
|
if (
|
||||||
|
desiredWeapons.ShouldSpawn && templateInventory.Equipment[desiredWeapons.Slot].Any()
|
||||||
|
)
|
||||||
{
|
{
|
||||||
AddWeaponAndMagazinesToInventory(
|
AddWeaponAndMagazinesToInventory(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -664,24 +726,32 @@ public class BotInventoryGenerator(
|
|||||||
/// <returns>What slots bot should have weapons generated for</returns>
|
/// <returns>What slots bot should have weapons generated for</returns>
|
||||||
public List<DesiredWeapons> GetDesiredWeaponsForBot(Chances equipmentChances)
|
public List<DesiredWeapons> GetDesiredWeaponsForBot(Chances equipmentChances)
|
||||||
{
|
{
|
||||||
var shouldSpawnPrimary = _randomUtil.GetChance100(equipmentChances.EquipmentChances["FirstPrimaryWeapon"]);
|
var shouldSpawnPrimary = _randomUtil.GetChance100(
|
||||||
|
equipmentChances.EquipmentChances["FirstPrimaryWeapon"]
|
||||||
|
);
|
||||||
return
|
return
|
||||||
[
|
[
|
||||||
new DesiredWeapons
|
new DesiredWeapons
|
||||||
{
|
{
|
||||||
Slot = EquipmentSlots.FirstPrimaryWeapon,
|
Slot = EquipmentSlots.FirstPrimaryWeapon,
|
||||||
ShouldSpawn = shouldSpawnPrimary
|
ShouldSpawn = shouldSpawnPrimary,
|
||||||
},
|
},
|
||||||
new DesiredWeapons
|
new DesiredWeapons
|
||||||
{
|
{
|
||||||
Slot = EquipmentSlots.SecondPrimaryWeapon,
|
Slot = EquipmentSlots.SecondPrimaryWeapon,
|
||||||
ShouldSpawn = shouldSpawnPrimary && _randomUtil.GetChance100(equipmentChances.EquipmentChances["SecondPrimaryWeapon"])
|
ShouldSpawn =
|
||||||
|
shouldSpawnPrimary
|
||||||
|
&& _randomUtil.GetChance100(
|
||||||
|
equipmentChances.EquipmentChances["SecondPrimaryWeapon"]
|
||||||
|
),
|
||||||
},
|
},
|
||||||
new DesiredWeapons
|
new DesiredWeapons
|
||||||
{
|
{
|
||||||
Slot = EquipmentSlots.Holster,
|
Slot = EquipmentSlots.Holster,
|
||||||
ShouldSpawn = !shouldSpawnPrimary || _randomUtil.GetChance100(equipmentChances.EquipmentChances["Holster"]) // No primary = force pistol
|
ShouldSpawn =
|
||||||
}
|
!shouldSpawnPrimary
|
||||||
|
|| _randomUtil.GetChance100(equipmentChances.EquipmentChances["Holster"]), // No primary = force pistol
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,9 +767,17 @@ public class BotInventoryGenerator(
|
|||||||
/// <param name="isPmc">Is the bot being generated as a pmc</param>
|
/// <param name="isPmc">Is the bot being generated as a pmc</param>
|
||||||
/// <param name="itemGenerationWeights"></param>
|
/// <param name="itemGenerationWeights"></param>
|
||||||
/// <param name="botLevel"></param>
|
/// <param name="botLevel"></param>
|
||||||
public void AddWeaponAndMagazinesToInventory(string sessionId, DesiredWeapons weaponSlot, BotTypeInventory templateInventory, BotBaseInventory botInventory,
|
public void AddWeaponAndMagazinesToInventory(
|
||||||
Chances equipmentChances, string botRole,
|
string sessionId,
|
||||||
bool isPmc, Generation itemGenerationWeights, int botLevel)
|
DesiredWeapons weaponSlot,
|
||||||
|
BotTypeInventory templateInventory,
|
||||||
|
BotBaseInventory botInventory,
|
||||||
|
Chances equipmentChances,
|
||||||
|
string botRole,
|
||||||
|
bool isPmc,
|
||||||
|
Generation itemGenerationWeights,
|
||||||
|
int botLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var generatedWeapon = _botWeaponGenerator.GenerateRandomWeapon(
|
var generatedWeapon = _botWeaponGenerator.GenerateRandomWeapon(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -725,15 +803,7 @@ public class BotInventoryGenerator(
|
|||||||
|
|
||||||
public class DesiredWeapons
|
public class DesiredWeapons
|
||||||
{
|
{
|
||||||
public EquipmentSlots Slot
|
public EquipmentSlots Slot { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ShouldSpawn
|
public bool ShouldSpawn { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,25 +24,28 @@ 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(MinMax<int> levelDetails, BotGenerationDetails botGenerationDetails, BotBase bot)
|
public RandomisedBotLevelResult GenerateBotLevel(
|
||||||
|
MinMax<int> levelDetails,
|
||||||
|
BotGenerationDetails botGenerationDetails,
|
||||||
|
BotBase bot
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!botGenerationDetails.IsPmc.GetValueOrDefault(false))
|
if (!botGenerationDetails.IsPmc.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
return new RandomisedBotLevelResult
|
return new RandomisedBotLevelResult { Exp = 0, Level = 1 };
|
||||||
{
|
|
||||||
Exp = 0,
|
|
||||||
Level = 1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var expTable = _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
|
var expTable = _databaseService.GetGlobals().Configuration.Exp.Level.ExperienceTable;
|
||||||
var botLevelRange = GetRelativePmcBotLevelRange(botGenerationDetails, levelDetails, expTable.Length);
|
var botLevelRange = GetRelativePmcBotLevelRange(
|
||||||
|
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)
|
ChooseBotLevel(botLevelRange.Min, botLevelRange.Max, 1, 1.15).ToString()
|
||||||
.ToString()
|
|
||||||
); // TODO - nasty double to string to int conversion
|
); // TODO - nasty double to string to int conversion
|
||||||
for (var i = 0; i < level; i++)
|
for (var i = 0; i < level; i++)
|
||||||
{
|
{
|
||||||
@@ -55,11 +58,7 @@ public class BotLevelGenerator(
|
|||||||
exp += _randomUtil.GetInt(0, expTable[level].Experience.Value - 1);
|
exp += _randomUtil.GetInt(0, expTable[level].Experience.Value - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RandomisedBotLevelResult
|
return new RandomisedBotLevelResult { Level = level, Exp = exp };
|
||||||
{
|
|
||||||
Level = level,
|
|
||||||
Exp = exp
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double ChooseBotLevel(double min, double max, int shift, double number)
|
public double ChooseBotLevel(double min, double max, int shift, double number)
|
||||||
@@ -74,7 +73,11 @@ public class BotLevelGenerator(
|
|||||||
/// <param name="levelDetails"></param>
|
/// <param name="levelDetails"></param>
|
||||||
/// <param name="maxAvailableLevel">Max level allowed</param>
|
/// <param name="maxAvailableLevel">Max level allowed</param>
|
||||||
/// <returns>A MinMax of the lowest and highest level to generate the bots</returns>
|
/// <returns>A MinMax of the lowest and highest level to generate the bots</returns>
|
||||||
public MinMax<int> GetRelativePmcBotLevelRange(BotGenerationDetails botGenerationDetails, MinMax<int> levelDetails, int maxAvailableLevel)
|
public MinMax<int> GetRelativePmcBotLevelRange(
|
||||||
|
BotGenerationDetails botGenerationDetails,
|
||||||
|
MinMax<int> levelDetails,
|
||||||
|
int maxAvailableLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var levelOverride = botGenerationDetails.LocationSpecificPmcLevelOverride;
|
var levelOverride = botGenerationDetails.LocationSpecificPmcLevelOverride;
|
||||||
|
|
||||||
@@ -93,12 +96,14 @@ public class BotLevelGenerator(
|
|||||||
|
|
||||||
// Get min level relative to player if value exists
|
// Get min level relative to player if value exists
|
||||||
var minLevel = botGenerationDetails.PlayerLevel.HasValue
|
var minLevel = botGenerationDetails.PlayerLevel.HasValue
|
||||||
? botGenerationDetails.PlayerLevel.Value - botGenerationDetails.BotRelativeLevelDeltaMin.Value
|
? botGenerationDetails.PlayerLevel.Value
|
||||||
|
- botGenerationDetails.BotRelativeLevelDeltaMin.Value
|
||||||
: 1 - botGenerationDetails.BotRelativeLevelDeltaMin.Value;
|
: 1 - botGenerationDetails.BotRelativeLevelDeltaMin.Value;
|
||||||
|
|
||||||
// Get max level relative to player if value exists
|
// Get max level relative to player if value exists
|
||||||
var maxLevel = botGenerationDetails.PlayerLevel.HasValue
|
var maxLevel = botGenerationDetails.PlayerLevel.HasValue
|
||||||
? botGenerationDetails.PlayerLevel.Value + botGenerationDetails.BotRelativeLevelDeltaMax.Value
|
? botGenerationDetails.PlayerLevel.Value
|
||||||
|
+ botGenerationDetails.BotRelativeLevelDeltaMax.Value
|
||||||
: 1 + botGenerationDetails.BotRelativeLevelDeltaMin.Value;
|
: 1 + botGenerationDetails.BotRelativeLevelDeltaMin.Value;
|
||||||
|
|
||||||
// Bound the level to the min/max possible
|
// Bound the level to the min/max possible
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class BotLootGenerator(
|
|||||||
return new ItemSpawnLimitSettings
|
return new ItemSpawnLimitSettings
|
||||||
{
|
{
|
||||||
CurrentLimits = limitsForBotDict,
|
CurrentLimits = limitsForBotDict,
|
||||||
GlobalLimits = GetItemSpawnLimitsForBotType(botRole)
|
GlobalLimits = GetItemSpawnLimitsForBotType(botRole),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,33 +67,46 @@ public class BotLootGenerator(
|
|||||||
/// <param name="botRole">Role of bot, e.g. asssult</param>
|
/// <param name="botRole">Role of bot, e.g. asssult</param>
|
||||||
/// <param name="botInventory">Inventory to add loot to</param>
|
/// <param name="botInventory">Inventory to add loot to</param>
|
||||||
/// <param name="botLevel">Level of bot</param>
|
/// <param name="botLevel">Level of bot</param>
|
||||||
public void GenerateLoot(string sessionId, BotType botJsonTemplate, bool isPmc, string botRole, BotBaseInventory botInventory, int botLevel)
|
public void GenerateLoot(
|
||||||
|
string sessionId,
|
||||||
|
BotType botJsonTemplate,
|
||||||
|
bool isPmc,
|
||||||
|
string botRole,
|
||||||
|
BotBaseInventory botInventory,
|
||||||
|
int botLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Limits on item types to be added as loot
|
// Limits on item types to be added as loot
|
||||||
var itemCounts = botJsonTemplate.BotGeneration?.Items;
|
var itemCounts = botJsonTemplate.BotGeneration?.Items;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
itemCounts?.BackpackLoot.Weights is null ||
|
itemCounts?.BackpackLoot.Weights is null
|
||||||
itemCounts.PocketLoot.Weights is null ||
|
|| itemCounts.PocketLoot.Weights is null
|
||||||
itemCounts.VestLoot.Weights is null ||
|
|| itemCounts.VestLoot.Weights is null
|
||||||
itemCounts.SpecialItems.Weights is null ||
|
|| itemCounts.SpecialItems.Weights is null
|
||||||
itemCounts.Healing.Weights is null ||
|
|| itemCounts.Healing.Weights is null
|
||||||
itemCounts.Drugs.Weights is null ||
|
|| itemCounts.Drugs.Weights is null
|
||||||
itemCounts.Food.Weights is null ||
|
|| itemCounts.Food.Weights is null
|
||||||
itemCounts.Drink.Weights is null ||
|
|| itemCounts.Drink.Weights is null
|
||||||
itemCounts.Currency.Weights is null ||
|
|| itemCounts.Currency.Weights is null
|
||||||
itemCounts.Stims.Weights is null ||
|
|| itemCounts.Stims.Weights is null
|
||||||
itemCounts.Grenades.Weights is null
|
|| itemCounts.Grenades.Weights is null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("bot-unable_to_generate_bot_loot", botRole));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("bot-unable_to_generate_bot_loot", botRole)
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var backpackLootCount = _weightedRandomHelper.GetWeightedValue(itemCounts.BackpackLoot.Weights);
|
var backpackLootCount = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
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(itemCounts.SpecialItems.Weights);
|
var specialLootItemCount = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
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);
|
||||||
@@ -127,7 +140,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Special items
|
// Special items
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Special, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.Special,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
specialLootItemCount,
|
specialLootItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -138,7 +156,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Healing items / Meds
|
// Healing items / Meds
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.HealingItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.HealingItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
healingItemCount,
|
healingItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -151,7 +174,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Drugs
|
// Drugs
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.DrugItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.DrugItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
drugItemCount,
|
drugItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -164,7 +192,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Food
|
// Food
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.FoodItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.FoodItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
foodItemCount,
|
foodItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -177,7 +210,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Drink
|
// Drink
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.DrinkItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.DrinkItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
drinkItemCount,
|
drinkItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -190,7 +228,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Currency
|
// Currency
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.CurrencyItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.CurrencyItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
currencyItemCount,
|
currencyItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -203,7 +246,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Stims
|
// Stims
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.StimItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.StimItems,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
containersBotHasAvailable,
|
containersBotHasAvailable,
|
||||||
stimItemCount,
|
stimItemCount,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -216,7 +264,12 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// Grenades
|
// Grenades
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.GrenadeItems, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
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,
|
||||||
@@ -316,7 +369,12 @@ public class BotLootGenerator(
|
|||||||
if (!isPmc || (isPmc && _pmcConfig.AddSecureContainerLootFromBotConfig))
|
if (!isPmc || (isPmc && _pmcConfig.AddSecureContainerLootFromBotConfig))
|
||||||
{
|
{
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
_botLootCacheService.GetLootFromCache(botRole, isPmc, LootCacheType.Secure, botJsonTemplate),
|
_botLootCacheService.GetLootFromCache(
|
||||||
|
botRole,
|
||||||
|
isPmc,
|
||||||
|
LootCacheType.Secure,
|
||||||
|
botJsonTemplate
|
||||||
|
),
|
||||||
[EquipmentSlots.SecuredContainer],
|
[EquipmentSlots.SecuredContainer],
|
||||||
50,
|
50,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -337,7 +395,8 @@ public class BotLootGenerator(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchingValue = _pmcConfig?.LootItemLimitsRub?.FirstOrDefault(minMaxValue => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
var matchingValue = _pmcConfig?.LootItemLimitsRub?.FirstOrDefault(minMaxValue =>
|
||||||
|
botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
||||||
);
|
);
|
||||||
|
|
||||||
return matchingValue;
|
return matchingValue;
|
||||||
@@ -357,7 +416,8 @@ public class BotLootGenerator(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var matchingValue = _pmcConfig.MaxBackpackLootTotalRub.FirstOrDefault(minMaxValue => botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
var matchingValue = _pmcConfig.MaxBackpackLootTotalRub.FirstOrDefault(minMaxValue =>
|
||||||
|
botLevel >= minMaxValue.Min && botLevel <= minMaxValue.Max
|
||||||
);
|
);
|
||||||
return matchingValue?.Value;
|
return matchingValue?.Value;
|
||||||
}
|
}
|
||||||
@@ -367,11 +427,17 @@ 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(BotBaseInventory botInventory)
|
protected HashSet<EquipmentSlots> GetAvailableContainersBotCanStoreItemsIn(
|
||||||
|
BotBaseInventory botInventory
|
||||||
|
)
|
||||||
{
|
{
|
||||||
HashSet<EquipmentSlots> result = [EquipmentSlots.Pockets];
|
HashSet<EquipmentSlots> result = [EquipmentSlots.Pockets];
|
||||||
|
|
||||||
if ((botInventory.Items ?? []).Any(item => item.SlotId == nameof(EquipmentSlots.TacticalVest)))
|
if (
|
||||||
|
(botInventory.Items ?? []).Any(item =>
|
||||||
|
item.SlotId == nameof(EquipmentSlots.TacticalVest)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
result.Add(EquipmentSlots.TacticalVest);
|
result.Add(EquipmentSlots.TacticalVest);
|
||||||
}
|
}
|
||||||
@@ -393,10 +459,7 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
// surv12
|
// surv12
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
new Dictionary<string, double>
|
new Dictionary<string, double> { { "5d02797c86f774203f38e30a", 1 } },
|
||||||
{
|
|
||||||
{ "5d02797c86f774203f38e30a", 1 }
|
|
||||||
},
|
|
||||||
[EquipmentSlots.SecuredContainer],
|
[EquipmentSlots.SecuredContainer],
|
||||||
1,
|
1,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -408,10 +471,7 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
// AFAK
|
// AFAK
|
||||||
AddLootFromPool(
|
AddLootFromPool(
|
||||||
new Dictionary<string, double>
|
new Dictionary<string, double> { { "60098ad7c2240c0fe85c570a", 1 } },
|
||||||
{
|
|
||||||
{ "60098ad7c2240c0fe85c570a", 1 }
|
|
||||||
},
|
|
||||||
[EquipmentSlots.SecuredContainer],
|
[EquipmentSlots.SecuredContainer],
|
||||||
10,
|
10,
|
||||||
botInventory,
|
botInventory,
|
||||||
@@ -434,8 +494,7 @@ public class BotLootGenerator(
|
|||||||
/// <param name="containersIdFull"></param>
|
/// <param name="containersIdFull"></param>
|
||||||
/// <param name="totalValueLimitRub">Total value of loot allowed in roubles</param>
|
/// <param name="totalValueLimitRub">Total value of loot allowed in roubles</param>
|
||||||
/// <param name="isPmc">Is bot being generated for a pmc</param>
|
/// <param name="isPmc">Is bot being generated for a pmc</param>
|
||||||
protected void AddLootFromPool
|
protected void AddLootFromPool(
|
||||||
(
|
|
||||||
Dictionary<string, double> pool,
|
Dictionary<string, double> pool,
|
||||||
HashSet<EquipmentSlots> equipmentSlots,
|
HashSet<EquipmentSlots> equipmentSlots,
|
||||||
double totalItemCount,
|
double totalItemCount,
|
||||||
@@ -471,12 +530,17 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
if (!key)
|
if (!key)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}");
|
_logger.Warning(
|
||||||
|
$"Unable to process item tpl: {weightedItemTpl} for slots: {equipmentSlots} on bot: {botRole}"
|
||||||
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemSpawnLimits is not null && ItemHasReachedSpawnLimit(itemToAddTemplate, botRole, itemSpawnLimits))
|
if (
|
||||||
|
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);
|
||||||
@@ -492,14 +556,19 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
Id = newRootItemId,
|
Id = newRootItemId,
|
||||||
Template = itemToAddTemplate?.Id ?? string.Empty,
|
Template = itemToAddTemplate?.Id ?? string.Empty,
|
||||||
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(itemToAddTemplate, botRole)
|
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(
|
||||||
}
|
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(_botConfig.WalletLoot.ChancePercent);
|
var addCurrencyToWallet = _randomUtil.GetChance100(
|
||||||
|
_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
|
||||||
@@ -552,7 +621,9 @@ 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($"Unable to add: {totalItemCount} items to bot as it lacks a container to include them");
|
_logger.Debug(
|
||||||
|
$"Unable to add: {totalItemCount} items to bot as it lacks a container to include them"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -564,9 +635,9 @@ public class BotLootGenerator(
|
|||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
$"Failed placing item: {itemToAddTemplate.Id} - {itemToAddTemplate.Name}: {i} of: {totalItemCount} items into: {botRole} " +
|
$"Failed placing item: {itemToAddTemplate.Id} - {itemToAddTemplate.Name}: {i} of: {totalItemCount} items into: {botRole} "
|
||||||
$"containers: {string.Join(",", equipmentSlots)}. Tried: {fitItemIntoContainerAttempts} " +
|
+ $"containers: {string.Join(",", equipmentSlots)}. Tried: {fitItemIntoContainerAttempts} "
|
||||||
$"times, reason: {itemAddedResult}, skipping"
|
+ $"times, reason: {itemAddedResult}, skipping"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,19 +680,20 @@ public class BotLootGenerator(
|
|||||||
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(_botConfig.WalletLoot.StackSizeWeight);
|
var chosenStackCount = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
_botConfig.WalletLoot.StackSizeWeight
|
||||||
|
);
|
||||||
List<Item> items =
|
List<Item> items =
|
||||||
[
|
[
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = _weightedRandomHelper.GetWeightedValue(_botConfig.WalletLoot.CurrencyWeight),
|
Template = _weightedRandomHelper.GetWeightedValue(
|
||||||
|
_botConfig.WalletLoot.CurrencyWeight
|
||||||
|
),
|
||||||
ParentId = walletId,
|
ParentId = walletId,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = int.Parse(chosenStackCount) },
|
||||||
{
|
},
|
||||||
StackObjectsCount = int.Parse(chosenStackCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
result.Add(items);
|
result.Add(items);
|
||||||
}
|
}
|
||||||
@@ -636,7 +708,12 @@ 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(TemplateItem? itemToAddTemplate, List<Item> itemToAddChildrenTo, bool isPmc, string botRole)
|
public void AddRequiredChildItemsToParent(
|
||||||
|
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))
|
||||||
@@ -672,7 +749,8 @@ public class BotLootGenerator(
|
|||||||
/// <param name="isPmc">are we generating for a pmc</param>
|
/// <param name="isPmc">are we generating for a pmc</param>
|
||||||
/// <param name="botLevel"></param>
|
/// <param name="botLevel"></param>
|
||||||
/// <param name="containersIdFull"></param>
|
/// <param name="containersIdFull"></param>
|
||||||
public void AddLooseWeaponsToInventorySlot(string sessionId,
|
public void AddLooseWeaponsToInventorySlot(
|
||||||
|
string sessionId,
|
||||||
BotBaseInventory botInventory,
|
BotBaseInventory botInventory,
|
||||||
EquipmentSlots equipmentSlot,
|
EquipmentSlots equipmentSlot,
|
||||||
BotTypeInventory? templateInventory,
|
BotTypeInventory? templateInventory,
|
||||||
@@ -680,14 +758,15 @@ public class BotLootGenerator(
|
|||||||
string botRole,
|
string botRole,
|
||||||
bool isPmc,
|
bool isPmc,
|
||||||
int botLevel,
|
int botLevel,
|
||||||
HashSet<string>? containersIdFull)
|
HashSet<string>? containersIdFull
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var chosenWeaponType = _randomUtil.GetArrayValue<string>(
|
var chosenWeaponType = _randomUtil.GetArrayValue<string>(
|
||||||
[
|
[
|
||||||
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
||||||
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
||||||
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
EquipmentSlots.FirstPrimaryWeapon.ToString(),
|
||||||
EquipmentSlots.Holster.ToString()
|
EquipmentSlots.Holster.ToString(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
var randomisedWeaponCount = _randomUtil.GetInt(
|
var randomisedWeaponCount = _randomUtil.GetInt(
|
||||||
@@ -716,7 +795,9 @@ public class BotLootGenerator(
|
|||||||
var weaponRootItem = generatedWeapon.Weapon?.FirstOrDefault();
|
var weaponRootItem = generatedWeapon.Weapon?.FirstOrDefault();
|
||||||
if (weaponRootItem is null)
|
if (weaponRootItem is null)
|
||||||
{
|
{
|
||||||
_logger.Error($"Generated loose weapon: {chosenWeaponType} for: {botRole} level: {botLevel} was null, skipping");
|
_logger.Error(
|
||||||
|
$"Generated loose weapon: {chosenWeaponType} for: {botRole} level: {botLevel} was null, skipping"
|
||||||
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -733,7 +814,9 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Failed to add additional weapon: {weaponRootItem.Id} to bot backpack, reason: {result.ToString()}");
|
_logger.Debug(
|
||||||
|
$"Failed to add additional weapon: {weaponRootItem.Id} to bot backpack, reason: {result.ToString()}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -746,7 +829,11 @@ 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(TemplateItem? itemTemplate, string botRole, ItemSpawnLimitSettings? itemSpawnLimits)
|
protected bool ItemHasReachedSpawnLimit(
|
||||||
|
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)
|
||||||
@@ -768,7 +855,6 @@ public class BotLootGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Use tryAdd to see if it exists, and automatically add 1
|
// Use tryAdd to see if it exists, and automatically add 1
|
||||||
if (!itemSpawnLimits.CurrentLimits.TryAdd(idToCheckFor, 1))
|
if (!itemSpawnLimits.CurrentLimits.TryAdd(idToCheckFor, 1))
|
||||||
// if it does exist, come in here and increment
|
// if it does exist, come in here and increment
|
||||||
@@ -777,10 +863,11 @@ public class BotLootGenerator(
|
|||||||
itemSpawnLimits.CurrentLimits[idToCheckFor]++;
|
itemSpawnLimits.CurrentLimits[idToCheckFor]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if over limit
|
// Check if over limit
|
||||||
var currentLimitCount = itemSpawnLimits.CurrentLimits[idToCheckFor];
|
var currentLimitCount = itemSpawnLimits.CurrentLimits[idToCheckFor];
|
||||||
if (itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor])
|
if (
|
||||||
|
itemSpawnLimits.CurrentLimits[idToCheckFor] > itemSpawnLimits.GlobalLimits[idToCheckFor]
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// 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)
|
||||||
@@ -794,7 +881,7 @@ public class BotLootGenerator(
|
|||||||
{
|
{
|
||||||
botRole,
|
botRole,
|
||||||
itemName = itemTemplate.Name,
|
itemName = itemTemplate.Name,
|
||||||
attempts = currentLimitCount
|
attempts = currentLimitCount,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -827,7 +914,9 @@ public class BotLootGenerator(
|
|||||||
|
|
||||||
_itemHelper.AddUpdObjectToItem(moneyItem);
|
_itemHelper.AddUpdObjectToItem(moneyItem);
|
||||||
|
|
||||||
moneyItem.Upd.StackObjectsCount = int.Parse(_weightedRandomHelper.GetWeightedValue(currencyWeight));
|
moneyItem.Upd.StackObjectsCount = int.Parse(
|
||||||
|
_weightedRandomHelper.GetWeightedValue(currencyWeight)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -862,7 +951,12 @@ public class BotLootGenerator(
|
|||||||
return _botConfig.ItemSpawnLimits[botRole.ToLower()];
|
return _botConfig.ItemSpawnLimits[botRole.ToLower()];
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Warning(_localisationService.GetText("bot-unable_to_find_spawn_limits_fallback_to_defaults", botRole));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"bot-unable_to_find_spawn_limits_fallback_to_defaults",
|
||||||
|
botRole
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return new Dictionary<string, double>();
|
return new Dictionary<string, double>();
|
||||||
}
|
}
|
||||||
@@ -873,7 +967,10 @@ 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 string? GetMatchingIdFromSpawnLimits(TemplateItem itemTemplate, Dictionary<string, double> spawnLimits)
|
public string? GetMatchingIdFromSpawnLimits(
|
||||||
|
TemplateItem itemTemplate,
|
||||||
|
Dictionary<string, double> spawnLimits
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (spawnLimits.ContainsKey(itemTemplate.Id))
|
if (spawnLimits.ContainsKey(itemTemplate.Id))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
protected const string _modMagazineSlotId = "mod_magazine";
|
protected const string _modMagazineSlotId = "mod_magazine";
|
||||||
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
|
protected BotConfig _botConfig = _configServer.GetConfig<BotConfig>();
|
||||||
protected IEnumerable<IInventoryMagGen> _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents);
|
protected IEnumerable<IInventoryMagGen> _inventoryMagGenComponents = MagGenSetUp(
|
||||||
|
inventoryMagGenComponents
|
||||||
|
);
|
||||||
protected PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
|
protected PmcConfig _pmcConfig = _configServer.GetConfig<PmcConfig>();
|
||||||
protected RepairConfig _repairConfig = _configServer.GetConfig<RepairConfig>();
|
protected RepairConfig _repairConfig = _configServer.GetConfig<RepairConfig>();
|
||||||
|
|
||||||
@@ -59,8 +61,16 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="isPmc">Is weapon generated for a pmc</param>
|
/// <param name="isPmc">Is weapon generated for a pmc</param>
|
||||||
/// <param name="botLevel"></param>
|
/// <param name="botLevel"></param>
|
||||||
/// <returns>GenerateWeaponResult object</returns>
|
/// <returns>GenerateWeaponResult object</returns>
|
||||||
public GenerateWeaponResult GenerateRandomWeapon(string sessionId, string equipmentSlot, BotTypeInventory botTemplateInventory, string weaponParentId,
|
public GenerateWeaponResult GenerateRandomWeapon(
|
||||||
Dictionary<string, double> modChances, string botRole, bool isPmc, int botLevel)
|
string sessionId,
|
||||||
|
string equipmentSlot,
|
||||||
|
BotTypeInventory botTemplateInventory,
|
||||||
|
string weaponParentId,
|
||||||
|
Dictionary<string, double> modChances,
|
||||||
|
string botRole,
|
||||||
|
bool isPmc,
|
||||||
|
int botLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var weaponTpl = PickWeightedWeaponTemplateFromPool(equipmentSlot, botTemplateInventory);
|
var weaponTpl = PickWeightedWeaponTemplateFromPool(equipmentSlot, botTemplateInventory);
|
||||||
return GenerateWeaponByTpl(
|
return GenerateWeaponByTpl(
|
||||||
@@ -82,7 +92,10 @@ 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 string PickWeightedWeaponTemplateFromPool(string equipmentSlot, BotTypeInventory botTemplateInventory)
|
public string PickWeightedWeaponTemplateFromPool(
|
||||||
|
string equipmentSlot,
|
||||||
|
BotTypeInventory botTemplateInventory
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!Enum.TryParse(equipmentSlot, out EquipmentSlots key))
|
if (!Enum.TryParse(equipmentSlot, out EquipmentSlots key))
|
||||||
{
|
{
|
||||||
@@ -106,8 +119,17 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="isPmc">Is weapon being generated for a PMC.</param>
|
/// <param name="isPmc">Is weapon being generated for a PMC.</param>
|
||||||
/// <param name="botLevel">The level of the bot.</param>
|
/// <param name="botLevel">The level of the bot.</param>
|
||||||
/// <returns>GenerateWeaponResult object.</returns>
|
/// <returns>GenerateWeaponResult object.</returns>
|
||||||
public GenerateWeaponResult? GenerateWeaponByTpl(string sessionId, string weaponTpl, string slotName, BotTypeInventory botTemplateInventory,
|
public GenerateWeaponResult? GenerateWeaponByTpl(
|
||||||
string weaponParentId, Dictionary<string, double> modChances, string botRole, bool isPmc, int botLevel)
|
string sessionId,
|
||||||
|
string weaponTpl,
|
||||||
|
string slotName,
|
||||||
|
BotTypeInventory botTemplateInventory,
|
||||||
|
string weaponParentId,
|
||||||
|
Dictionary<string, double> modChances,
|
||||||
|
string botRole,
|
||||||
|
bool isPmc,
|
||||||
|
int botLevel
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var modPool = botTemplateInventory.Mods;
|
var modPool = botTemplateInventory.Mods;
|
||||||
var weaponItemTemplate = _itemHelper.GetItem(weaponTpl).Value;
|
var weaponItemTemplate = _itemHelper.GetItem(weaponTpl).Value;
|
||||||
@@ -166,11 +188,11 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
Role = botRole,
|
Role = botRole,
|
||||||
Level = botLevel,
|
Level = botLevel,
|
||||||
EquipmentRole = botEquipmentRole
|
EquipmentRole = botEquipmentRole,
|
||||||
},
|
},
|
||||||
ModLimits = modLimits,
|
ModLimits = modLimits,
|
||||||
WeaponStats = new WeaponStats(),
|
WeaponStats = new WeaponStats(),
|
||||||
ConflictingItemTpls = new HashSet<string>()
|
ConflictingItemTpls = new HashSet<string>(),
|
||||||
};
|
};
|
||||||
weaponWithModsArray = _botEquipmentModGenerator.GenerateModsForWeapon(
|
weaponWithModsArray = _botEquipmentModGenerator.GenerateModsForWeapon(
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -191,7 +213,9 @@ public class BotWeaponGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tempList = _cloner.Clone(weaponWithModsArray.Where(item => item.SlotId == _modMagazineSlotId));
|
var tempList = _cloner.Clone(
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@@ -199,11 +223,18 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add cartridge(s) to gun chamber(s)
|
// Add cartridge(s) to gun chamber(s)
|
||||||
if (weaponItemTemplate.Properties?.Chambers?.Count > 0 &&
|
if (
|
||||||
weaponItemTemplate.Properties.Chambers.FirstOrDefault().Props.Filters.FirstOrDefault().Filter.Contains(ammoTpl))
|
weaponItemTemplate.Properties?.Chambers?.Count > 0
|
||||||
|
&& weaponItemTemplate
|
||||||
|
.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 => chamberSlot.Name);
|
var chamberSlotNames = weaponItemTemplate.Properties.Chambers.Select(chamberSlot =>
|
||||||
|
chamberSlot.Name
|
||||||
|
);
|
||||||
AddCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames.ToList());
|
AddCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +259,7 @@ public class BotWeaponGenerator(
|
|||||||
ChosenAmmoTemplate = ammoTpl,
|
ChosenAmmoTemplate = ammoTpl,
|
||||||
ChosenUbglAmmoTemplate = ubglAmmoTpl,
|
ChosenUbglAmmoTemplate = ubglAmmoTpl,
|
||||||
WeaponMods = modPool,
|
WeaponMods = modPool,
|
||||||
WeaponTemplate = weaponItemTemplate
|
WeaponTemplate = weaponItemTemplate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +270,11 @@ 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(List<Item> weaponWithModsList, string ammoTemplate, List<string> chamberSlotIds)
|
protected void AddCartridgeToChamber(
|
||||||
|
List<Item> weaponWithModsList,
|
||||||
|
string ammoTemplate,
|
||||||
|
List<string> chamberSlotIds
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var slotId in chamberSlotIds)
|
foreach (var slotId in chamberSlotIds)
|
||||||
{
|
{
|
||||||
@@ -254,10 +289,7 @@ public class BotWeaponGenerator(
|
|||||||
Template = ammoTemplate,
|
Template = ammoTemplate,
|
||||||
ParentId = weaponWithModsList[0].Id,
|
ParentId = weaponWithModsList[0].Id,
|
||||||
SlotId = slotId,
|
SlotId = slotId,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 1 },
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -265,10 +297,7 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
// Already exists, update values
|
// Already exists, update values
|
||||||
existingItemWithSlot.Template = ammoTemplate;
|
existingItemWithSlot.Template = ammoTemplate;
|
||||||
existingItemWithSlot.Upd = new Upd
|
existingItemWithSlot.Upd = new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,8 +312,13 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponItemTemplate">Database template for weapon</param>
|
/// <param name="weaponItemTemplate">Database template for weapon</param>
|
||||||
/// <param name="botRole">For durability values</param>
|
/// <param name="botRole">For durability values</param>
|
||||||
/// <returns>Base weapon item in a list</returns>
|
/// <returns>Base weapon item in a list</returns>
|
||||||
protected List<Item> ConstructWeaponBaseList(string weaponTemplate, string weaponParentId, string equipmentSlot, TemplateItem weaponItemTemplate,
|
protected List<Item> ConstructWeaponBaseList(
|
||||||
string botRole)
|
string weaponTemplate,
|
||||||
|
string weaponParentId,
|
||||||
|
string equipmentSlot,
|
||||||
|
TemplateItem weaponItemTemplate,
|
||||||
|
string botRole
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
[
|
[
|
||||||
@@ -294,8 +328,11 @@ public class BotWeaponGenerator(
|
|||||||
Template = weaponTemplate,
|
Template = weaponTemplate,
|
||||||
ParentId = weaponParentId,
|
ParentId = weaponParentId,
|
||||||
SlotId = equipmentSlot,
|
SlotId = equipmentSlot,
|
||||||
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(weaponItemTemplate, botRole)
|
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(
|
||||||
}
|
weaponItemTemplate,
|
||||||
|
botRole
|
||||||
|
),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,10 +345,21 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="itemTemplate">Item template</param>
|
/// <param name="itemTemplate">Item template</param>
|
||||||
/// <param name="botRole">Bot role</param>
|
/// <param name="botRole">Bot role</param>
|
||||||
/// <returns>List of weapon mods</returns>
|
/// <returns>List of weapon mods</returns>
|
||||||
protected List<Item> GetPresetWeaponMods(string weaponTemplate, string equipmentSlot, string weaponParentId, TemplateItem itemTemplate, string botRole)
|
protected List<Item> GetPresetWeaponMods(
|
||||||
|
string weaponTemplate,
|
||||||
|
string equipmentSlot,
|
||||||
|
string weaponParentId,
|
||||||
|
TemplateItem itemTemplate,
|
||||||
|
string botRole
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Invalid weapon generated, fallback to preset
|
// Invalid weapon generated, fallback to preset
|
||||||
_logger.Warning(_localisationService.GetText("bot-weapon_generated_incorrect_using_default", $"{weaponTemplate} - {itemTemplate.Name}"));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"bot-weapon_generated_incorrect_using_default",
|
||||||
|
$"{weaponTemplate} - {itemTemplate.Name}"
|
||||||
|
)
|
||||||
|
);
|
||||||
List<Item> weaponMods = [];
|
List<Item> weaponMods = [];
|
||||||
|
|
||||||
// TODO: Preset weapons trigger a lot of warnings regarding missing ammo in magazines & such
|
// TODO: Preset weapons trigger a lot of warnings regarding missing ammo in magazines & such
|
||||||
@@ -331,13 +379,18 @@ 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(itemTemplate, botRole);
|
parentItem.Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(
|
||||||
|
itemTemplate,
|
||||||
|
botRole
|
||||||
|
);
|
||||||
preset.Items[0] = parentItem;
|
preset.Items[0] = parentItem;
|
||||||
weaponMods.AddRange(preset.Items);
|
weaponMods.AddRange(preset.Items);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("bot-missing_weapon_preset", weaponTemplate));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("bot-missing_weapon_preset", weaponTemplate)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return weaponMods;
|
return weaponMods;
|
||||||
@@ -360,10 +413,16 @@ 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 (var modSlotTemplate in modTemplate.Properties.Slots?.Where(slot => slot.Required.GetValueOrDefault(false)) ?? [])
|
foreach (
|
||||||
|
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 => weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName);
|
var hasWeaponSlotItem = weaponItemList.Any(weaponItem =>
|
||||||
|
weaponItem.ParentId == mod.Id && weaponItem.SlotId == slotName
|
||||||
|
);
|
||||||
if (!hasWeaponSlotItem)
|
if (!hasWeaponSlotItem)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
@@ -374,7 +433,7 @@ public class BotWeaponGenerator(
|
|||||||
modSlot = modSlotTemplate.Name,
|
modSlot = modSlotTemplate.Name,
|
||||||
modName = modTemplate.Name,
|
modName = modTemplate.Name,
|
||||||
slotId = mod.SlotId,
|
slotId = mod.SlotId,
|
||||||
botRole
|
botRole,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -395,16 +454,27 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="magWeights">Magazine weights for count to add to inventory</param>
|
/// <param name="magWeights">Magazine weights for count to add to inventory</param>
|
||||||
/// <param name="inventory">Inventory to add magazines to</param>
|
/// <param name="inventory">Inventory to add magazines to</param>
|
||||||
/// <param name="botRole">The bot type we're generating extra mags for</param>
|
/// <param name="botRole">The bot type we're generating extra mags for</param>
|
||||||
public void AddExtraMagazinesToInventory(GenerateWeaponResult generatedWeaponResult, GenerationData magWeights, BotBaseInventory inventory, string botRole)
|
public void AddExtraMagazinesToInventory(
|
||||||
|
GenerateWeaponResult generatedWeaponResult,
|
||||||
|
GenerationData magWeights,
|
||||||
|
BotBaseInventory inventory,
|
||||||
|
string botRole
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var weaponAndMods = generatedWeaponResult.Weapon;
|
var weaponAndMods = generatedWeaponResult.Weapon;
|
||||||
var weaponTemplate = generatedWeaponResult.WeaponTemplate;
|
var weaponTemplate = generatedWeaponResult.WeaponTemplate;
|
||||||
var magazineTpl = GetMagazineTemplateFromWeaponTemplate(weaponAndMods, weaponTemplate, botRole);
|
var magazineTpl = GetMagazineTemplateFromWeaponTemplate(
|
||||||
|
weaponAndMods,
|
||||||
|
weaponTemplate,
|
||||||
|
botRole
|
||||||
|
);
|
||||||
|
|
||||||
var magTemplate = _itemHelper.GetItem(magazineTpl).Value;
|
var magTemplate = _itemHelper.GetItem(magazineTpl).Value;
|
||||||
if (magTemplate is null)
|
if (magTemplate is null)
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("bot-unable_to_find_magazine_item", magazineTpl));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("bot-unable_to_find_magazine_item", magazineTpl)
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -414,7 +484,10 @@ public class BotWeaponGenerator(
|
|||||||
if (!ammoTemplate.Key)
|
if (!ammoTemplate.Key)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("bot-unable_to_find_ammo_item", generatedWeaponResult.ChosenAmmoTemplate)
|
_localisationService.GetText(
|
||||||
|
"bot-unable_to_find_ammo_item",
|
||||||
|
generatedWeaponResult.ChosenAmmoTemplate
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -434,7 +507,8 @@ public class BotWeaponGenerator(
|
|||||||
inventory
|
inventory
|
||||||
);
|
);
|
||||||
|
|
||||||
_inventoryMagGenComponents.FirstOrDefault(v => v.CanHandleInventoryMagGen(inventoryMagGenModel))
|
_inventoryMagGenComponents
|
||||||
|
.FirstOrDefault(v => v.CanHandleInventoryMagGen(inventoryMagGenModel))
|
||||||
.Process(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)
|
||||||
@@ -452,7 +526,11 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="weaponMods">Weapon list with mods</param>
|
/// <param name="weaponMods">Weapon list with mods</param>
|
||||||
/// <param name="generatedWeaponResult">Result of weapon generation</param>
|
/// <param name="generatedWeaponResult">Result of weapon generation</param>
|
||||||
/// <param name="inventory">Bot inventory to add grenades to</param>
|
/// <param name="inventory">Bot inventory to add grenades to</param>
|
||||||
protected void AddUbglGrenadesToBotInventory(List<Item> weaponMods, GenerateWeaponResult generatedWeaponResult, BotBaseInventory inventory)
|
protected void AddUbglGrenadesToBotInventory(
|
||||||
|
List<Item> weaponMods,
|
||||||
|
GenerateWeaponResult generatedWeaponResult,
|
||||||
|
BotBaseInventory inventory
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Find ubgl mod item + get details of it from db
|
// Find ubgl mod item + get details of it from db
|
||||||
var ubglMod = weaponMods.FirstOrDefault(x => x.SlotId == "mod_launcher");
|
var ubglMod = weaponMods.FirstOrDefault(x => x.SlotId == "mod_launcher");
|
||||||
@@ -461,16 +539,14 @@ public class BotWeaponGenerator(
|
|||||||
// Define min/max of how many grenades bot will have
|
// Define min/max of how many grenades bot will have
|
||||||
GenerationData ubglMinMax = new()
|
GenerationData ubglMinMax = new()
|
||||||
{
|
{
|
||||||
Weights = new Dictionary<double, double>
|
Weights = new Dictionary<double, double> { { 1, 1 }, { 2, 1 } },
|
||||||
{
|
Whitelist = new Dictionary<string, double>(),
|
||||||
{ 1, 1 },
|
|
||||||
{ 2, 1 }
|
|
||||||
},
|
|
||||||
Whitelist = new Dictionary<string, double>()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// get ammo template from db
|
// get ammo template from db
|
||||||
var ubglAmmoDbTemplate = _itemHelper.GetItem(generatedWeaponResult.ChosenUbglAmmoTemplate).Value;
|
var ubglAmmoDbTemplate = _itemHelper
|
||||||
|
.GetItem(generatedWeaponResult.ChosenUbglAmmoTemplate)
|
||||||
|
.Value;
|
||||||
|
|
||||||
// Add greandes to bot inventory
|
// Add greandes to bot inventory
|
||||||
var ubglAmmoGenModel = new InventoryMagGen(
|
var ubglAmmoGenModel = new InventoryMagGen(
|
||||||
@@ -495,16 +571,18 @@ 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(int stackCount, string ammoTpl, int stackSize, BotBaseInventory inventory)
|
protected void AddAmmoToSecureContainer(
|
||||||
|
int stackCount,
|
||||||
|
string ammoTpl,
|
||||||
|
int stackSize,
|
||||||
|
BotBaseInventory inventory
|
||||||
|
)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < stackCount; i++)
|
for (var i = 0; i < stackCount; i++)
|
||||||
{
|
{
|
||||||
var id = _hashUtil.Generate();
|
var id = _hashUtil.Generate();
|
||||||
_botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
|
_botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
|
||||||
new HashSet<EquipmentSlots>
|
new HashSet<EquipmentSlots> { EquipmentSlots.SecuredContainer },
|
||||||
{
|
|
||||||
EquipmentSlots.SecuredContainer
|
|
||||||
},
|
|
||||||
id,
|
id,
|
||||||
ammoTpl,
|
ammoTpl,
|
||||||
new List<Item>
|
new List<Item>
|
||||||
@@ -513,11 +591,8 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
Template = ammoTpl,
|
Template = ammoTpl,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = stackSize },
|
||||||
{
|
},
|
||||||
StackObjectsCount = stackSize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
inventory
|
inventory
|
||||||
);
|
);
|
||||||
@@ -531,7 +606,11 @@ 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 string GetMagazineTemplateFromWeaponTemplate(List<Item> weaponMods, TemplateItem weaponTemplate, string botRole)
|
protected string GetMagazineTemplateFromWeaponTemplate(
|
||||||
|
List<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)
|
||||||
@@ -550,16 +629,14 @@ public class BotWeaponGenerator(
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"bot-weapon_missing_magazine_or_chamber",
|
"bot-weapon_missing_magazine_or_chamber",
|
||||||
new
|
new { weaponId = weaponTemplate.Id, botRole }
|
||||||
{
|
|
||||||
weaponId = weaponTemplate.Id,
|
|
||||||
botRole
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultMagTplId = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weaponTemplate);
|
var defaultMagTplId = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(
|
||||||
|
weaponTemplate
|
||||||
|
);
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
@@ -579,10 +656,16 @@ 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 string? GetWeightedCompatibleAmmo(Dictionary<string, Dictionary<string, double>> cartridgePool, TemplateItem weaponTemplate)
|
protected string? GetWeightedCompatibleAmmo(
|
||||||
|
Dictionary<string, Dictionary<string, double>> cartridgePool,
|
||||||
|
TemplateItem weaponTemplate
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var desiredCaliber = GetWeaponCaliber(weaponTemplate);
|
var desiredCaliber = GetWeaponCaliber(weaponTemplate);
|
||||||
if (!cartridgePool.TryGetValue(desiredCaliber, out var cartridgePoolForWeapon) || cartridgePoolForWeapon?.Count == 0)
|
if (
|
||||||
|
!cartridgePool.TryGetValue(desiredCaliber, out var cartridgePoolForWeapon)
|
||||||
|
|| cartridgePoolForWeapon?.Count == 0
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
@@ -593,7 +676,7 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
weaponId = weaponTemplate.Id,
|
weaponId = weaponTemplate.Id,
|
||||||
weaponName = weaponTemplate.Name,
|
weaponName = weaponTemplate.Name,
|
||||||
defaultAmmo = weaponTemplate.Properties.DefAmmo
|
defaultAmmo = weaponTemplate.Properties.DefAmmo,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -605,7 +688,9 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get cartridges the weapons first chamber allow
|
// Get cartridges the weapons first chamber allow
|
||||||
var compatibleCartridgesInTemplate = GetCompatibleCartridgesFromWeaponTemplate(weaponTemplate);
|
var compatibleCartridgesInTemplate = GetCompatibleCartridgesFromWeaponTemplate(
|
||||||
|
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
|
||||||
{
|
{
|
||||||
@@ -626,7 +711,9 @@ 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(weaponTemplate);
|
var compatibleCartridgesInMagazine = GetCompatibleCartridgesFromMagazineTemplate(
|
||||||
|
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
|
||||||
@@ -634,7 +721,9 @@ 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.GetItem(compatibleCartridgesInMagazine.FirstOrDefault()).Value.Properties.Caliber;
|
var magazineCaliberData = _itemHelper
|
||||||
|
.GetItem(compatibleCartridgesInMagazine.FirstOrDefault())
|
||||||
|
.Value.Properties.Caliber;
|
||||||
cartridgePoolForWeapon = cartridgePool[magazineCaliberData];
|
cartridgePoolForWeapon = cartridgePool[magazineCaliberData];
|
||||||
|
|
||||||
foreach (var cartridgeKvP in cartridgePoolForWeapon)
|
foreach (var cartridgeKvP in cartridgePoolForWeapon)
|
||||||
@@ -664,7 +753,9 @@ public class BotWeaponGenerator(
|
|||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
ArgumentNullException.ThrowIfNull(weaponTemplate);
|
||||||
|
|
||||||
var cartridges = weaponTemplate.Properties?.Chambers?.FirstOrDefault()?.Props?.Filters?[0].Filter;
|
var cartridges = weaponTemplate
|
||||||
|
.Properties?.Chambers?.FirstOrDefault()
|
||||||
|
?.Props?.Filters?[0].Filter;
|
||||||
if (cartridges is not null)
|
if (cartridges is not null)
|
||||||
{
|
{
|
||||||
return cartridges;
|
return cartridges;
|
||||||
@@ -680,26 +771,39 @@ 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<string> GetCompatibleCartridgesFromMagazineTemplate(TemplateItem weaponTemplate)
|
protected HashSet<string> GetCompatibleCartridgesFromMagazineTemplate(
|
||||||
|
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 => slot.Name == "mod_magazine");
|
var magazineSlot = weaponTemplate.Properties.Slots?.FirstOrDefault(slot =>
|
||||||
|
slot.Name == "mod_magazine"
|
||||||
|
);
|
||||||
if (magazineSlot is null)
|
if (magazineSlot is null)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var magazineTemplate = _itemHelper.GetItem(magazineSlot.Props?.Filters.FirstOrDefault()?.Filter?.FirstOrDefault());
|
var magazineTemplate = _itemHelper.GetItem(
|
||||||
|
magazineSlot.Props?.Filters.FirstOrDefault()?.Filter?.FirstOrDefault()
|
||||||
|
);
|
||||||
if (!magazineTemplate.Key)
|
if (!magazineTemplate.Key)
|
||||||
{
|
{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 = magazineTemplate.Value.Properties.Slots.FirstOrDefault()?.Props?.Filters.FirstOrDefault()?.Filter
|
var cartridges =
|
||||||
?? magazineTemplate.Value.Properties.Cartridges.FirstOrDefault()?.Props?.Filters.FirstOrDefault()?.Filter;
|
magazineTemplate
|
||||||
|
.Value.Properties.Slots.FirstOrDefault()
|
||||||
|
?.Props?.Filters.FirstOrDefault()
|
||||||
|
?.Filter
|
||||||
|
?? magazineTemplate
|
||||||
|
.Value.Properties.Cartridges.FirstOrDefault()
|
||||||
|
?.Props?.Filters.FirstOrDefault()
|
||||||
|
?.Filter;
|
||||||
|
|
||||||
return cartridges ?? [];
|
return cartridges ?? [];
|
||||||
}
|
}
|
||||||
@@ -729,9 +833,7 @@ public class BotWeaponGenerator(
|
|||||||
var ammoInChamber = _itemHelper.GetItem(
|
var ammoInChamber = _itemHelper.GetItem(
|
||||||
weaponTemplate.Properties.Chambers[0].Props.Filters[0].Filter.FirstOrDefault()
|
weaponTemplate.Properties.Chambers[0].Props.Filters[0].Filter.FirstOrDefault()
|
||||||
);
|
);
|
||||||
return !ammoInChamber.Key
|
return !ammoInChamber.Key ? null : ammoInChamber.Value.Properties.Caliber;
|
||||||
? null
|
|
||||||
: ammoInChamber.Value.Properties.Caliber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -743,12 +845,18 @@ 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(List<Item> weaponMods, Item magazine, string cartridgeTemplate)
|
protected void FillExistingMagazines(
|
||||||
|
List<Item> weaponMods,
|
||||||
|
Item magazine,
|
||||||
|
string 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(_localisationService.GetText("bot-unable_to_find_magazine_item", magazine.Template));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("bot-unable_to_find_magazine_item", magazine.Template)
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -765,7 +873,12 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddOrUpdateMagazinesChildWithAmmo(weaponMods, magazine, cartridgeTemplate, magazineTemplate);
|
AddOrUpdateMagazinesChildWithAmmo(
|
||||||
|
weaponMods,
|
||||||
|
magazine,
|
||||||
|
cartridgeTemplate,
|
||||||
|
magazineTemplate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,10 +897,7 @@ public class BotWeaponGenerator(
|
|||||||
Template = ubglAmmoTpl,
|
Template = ubglAmmoTpl,
|
||||||
ParentId = ubglMod.Id,
|
ParentId = ubglMod.Id,
|
||||||
SlotId = "patron_in_weapon",
|
SlotId = "patron_in_weapon",
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 1 },
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -799,9 +909,15 @@ public class BotWeaponGenerator(
|
|||||||
/// <param name="magazine">Magazine item details we're adding cartridges to</param>
|
/// <param name="magazine">Magazine item details we're adding cartridges to</param>
|
||||||
/// <param name="chosenAmmoTpl">Cartridge to put into the magazine</param>
|
/// <param name="chosenAmmoTpl">Cartridge to put into the magazine</param>
|
||||||
/// <param name="magazineTemplate">Magazines db template</param>
|
/// <param name="magazineTemplate">Magazines db template</param>
|
||||||
protected void AddOrUpdateMagazinesChildWithAmmo(List<Item> weaponWithMods, Item magazine, string chosenAmmoTpl, TemplateItem magazineTemplate)
|
protected void AddOrUpdateMagazinesChildWithAmmo(
|
||||||
|
List<Item> weaponWithMods,
|
||||||
|
Item magazine,
|
||||||
|
string chosenAmmoTpl,
|
||||||
|
TemplateItem magazineTemplate
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var magazineCartridgeChildItem = weaponWithMods.FirstOrDefault(m => m.ParentId == magazine.Id && m.SlotId == "cartridges"
|
var magazineCartridgeChildItem = weaponWithMods.FirstOrDefault(m =>
|
||||||
|
m.ParentId == magazine.Id && m.SlotId == "cartridges"
|
||||||
);
|
);
|
||||||
if (magazineCartridgeChildItem is not null)
|
if (magazineCartridgeChildItem is not null)
|
||||||
{
|
{
|
||||||
@@ -813,13 +929,20 @@ 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(magazineWithCartridges, magazineTemplate, chosenAmmoTpl, 1);
|
_itemHelper.FillMagazineWithCartridge(
|
||||||
|
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($"Unable to add cartridges: {chosenAmmoTpl} to magazine: {magazine.Id} as none found");
|
_logger.Error(
|
||||||
|
$"Unable to add cartridges: {chosenAmmoTpl} to magazine: {magazine.Id} as none found"
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -842,7 +965,9 @@ public class BotWeaponGenerator(
|
|||||||
// 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))
|
.Where(x =>
|
||||||
|
x.ParentId == magazineId && x.SlotId.StartsWith("camora", StringComparison.Ordinal)
|
||||||
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (camoras.Count == 0)
|
if (camoras.Count == 0)
|
||||||
@@ -859,10 +984,7 @@ public class BotWeaponGenerator(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
camora.Upd = new Upd
|
camora.Upd = new Upd { StackObjectsCount = 1 };
|
||||||
{
|
|
||||||
StackObjectsCount = 1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ public class FenceBaseAssortGenerator(
|
|||||||
// Item base type blacklisted
|
// Item base type blacklisted
|
||||||
if (traderConfig.Fence.Blacklist.Count > 0)
|
if (traderConfig.Fence.Blacklist.Count > 0)
|
||||||
{
|
{
|
||||||
if (traderConfig.Fence.Blacklist.Contains(rootItemDb.Id) ||
|
if (
|
||||||
itemHelper.IsOfBaseclasses(rootItemDb.Id, traderConfig.Fence.Blacklist)
|
traderConfig.Fence.Blacklist.Contains(rootItemDb.Id)
|
||||||
|
|| itemHelper.IsOfBaseclasses(rootItemDb.Id, traderConfig.Fence.Blacklist)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -69,15 +70,19 @@ public class FenceBaseAssortGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only allow rigs with no slots (carrier rigs)
|
// Only allow rigs with no slots (carrier rigs)
|
||||||
if (itemHelper.IsOfBaseclass(rootItemDb.Id, BaseClasses.VEST) &&
|
if (
|
||||||
(rootItemDb.Properties?.Slots?.Count ?? 0) > 0
|
itemHelper.IsOfBaseclass(rootItemDb.Id, BaseClasses.VEST)
|
||||||
|
&& (rootItemDb.Properties?.Slots?.Count ?? 0) > 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip seasonal event items when not in seasonal event
|
// Skip seasonal event items when not in seasonal event
|
||||||
if (traderConfig.Fence.BlacklistSeasonalItems && blockedSeasonalItems.Contains(rootItemDb.Id))
|
if (
|
||||||
|
traderConfig.Fence.BlacklistSeasonalItems
|
||||||
|
&& blockedSeasonalItems.Contains(rootItemDb.Id)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -91,11 +96,8 @@ public class FenceBaseAssortGenerator(
|
|||||||
Template = rootItemDb.Id,
|
Template = rootItemDb.Id,
|
||||||
ParentId = "hideout",
|
ParentId = "hideout",
|
||||||
SlotId = "hideout",
|
SlotId = "hideout",
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 9999999 },
|
||||||
{
|
},
|
||||||
StackObjectsCount = 9999999
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure ammo is not above penetration limit value
|
// Ensure ammo is not above penetration limit value
|
||||||
@@ -127,12 +129,17 @@ public class FenceBaseAssortGenerator(
|
|||||||
// Create barter scheme (price)
|
// Create barter scheme (price)
|
||||||
var barterSchemeToAdd = new BarterScheme
|
var barterSchemeToAdd = new BarterScheme
|
||||||
{
|
{
|
||||||
Count = Math.Round((double) fenceService.GetItemPrice(rootItemDb.Id, itemWithChildrenToAdd)),
|
Count = Math.Round(
|
||||||
Template = Money.ROUBLES
|
(double)fenceService.GetItemPrice(rootItemDb.Id, itemWithChildrenToAdd)
|
||||||
|
),
|
||||||
|
Template = Money.ROUBLES,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add barter data to base
|
// Add barter data to base
|
||||||
baseFenceAssort.BarterScheme[itemWithChildrenToAdd[0].Id] = [[barterSchemeToAdd]];
|
baseFenceAssort.BarterScheme[itemWithChildrenToAdd[0].Id] =
|
||||||
|
[
|
||||||
|
[barterSchemeToAdd],
|
||||||
|
];
|
||||||
|
|
||||||
// Add item to base
|
// Add item to base
|
||||||
baseFenceAssort.Items.AddRange(itemWithChildrenToAdd);
|
baseFenceAssort.Items.AddRange(itemWithChildrenToAdd);
|
||||||
@@ -146,7 +153,11 @@ 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 (baseFenceAssort.Items.Any(item => item.Upd != null && item.Upd.SptPresetId == defaultPreset.Id))
|
if (
|
||||||
|
baseFenceAssort.Items.Any(item =>
|
||||||
|
item.Upd != null && item.Upd.SptPresetId == defaultPreset.Id
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -167,8 +178,7 @@ public class FenceBaseAssortGenerator(
|
|||||||
mod.Upd = new Upd
|
mod.Upd = new Upd
|
||||||
{
|
{
|
||||||
StackObjectsCount = 1,
|
StackObjectsCount = 1,
|
||||||
SptPresetId =
|
SptPresetId = defaultPreset.Id, // Store preset id here so we can check it later to prevent preset dupes
|
||||||
defaultPreset.Id // Store preset id here so we can check it later to prevent preset dupes
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Updated root item, exit loop
|
// Updated root item, exit loop
|
||||||
@@ -191,9 +201,9 @@ public class FenceBaseAssortGenerator(
|
|||||||
new BarterScheme
|
new BarterScheme
|
||||||
{
|
{
|
||||||
Template = Money.ROUBLES,
|
Template = Money.ROUBLES,
|
||||||
Count = Math.Round(price * itemQualityModifier)
|
Count = Math.Round(price * itemQualityModifier),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
baseFenceAssort.LoyalLevelItems[itemAndChildren[0].Id] = 1;
|
baseFenceAssort.LoyalLevelItems[itemAndChildren[0].Id] = 1;
|
||||||
@@ -210,7 +220,12 @@ public class FenceBaseAssortGenerator(
|
|||||||
var ammoPenetrationPower = GetAmmoPenetrationPower(rootItemDb);
|
var ammoPenetrationPower = GetAmmoPenetrationPower(rootItemDb);
|
||||||
if (ammoPenetrationPower == null)
|
if (ammoPenetrationPower == null)
|
||||||
{
|
{
|
||||||
logger.Warning(localisationService.GetText("fence-unable_to_get_ammo_penetration_value", rootItemDb.Id));
|
logger.Warning(
|
||||||
|
localisationService.GetText(
|
||||||
|
"fence-unable_to_get_ammo_penetration_value",
|
||||||
|
rootItemDb.Id
|
||||||
|
)
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,13 +242,18 @@ 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.Properties.StackSlots[0].Props.Filters[0].Filter.FirstOrDefault();
|
var cartridgeTplInBox = rootItemDb
|
||||||
|
.Properties.StackSlots[0]
|
||||||
|
.Props.Filters[0]
|
||||||
|
.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(localisationService.GetText("fence-ammo_not_found_in_db", cartridgeTplInBox));
|
logger.Warning(
|
||||||
|
localisationService.GetText("fence-ammo_not_found_in_db", cartridgeTplInBox)
|
||||||
|
);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,15 +285,18 @@ public class FenceBaseAssortGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for and add required soft inserts to armors
|
// Check for and add required soft inserts to armors
|
||||||
var requiredSlots = itemDbDetails.Properties.Slots.Where(slot => slot.Required ?? false).ToList();
|
var requiredSlots = itemDbDetails
|
||||||
|
.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.GetItem(requiredSlot.Props.Filters[0].Plate).Value;
|
var modItemDbDetails = itemHelper
|
||||||
var plateTpl =
|
.GetItem(requiredSlot.Props.Filters[0].Plate)
|
||||||
requiredSlot.Props.Filters[0].Plate; // `Plate` property appears to be the 'default' item for slot
|
.Value;
|
||||||
|
var plateTpl = requiredSlot.Props.Filters[0].Plate; // `Plate` property appears to be the 'default' item for slot
|
||||||
if (string.IsNullOrEmpty(plateTpl))
|
if (string.IsNullOrEmpty(plateTpl))
|
||||||
// Some bsg plate properties are empty, skip mod
|
// Some bsg plate properties are empty, skip mod
|
||||||
{
|
{
|
||||||
@@ -291,9 +314,9 @@ public class FenceBaseAssortGenerator(
|
|||||||
Repairable = new UpdRepairable
|
Repairable = new UpdRepairable
|
||||||
{
|
{
|
||||||
Durability = modItemDbDetails.Properties.MaxDurability,
|
Durability = modItemDbDetails.Properties.MaxDurability,
|
||||||
MaxDurability = modItemDbDetails.Properties.MaxDurability
|
MaxDurability = modItemDbDetails.Properties.MaxDurability,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
armor.Add(mod);
|
armor.Add(mod);
|
||||||
@@ -301,7 +324,8 @@ public class FenceBaseAssortGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for and add plate items
|
// Check for and add plate items
|
||||||
var plateSlots = itemDbDetails.Properties.Slots.Where(slot => itemHelper.IsRemovablePlateSlot(slot.Name))
|
var plateSlots = itemDbDetails
|
||||||
|
.Properties.Slots.Where(slot => itemHelper.IsRemovablePlateSlot(slot.Name))
|
||||||
.ToList();
|
.ToList();
|
||||||
if (plateSlots.Count > 0)
|
if (plateSlots.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -327,9 +351,9 @@ public class FenceBaseAssortGenerator(
|
|||||||
Repairable = new UpdRepairable
|
Repairable = new UpdRepairable
|
||||||
{
|
{
|
||||||
Durability = modItemDbDetails.Properties.MaxDurability,
|
Durability = modItemDbDetails.Properties.MaxDurability,
|
||||||
MaxDurability = modItemDbDetails.Properties.MaxDurability
|
MaxDurability = modItemDbDetails.Properties.MaxDurability,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,14 +33,17 @@ public class LocationLootGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected readonly LocationConfig _locationConfig = _configServer.GetConfig<LocationConfig>();
|
protected readonly LocationConfig _locationConfig = _configServer.GetConfig<LocationConfig>();
|
||||||
protected readonly SeasonalEventConfig _seasonalEventConfig = _configServer.GetConfig<SeasonalEventConfig>();
|
protected readonly SeasonalEventConfig _seasonalEventConfig =
|
||||||
|
_configServer.GetConfig<SeasonalEventConfig>();
|
||||||
|
|
||||||
/// Create a list of container objects with randomised loot
|
/// Create a list of container objects with randomised loot
|
||||||
/// <param name="locationBase">Map base to generate containers for</param>
|
/// <param name="locationBase">Map base to generate containers for</param>
|
||||||
/// <param name="staticAmmoDist">Static ammo distribution</param>
|
/// <param name="staticAmmoDist">Static ammo distribution</param>
|
||||||
/// <returns>List of container objects</returns>
|
/// <returns>List of container objects</returns>
|
||||||
public List<SpawnpointTemplate> GenerateStaticContainers(LocationBase locationBase,
|
public List<SpawnpointTemplate> GenerateStaticContainers(
|
||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist)
|
LocationBase locationBase,
|
||||||
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var staticLootItemCount = 0;
|
var staticLootItemCount = 0;
|
||||||
var result = new List<SpawnpointTemplate>();
|
var result = new List<SpawnpointTemplate>();
|
||||||
@@ -52,18 +55,26 @@ public class LocationLootGenerator(
|
|||||||
if (staticWeaponsOnMapClone is null)
|
if (staticWeaponsOnMapClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("location-unable_to_find_static_weapon_for_map", locationBase.Name)
|
_localisationService.GetText(
|
||||||
|
"location-unable_to_find_static_weapon_for_map",
|
||||||
|
locationBase.Name
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add mounted weapons to output loot
|
// Add mounted weapons to output loot
|
||||||
result.AddRange(staticWeaponsOnMapClone);
|
result.AddRange(staticWeaponsOnMapClone);
|
||||||
|
|
||||||
var allStaticContainersOnMapClone = _cloner.Clone(mapData.StaticContainers.Value.StaticContainers);
|
var allStaticContainersOnMapClone = _cloner.Clone(
|
||||||
|
mapData.StaticContainers.Value.StaticContainers
|
||||||
|
);
|
||||||
if (allStaticContainersOnMapClone is null)
|
if (allStaticContainersOnMapClone is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("location-unable_to_find_static_container_for_map", locationBase.Name)
|
_localisationService.GetText(
|
||||||
|
"location-unable_to_find_static_container_for_map",
|
||||||
|
locationBase.Name
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,12 +93,16 @@ public class LocationLootGenerator(
|
|||||||
// Remove christmas items from loot data
|
// Remove christmas items from loot data
|
||||||
if (!_seasonalEventService.ChristmasEventEnabled())
|
if (!_seasonalEventService.ChristmasEventEnabled())
|
||||||
{
|
{
|
||||||
allStaticContainersOnMapClone = allStaticContainersOnMapClone.Where(item => !_seasonalEventConfig.ChristmasContainerIds.Contains(item.Template.Id)
|
allStaticContainersOnMapClone = allStaticContainersOnMapClone
|
||||||
|
.Where(item =>
|
||||||
|
!_seasonalEventConfig.ChristmasContainerIds.Contains(item.Template.Id)
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var staticRandomisableContainersOnMap = GetRandomisableContainersOnMap(allStaticContainersOnMapClone);
|
var staticRandomisableContainersOnMap = GetRandomisableContainersOnMap(
|
||||||
|
allStaticContainersOnMapClone
|
||||||
|
);
|
||||||
|
|
||||||
// Keep track of static loot count
|
// Keep track of static loot count
|
||||||
var staticContainerCount = 0;
|
var staticContainerCount = 0;
|
||||||
@@ -98,13 +113,17 @@ public class LocationLootGenerator(
|
|||||||
staticContainerCount += guaranteedContainers.Count;
|
staticContainerCount += guaranteedContainers.Count;
|
||||||
|
|
||||||
// Add loot to guaranteed containers and add to result
|
// Add loot to guaranteed containers and add to result
|
||||||
foreach (var containerWithLoot in guaranteedContainers.Select(container => AddLootToContainer(
|
foreach (
|
||||||
|
var containerWithLoot in guaranteedContainers.Select(container =>
|
||||||
|
AddLootToContainer(
|
||||||
container,
|
container,
|
||||||
staticForcedOnMapClone,
|
staticForcedOnMapClone,
|
||||||
staticLootDist.Value,
|
staticLootDist.Value,
|
||||||
staticAmmoDist,
|
staticAmmoDist,
|
||||||
locationId
|
locationId
|
||||||
)))
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
result.Add(containerWithLoot.Template);
|
result.Add(containerWithLoot.Template);
|
||||||
|
|
||||||
@@ -117,7 +136,9 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Randomisation is turned off globally or just turned off for this map
|
// Randomisation is turned off globally or just turned off for this map
|
||||||
if (!_locationConfig.ContainerRandomisationSettings.Enabled || !_locationConfig.ContainerRandomisationSettings.Maps.ContainsKey(locationId)
|
if (
|
||||||
|
!_locationConfig.ContainerRandomisationSettings.Enabled
|
||||||
|
|| !_locationConfig.ContainerRandomisationSettings.Maps.ContainsKey(locationId)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
@@ -149,15 +170,18 @@ 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(_localisationService.GetText("location-unable_to_generate_static_loot", locationId));
|
_logger.Warning(
|
||||||
|
_localisationService.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(mapData.Statics, staticRandomisableContainersOnMap);
|
var mapping = GetGroupIdToContainerMappings(
|
||||||
|
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
|
||||||
@@ -170,7 +194,9 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Group: {key} has no containers with < 100 % spawn chance to choose from, skipping");
|
_logger.Debug(
|
||||||
|
$"Group: {key} has no containers with < 100 % spawn chance to choose from, skipping"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -186,7 +212,9 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
if (_randomUtil.GetChance100(containerIdsCopy[containerId.Key] * 100))
|
if (_randomUtil.GetChance100(containerIdsCopy[containerId.Key] * 100))
|
||||||
{
|
{
|
||||||
data.ContainerIdsWithProbability[containerId.Key] = containerIdsCopy[containerId.Key];
|
data.ContainerIdsWithProbability[containerId.Key] = containerIdsCopy[
|
||||||
|
containerId.Key
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +233,8 @@ 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(staticContainer => staticContainer.Template.Id == chosenContainerId
|
var containerObject = staticRandomisableContainersOnMap.FirstOrDefault(
|
||||||
|
staticContainer => staticContainer.Template.Id == chosenContainerId
|
||||||
);
|
);
|
||||||
if (containerObject is null)
|
if (containerObject is null)
|
||||||
{
|
{
|
||||||
@@ -236,7 +265,10 @@ 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(
|
||||||
_localisationService.GetText("location-containers_generated_success", staticContainerCount)
|
_localisationService.GetText(
|
||||||
|
"location-containers_generated_success",
|
||||||
|
staticContainerCount
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -247,12 +279,15 @@ public class LocationLootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticContainers"></param>
|
/// <param name="staticContainers"></param>
|
||||||
/// <returns>StaticContainerData array</returns>
|
/// <returns>StaticContainerData array</returns>
|
||||||
protected List<StaticContainerData> GetRandomisableContainersOnMap(List<StaticContainerData> staticContainers)
|
protected List<StaticContainerData> GetRandomisableContainersOnMap(
|
||||||
|
List<StaticContainerData> staticContainers
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return staticContainers.Where(staticContainer =>
|
return staticContainers
|
||||||
staticContainer.Probability != 1 &&
|
.Where(staticContainer =>
|
||||||
!staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false) &&
|
staticContainer.Probability != 1
|
||||||
!_locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
|
&& !staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false)
|
||||||
|
&& !_locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
|
||||||
staticContainer.Template.Items.FirstOrDefault().Template
|
staticContainer.Template.Items.FirstOrDefault().Template
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -264,12 +299,15 @@ public class LocationLootGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticContainersOnMap"></param>
|
/// <param name="staticContainersOnMap"></param>
|
||||||
/// <returns>IStaticContainerData array</returns>
|
/// <returns>IStaticContainerData array</returns>
|
||||||
protected List<StaticContainerData> GetGuaranteedContainers(List<StaticContainerData> staticContainersOnMap)
|
protected List<StaticContainerData> GetGuaranteedContainers(
|
||||||
|
List<StaticContainerData> staticContainersOnMap
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return staticContainersOnMap.Where(staticContainer =>
|
return staticContainersOnMap
|
||||||
staticContainer.Probability == 1 ||
|
.Where(staticContainer =>
|
||||||
staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false) ||
|
staticContainer.Probability == 1
|
||||||
_locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
|
|| staticContainer.Template.IsAlwaysSpawn.GetValueOrDefault(false)
|
||||||
|
|| _locationConfig.ContainerRandomisationSettings.ContainerTypesToNotRandomise.Contains(
|
||||||
staticContainer.Template.Items.FirstOrDefault().Template
|
staticContainer.Template.Items.FirstOrDefault().Template
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -283,7 +321,10 @@ 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(string groupId, ContainerGroupCount containerData)
|
protected List<string> GetContainersByProbability(
|
||||||
|
string groupId,
|
||||||
|
ContainerGroupCount containerData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var chosenContainerIds = new List<string>();
|
var chosenContainerIds = new List<string>();
|
||||||
|
|
||||||
@@ -301,8 +342,7 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create probability array with all possible container ids in this group and their relative probability of spawning
|
// Create probability array with all possible container ids in this group and their relative probability of spawning
|
||||||
var containerDistribution =
|
var containerDistribution = new ProbabilityObjectArray<string, double>(_mathUtil, _cloner);
|
||||||
new ProbabilityObjectArray<string, double>(_mathUtil, _cloner);
|
|
||||||
foreach (var x in containerIds)
|
foreach (var x in containerIds)
|
||||||
{
|
{
|
||||||
var value = containerData.ContainerIdsWithProbability[x];
|
var value = containerData.ContainerIdsWithProbability[x];
|
||||||
@@ -322,7 +362,8 @@ public class LocationLootGenerator(
|
|||||||
/// <returns>dictionary keyed by groupId</returns>
|
/// <returns>dictionary keyed by groupId</returns>
|
||||||
protected Dictionary<string, ContainerGroupCount> GetGroupIdToContainerMappings(
|
protected Dictionary<string, ContainerGroupCount> GetGroupIdToContainerMappings(
|
||||||
StaticContainer staticContainerGroupData,
|
StaticContainer staticContainerGroupData,
|
||||||
List<StaticContainerData> staticContainersOnMap)
|
List<StaticContainerData> staticContainersOnMap
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Create dictionary of all group ids and choose a count of containers the map will spawn of that group
|
// Create dictionary of all group ids and choose a count of containers the map will spawn of that group
|
||||||
var mapping = new Dictionary<string, ContainerGroupCount>();
|
var mapping = new Dictionary<string, ContainerGroupCount>();
|
||||||
@@ -332,31 +373,45 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
||||||
ChosenCount = _randomUtil.GetInt(
|
ChosenCount = _randomUtil.GetInt(
|
||||||
(int) Math.Round(
|
(int)
|
||||||
groupKvP.Value.MinContainers.Value *
|
Math.Round(
|
||||||
_locationConfig.ContainerRandomisationSettings.ContainerGroupMinSizeMultiplier
|
groupKvP.Value.MinContainers.Value
|
||||||
|
* _locationConfig
|
||||||
|
.ContainerRandomisationSettings
|
||||||
|
.ContainerGroupMinSizeMultiplier
|
||||||
),
|
),
|
||||||
(int) Math.Round(
|
(int)
|
||||||
groupKvP.Value.MaxContainers.Value *
|
Math.Round(
|
||||||
_locationConfig.ContainerRandomisationSettings.ContainerGroupMaxSizeMultiplier
|
groupKvP.Value.MaxContainers.Value
|
||||||
)
|
* _locationConfig
|
||||||
|
.ContainerRandomisationSettings
|
||||||
|
.ContainerGroupMaxSizeMultiplier
|
||||||
)
|
)
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add an empty group for containers without a group id but still have a < 100% chance to spawn
|
// Add an empty group for containers without a group id but still have a < 100% chance to spawn
|
||||||
// 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(string.Empty, new ContainerGroupCount
|
mapping.Add(
|
||||||
|
string.Empty,
|
||||||
|
new ContainerGroupCount
|
||||||
{
|
{
|
||||||
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
||||||
ChosenCount = -1
|
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 (!staticContainerGroupData.Containers.TryGetValue(container.Template.Id, out var groupData))
|
if (
|
||||||
|
!staticContainerGroupData.Containers.TryGetValue(
|
||||||
|
container.Template.Id,
|
||||||
|
out var groupData
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
@@ -385,10 +440,14 @@ public class LocationLootGenerator(
|
|||||||
new ContainerGroupCount
|
new ContainerGroupCount
|
||||||
{
|
{
|
||||||
ChosenCount = 0d,
|
ChosenCount = 0d,
|
||||||
ContainerIdsWithProbability = new Dictionary<string, double>()
|
ContainerIdsWithProbability = new Dictionary<string, double>(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
mapping[groupData.GroupId].ContainerIdsWithProbability.TryAdd(container.Template.Id, container.Probability.Value);
|
mapping[groupData.GroupId]
|
||||||
|
.ContainerIdsWithProbability.TryAdd(
|
||||||
|
container.Template.Id,
|
||||||
|
container.Probability.Value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
@@ -404,7 +463,8 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="staticAmmoDist">staticAmmo.json</param>
|
/// <param name="staticAmmoDist">staticAmmo.json</param>
|
||||||
/// <param name="locationName">Name of the map to generate static loot for</param>
|
/// <param name="locationName">Name of the map to generate static loot for</param>
|
||||||
/// <returns>StaticContainerData</returns>
|
/// <returns>StaticContainerData</returns>
|
||||||
protected StaticContainerData AddLootToContainer(StaticContainerData staticContainer,
|
protected StaticContainerData AddLootToContainer(
|
||||||
|
StaticContainerData staticContainer,
|
||||||
List<StaticForced>? staticForced,
|
List<StaticForced>? staticForced,
|
||||||
Dictionary<string, StaticLootDetails> staticLootDist,
|
Dictionary<string, StaticLootDetails> staticLootDist,
|
||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||||
@@ -422,7 +482,11 @@ 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(containerTpl, staticLootDist, locationName);
|
var itemCountToAdd = GetWeightedCountOfContainerItems(
|
||||||
|
containerTpl,
|
||||||
|
staticLootDist,
|
||||||
|
locationName
|
||||||
|
);
|
||||||
if (itemCountToAdd == 0)
|
if (itemCountToAdd == 0)
|
||||||
{
|
{
|
||||||
return containerClone;
|
return containerClone;
|
||||||
@@ -468,7 +532,11 @@ 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 = _containerHelper.FindSlotForItem(containerMap, chosenItemWithChildren.Width, chosenItemWithChildren.Height);
|
var result = _containerHelper.FindSlotForItem(
|
||||||
|
containerMap,
|
||||||
|
chosenItemWithChildren.Width,
|
||||||
|
chosenItemWithChildren.Height
|
||||||
|
);
|
||||||
if (!result.Success.GetValueOrDefault(false))
|
if (!result.Success.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
if (failedToFitAttemptCount > _locationConfig.FitLootIntoContainerAttempts)
|
if (failedToFitAttemptCount > _locationConfig.FitLootIntoContainerAttempts)
|
||||||
@@ -499,7 +567,9 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
X = result.X,
|
X = result.X,
|
||||||
Y = result.Y,
|
Y = result.Y,
|
||||||
R = result.Rotation.GetValueOrDefault(false) ? ItemRotation.Vertical : ItemRotation.Horizontal
|
R = result.Rotation.GetValueOrDefault(false)
|
||||||
|
? ItemRotation.Vertical
|
||||||
|
: ItemRotation.Horizontal,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add loot to container before returning
|
// Add loot to container before returning
|
||||||
@@ -516,23 +586,21 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="staticLootDist">staticLoot.json</param>
|
/// <param name="staticLootDist">staticLoot.json</param>
|
||||||
/// <param name="locationName">Map name (to get per-map multiplier for from config)</param>
|
/// <param name="locationName">Map name (to get per-map multiplier for from config)</param>
|
||||||
/// <returns>item count</returns>
|
/// <returns>item count</returns>
|
||||||
protected int GetWeightedCountOfContainerItems(string containerTypeId,
|
protected int GetWeightedCountOfContainerItems(
|
||||||
Dictionary<string, StaticLootDetails> staticLootDist, string locationName)
|
string containerTypeId,
|
||||||
|
Dictionary<string, StaticLootDetails> staticLootDist,
|
||||||
|
string locationName
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Create probability array to calculate the total count of lootable items inside container
|
// Create probability array to calculate the total count of lootable items inside container
|
||||||
var itemCountArray =
|
var itemCountArray = new ProbabilityObjectArray<int, float?>(_mathUtil, _cloner);
|
||||||
new ProbabilityObjectArray<int, float?>(_mathUtil, _cloner);
|
|
||||||
var countDistribution = staticLootDist[containerTypeId]?.ItemCountDistribution;
|
var countDistribution = staticLootDist[containerTypeId]?.ItemCountDistribution;
|
||||||
if (countDistribution is null)
|
if (countDistribution is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"location-unable_to_find_count_distribution_for_container",
|
"location-unable_to_find_count_distribution_for_container",
|
||||||
new
|
new { containerId = containerTypeId, locationName }
|
||||||
{
|
|
||||||
containerId = containerTypeId,
|
|
||||||
locationName
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -551,7 +619,8 @@ public class LocationLootGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int) Math.Round(GetStaticLootMultiplierForLocation(locationName) * itemCountArray.Draw()[0]);
|
return (int)
|
||||||
|
Math.Round(GetStaticLootMultiplierForLocation(locationName) * itemCountArray.Draw()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -563,18 +632,23 @@ public class LocationLootGenerator(
|
|||||||
/// <returns>ProbabilityObjectArray of item tpls + probability</returns>
|
/// <returns>ProbabilityObjectArray of item tpls + probability</returns>
|
||||||
protected ProbabilityObjectArray<string, float?> GetPossibleLootItemsForContainer(
|
protected ProbabilityObjectArray<string, float?> GetPossibleLootItemsForContainer(
|
||||||
string containerTypeId,
|
string containerTypeId,
|
||||||
Dictionary<string, StaticLootDetails> staticLootDist)
|
Dictionary<string, StaticLootDetails> staticLootDist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var seasonalEventActive = _seasonalEventService.SeasonalEventEnabled();
|
var seasonalEventActive = _seasonalEventService.SeasonalEventEnabled();
|
||||||
var seasonalItemTplBlacklist = _seasonalEventService.GetInactiveSeasonalEventItems();
|
var seasonalItemTplBlacklist = _seasonalEventService.GetInactiveSeasonalEventItems();
|
||||||
|
|
||||||
var itemDistribution =
|
var itemDistribution = new ProbabilityObjectArray<string, float?>(_mathUtil, _cloner);
|
||||||
new ProbabilityObjectArray<string, float?>(_mathUtil, _cloner);
|
|
||||||
|
|
||||||
var itemContainerDistribution = staticLootDist[containerTypeId]?.ItemDistribution;
|
var itemContainerDistribution = staticLootDist[containerTypeId]?.ItemDistribution;
|
||||||
if (itemContainerDistribution is null)
|
if (itemContainerDistribution is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("location-missing_item_distribution_data", containerTypeId));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"location-missing_item_distribution_data",
|
||||||
|
containerTypeId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return itemDistribution;
|
return itemDistribution;
|
||||||
}
|
}
|
||||||
@@ -593,7 +667,9 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemDistribution.Add(new ProbabilityObject<string, float?>(icd.Tpl, icd.RelativeProbability.Value, null));
|
itemDistribution.Add(
|
||||||
|
new ProbabilityObject<string, float?>(icd.Tpl, icd.RelativeProbability.Value, null)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return itemDistribution;
|
return itemDistribution;
|
||||||
@@ -620,9 +696,11 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="staticAmmoDist"></param>
|
/// <param name="staticAmmoDist"></param>
|
||||||
/// <param name="locationName">Location to generate loot for</param>
|
/// <param name="locationName">Location to generate loot for</param>
|
||||||
/// <returns>Array of spawn points with loot in them</returns>
|
/// <returns>Array of spawn points with loot in them</returns>
|
||||||
public List<SpawnpointTemplate> GenerateDynamicLoot(LooseLoot dynamicLootDist,
|
public List<SpawnpointTemplate> GenerateDynamicLoot(
|
||||||
|
LooseLoot dynamicLootDist,
|
||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||||
string locationName)
|
string locationName
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<SpawnpointTemplate> loot = [];
|
List<SpawnpointTemplate> loot = [];
|
||||||
List<Spawnpoint> dynamicForcedSpawnPoints = [];
|
List<Spawnpoint> dynamicForcedSpawnPoints = [];
|
||||||
@@ -630,11 +708,13 @@ public class LocationLootGenerator(
|
|||||||
// Remove christmas items from loot data
|
// Remove christmas items from loot data
|
||||||
if (!_seasonalEventService.ChristmasEventEnabled())
|
if (!_seasonalEventService.ChristmasEventEnabled())
|
||||||
{
|
{
|
||||||
dynamicLootDist.Spawnpoints = dynamicLootDist.Spawnpoints.Where(point =>
|
dynamicLootDist.Spawnpoints = dynamicLootDist
|
||||||
|
.Spawnpoints.Where(point =>
|
||||||
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
|
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
dynamicLootDist.SpawnpointsForced = dynamicLootDist.SpawnpointsForced.Where(point =>
|
dynamicLootDist.SpawnpointsForced = dynamicLootDist
|
||||||
|
.SpawnpointsForced.Where(point =>
|
||||||
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
|
!point.Template.Id.StartsWith("christmas", StringComparison.OrdinalIgnoreCase)
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
@@ -642,7 +722,9 @@ 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(dynamicLootDist.Spawnpoints.Where(point => point.Template.IsAlwaysSpawn ?? false));
|
dynamicForcedSpawnPoints.AddRange(
|
||||||
|
dynamicLootDist.Spawnpoints.Where(point => point.Template.IsAlwaysSpawn ?? false)
|
||||||
|
);
|
||||||
|
|
||||||
// Add forced loot
|
// Add forced loot
|
||||||
AddForcedLoot(loot, dynamicForcedSpawnPoints, locationName, staticAmmoDist);
|
AddForcedLoot(loot, dynamicForcedSpawnPoints, locationName, staticAmmoDist);
|
||||||
@@ -651,7 +733,8 @@ public class LocationLootGenerator(
|
|||||||
|
|
||||||
// Draw from random distribution
|
// Draw from random distribution
|
||||||
var desiredSpawnPointCount = Math.Round(
|
var desiredSpawnPointCount = Math.Round(
|
||||||
GetLooseLootMultiplierForLocation(locationName) * _randomUtil.GetNormallyDistributedRandomNumber(
|
GetLooseLootMultiplierForLocation(locationName)
|
||||||
|
* _randomUtil.GetNormallyDistributedRandomNumber(
|
||||||
(double)dynamicLootDist.SpawnpointCount.Mean,
|
(double)dynamicLootDist.SpawnpointCount.Mean,
|
||||||
(double)dynamicLootDist.SpawnpointCount.Std
|
(double)dynamicLootDist.SpawnpointCount.Std
|
||||||
)
|
)
|
||||||
@@ -660,7 +743,9 @@ public class LocationLootGenerator(
|
|||||||
// Positions not in forced but have 100% chance to spawn
|
// Positions not in forced but have 100% chance to spawn
|
||||||
List<Spawnpoint> guaranteedLoosePoints = [];
|
List<Spawnpoint> guaranteedLoosePoints = [];
|
||||||
|
|
||||||
var blacklistedSpawnPoints = _locationConfig.LooseLootBlacklist.GetValueOrDefault(locationName);
|
var blacklistedSpawnPoints = _locationConfig.LooseLootBlacklist.GetValueOrDefault(
|
||||||
|
locationName
|
||||||
|
);
|
||||||
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_mathUtil, _cloner);
|
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_mathUtil, _cloner);
|
||||||
|
|
||||||
foreach (var spawnPoint in allDynamicSpawnPoints)
|
foreach (var spawnPoint in allDynamicSpawnPoints)
|
||||||
@@ -689,7 +774,13 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
spawnPointArray.Add(new ProbabilityObject<string, Spawnpoint>(spawnPoint.Template.Id, spawnPoint.Probability ?? 0, spawnPoint));
|
spawnPointArray.Add(
|
||||||
|
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
|
||||||
@@ -709,7 +800,10 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter out duplicate locationIds // prob can be done better
|
// Filter out duplicate locationIds // prob can be done better
|
||||||
chosenSpawnPoints = chosenSpawnPoints.GroupBy(spawnPoint => spawnPoint.LocationId).Select(group => group.First()).ToList();
|
chosenSpawnPoints = chosenSpawnPoints
|
||||||
|
.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;
|
||||||
@@ -724,7 +818,7 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
requested = desiredSpawnPointCount + guaranteedLoosePoints.Count,
|
requested = desiredSpawnPointCount + guaranteedLoosePoints.Count,
|
||||||
found = chosenSpawnPoints.Count,
|
found = chosenSpawnPoints.Count,
|
||||||
mapName = locationName
|
mapName = locationName,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -740,22 +834,27 @@ public class LocationLootGenerator(
|
|||||||
if (spawnPoint.Template is null)
|
if (spawnPoint.Template is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("location-missing_dynamic_template", spawnPoint.LocationId)
|
_localisationService.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.Template.Items.Where(item => !_itemFilterService.IsLootableItemBlacklisted(item.Template)
|
spawnPoint.Template.Items = spawnPoint
|
||||||
|
.Template.Items.Where(item =>
|
||||||
|
!_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 => !seasonalItemTplBlacklist.Contains(item.Template)
|
spawnPoint.Template.Items = spawnPoint
|
||||||
)
|
.Template.Items.Where(item => !seasonalItemTplBlacklist.Contains(item.Template))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +864,10 @@ public class LocationLootGenerator(
|
|||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
_localisationService.GetText("location-spawnpoint_missing_items", spawnPoint.Template.Id)
|
_localisationService.GetText(
|
||||||
|
"location-spawnpoint_missing_items",
|
||||||
|
spawnPoint.Template.Id
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,13 +886,22 @@ public class LocationLootGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
itemArray.Add(new ProbabilityObject<string, double?>(itemDist.ComposedKey.Key, itemDist.RelativeProbability ?? 0, null));
|
itemArray.Add(
|
||||||
|
new ProbabilityObject<string, double?>(
|
||||||
|
itemDist.ComposedKey.Key,
|
||||||
|
itemDist.RelativeProbability ?? 0,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemArray.Count == 0)
|
if (itemArray.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("location-loot_pool_is_empty_skipping", spawnPoint.Template.Id)
|
_localisationService.GetText(
|
||||||
|
"location-loot_pool_is_empty_skipping",
|
||||||
|
spawnPoint.Template.Id
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -822,44 +933,65 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="lootLocationTemplates">List to add forced loot spawn locations to</param>
|
/// <param name="lootLocationTemplates">List to add forced loot spawn locations to</param>
|
||||||
/// <param name="forcedSpawnPoints">Forced loot locations that must be added</param>
|
/// <param name="forcedSpawnPoints">Forced loot locations that must be added</param>
|
||||||
/// <param name="locationName">Name of map currently having force loot created for</param>
|
/// <param name="locationName">Name of map currently having force loot created for</param>
|
||||||
protected void AddForcedLoot(List<SpawnpointTemplate> lootLocationTemplates,
|
protected void AddForcedLoot(
|
||||||
List<Spawnpoint> forcedSpawnPoints, string locationName,
|
List<SpawnpointTemplate> lootLocationTemplates,
|
||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist)
|
List<Spawnpoint> forcedSpawnPoints,
|
||||||
|
string locationName,
|
||||||
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var lootToForceSingleAmountOnMap = _locationConfig.ForcedLootSingleSpawnById.GetValueOrDefault(locationName);
|
var lootToForceSingleAmountOnMap =
|
||||||
|
_locationConfig.ForcedLootSingleSpawnById.GetValueOrDefault(locationName);
|
||||||
if (lootToForceSingleAmountOnMap is not null)
|
if (lootToForceSingleAmountOnMap is not null)
|
||||||
// Process loot items defined as requiring only 1 spawn position as they appear in multiple positions on the map
|
// Process loot items defined as requiring only 1 spawn position as they appear in multiple positions on the map
|
||||||
{
|
{
|
||||||
foreach (var itemTpl in lootToForceSingleAmountOnMap)
|
foreach (var itemTpl in lootToForceSingleAmountOnMap)
|
||||||
{
|
{
|
||||||
// Get all spawn positions for item tpl in forced loot array
|
// Get all spawn positions for item tpl in forced loot array
|
||||||
var items = forcedSpawnPoints.Where(forcedSpawnPoint => forcedSpawnPoint.Template.Items.FirstOrDefault().Template == itemTpl);
|
var items = forcedSpawnPoints.Where(forcedSpawnPoint =>
|
||||||
|
forcedSpawnPoint.Template.Items.FirstOrDefault().Template == itemTpl
|
||||||
|
);
|
||||||
if (!items.Any())
|
if (!items.Any())
|
||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Unable to adjust loot item {itemTpl} as it does not exist inside {locationName} forced loot.");
|
_logger.Debug(
|
||||||
|
$"Unable to adjust loot item {itemTpl} as it does not exist inside {locationName} forced loot."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create probability array of all spawn positions for this spawn id
|
// Create probability array of all spawn positions for this spawn id
|
||||||
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_mathUtil, _cloner);
|
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(
|
||||||
|
_mathUtil,
|
||||||
|
_cloner
|
||||||
|
);
|
||||||
foreach (var si in items)
|
foreach (var si in items)
|
||||||
// use locationId as template.Id is the same across all items
|
// use locationId as template.Id is the same across all items
|
||||||
{
|
{
|
||||||
spawnPointArray.Add(new ProbabilityObject<string, Spawnpoint>(si.LocationId, si.Probability ?? 0, si));
|
spawnPointArray.Add(
|
||||||
|
new ProbabilityObject<string, Spawnpoint>(
|
||||||
|
si.LocationId,
|
||||||
|
si.Probability ?? 0,
|
||||||
|
si
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose 1 out of all found spawn positions for spawn id and add to loot array
|
// Choose 1 out of all found spawn positions for spawn id and add to loot array
|
||||||
foreach (var spawnPointLocationId in spawnPointArray.Draw(1, false))
|
foreach (var spawnPointLocationId in spawnPointArray.Draw(1, false))
|
||||||
{
|
{
|
||||||
var itemToAdd = items.FirstOrDefault(item => item.LocationId == spawnPointLocationId);
|
var itemToAdd = items.FirstOrDefault(item =>
|
||||||
|
item.LocationId == spawnPointLocationId
|
||||||
|
);
|
||||||
var lootItem = itemToAdd?.Template;
|
var lootItem = itemToAdd?.Template;
|
||||||
if (lootItem is null)
|
if (lootItem is null)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Item with spawn point id {spawnPointLocationId} could not be found, skipping");
|
_logger.Warning(
|
||||||
|
$"Item with spawn point id {spawnPointLocationId} could not be found, skipping"
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,7 +1041,8 @@ public class LocationLootGenerator(
|
|||||||
forcedLootLocation.Template.Items = createItemResult.Items;
|
forcedLootLocation.Template.Items = createItemResult.Items;
|
||||||
|
|
||||||
// Push forced location into array as long as it doesnt exist already
|
// Push forced location into array as long as it doesnt exist already
|
||||||
var existingLocation = lootLocationTemplates.Any(spawnPoint => spawnPoint.Id == locationTemplateToAdd.Id
|
var existingLocation = lootLocationTemplates.Any(spawnPoint =>
|
||||||
|
spawnPoint.Id == locationTemplateToAdd.Id
|
||||||
);
|
);
|
||||||
if (!existingLocation)
|
if (!existingLocation)
|
||||||
{
|
{
|
||||||
@@ -934,13 +1067,19 @@ public class LocationLootGenerator(
|
|||||||
/// <param name="items"> Location loot Template </param>
|
/// <param name="items"> Location loot Template </param>
|
||||||
/// <param name="staticAmmoDist"> Ammo distributions </param>
|
/// <param name="staticAmmoDist"> Ammo distributions </param>
|
||||||
/// <returns> ContainerItem object </returns>
|
/// <returns> ContainerItem object </returns>
|
||||||
protected ContainerItem CreateDynamicLootItem(string? chosenComposedKey, List<Item> items, Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist)
|
protected ContainerItem CreateDynamicLootItem(
|
||||||
|
string? chosenComposedKey,
|
||||||
|
List<Item> items,
|
||||||
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var chosenItem = items.FirstOrDefault(item => item.Id == chosenComposedKey);
|
var chosenItem = items.FirstOrDefault(item => item.Id == chosenComposedKey);
|
||||||
var chosenTpl = chosenItem?.Template;
|
var chosenTpl = chosenItem?.Template;
|
||||||
if (chosenTpl is null)
|
if (chosenTpl is null)
|
||||||
{
|
{
|
||||||
throw new Exception($"Item for tpl {chosenComposedKey} was not found in the spawn point");
|
throw new Exception(
|
||||||
|
$"Item for tpl {chosenComposedKey} was not found in the spawn point"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemTemplate = _itemHelper.GetItem(chosenTpl).Value;
|
var itemTemplate = _itemHelper.GetItem(chosenTpl).Value;
|
||||||
@@ -958,45 +1097,31 @@ public class LocationLootGenerator(
|
|||||||
var stackCount =
|
var stackCount =
|
||||||
itemTemplate.Properties.StackMaxSize == 1
|
itemTemplate.Properties.StackMaxSize == 1
|
||||||
? 1
|
? 1
|
||||||
: _randomUtil.GetInt(itemTemplate.Properties.StackMinRandom.Value, itemTemplate.Properties.StackMaxRandom.Value);
|
: _randomUtil.GetInt(
|
||||||
|
itemTemplate.Properties.StackMinRandom.Value,
|
||||||
|
itemTemplate.Properties.StackMaxRandom.Value
|
||||||
|
);
|
||||||
|
|
||||||
itemWithMods.Add(
|
itemWithMods.Add(
|
||||||
new Item
|
new Item
|
||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = chosenTpl,
|
Template = chosenTpl,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = stackCount },
|
||||||
{
|
|
||||||
StackObjectsCount = stackCount
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX))
|
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.AMMO_BOX))
|
||||||
{
|
{
|
||||||
// Fill with cartridges
|
// Fill with cartridges
|
||||||
List<Item> ammoBoxItem =
|
List<Item> ammoBoxItem = [new() { Id = _hashUtil.Generate(), Template = chosenTpl }];
|
||||||
[
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenTpl
|
|
||||||
}
|
|
||||||
];
|
|
||||||
_itemHelper.AddCartridgesToAmmoBox(ammoBoxItem, itemTemplate);
|
_itemHelper.AddCartridgesToAmmoBox(ammoBoxItem, itemTemplate);
|
||||||
itemWithMods.AddRange(ammoBoxItem);
|
itemWithMods.AddRange(ammoBoxItem);
|
||||||
}
|
}
|
||||||
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MAGAZINE))
|
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MAGAZINE))
|
||||||
{
|
{
|
||||||
// Create array with just magazine
|
// Create array with just magazine
|
||||||
List<Item> magazineItem =
|
List<Item> magazineItem = [new() { Id = _hashUtil.Generate(), Template = chosenTpl }];
|
||||||
[
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenTpl
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
if (_randomUtil.GetChance100(_locationConfig.StaticMagazineLootHasAmmoChancePercent))
|
if (_randomUtil.GetChance100(_locationConfig.StaticMagazineLootHasAmmoChancePercent))
|
||||||
// Add randomised amount of cartridges
|
// Add randomised amount of cartridges
|
||||||
@@ -1037,16 +1162,16 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
Items = itemWithMods,
|
Items = itemWithMods,
|
||||||
Width = size.Width,
|
Width = size.Width,
|
||||||
Height = size.Height
|
Height = size.Height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: rewrite, BIG yikes
|
// TODO: rewrite, BIG yikes
|
||||||
protected ContainerItem? CreateStaticLootItem(
|
protected ContainerItem? CreateStaticLootItem(
|
||||||
string chosenTpl,
|
string chosenTpl,
|
||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||||
string? parentId = null)
|
string? parentId = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var itemTemplate = _itemHelper.GetItem(chosenTpl).Value;
|
var itemTemplate = _itemHelper.GetItem(chosenTpl).Value;
|
||||||
if (itemTemplate.Properties is null)
|
if (itemTemplate.Properties is null)
|
||||||
@@ -1058,14 +1183,7 @@ public class LocationLootGenerator(
|
|||||||
|
|
||||||
var width = itemTemplate.Properties.Width;
|
var width = itemTemplate.Properties.Width;
|
||||||
var height = itemTemplate.Properties.Height;
|
var height = itemTemplate.Properties.Height;
|
||||||
List<Item> items =
|
List<Item> items = [new() { Id = _hashUtil.Generate(), Template = chosenTpl }];
|
||||||
[
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenTpl
|
|
||||||
}
|
|
||||||
];
|
|
||||||
var rootItem = items.FirstOrDefault();
|
var rootItem = items.FirstOrDefault();
|
||||||
|
|
||||||
// Use passed in parentId as override for new item
|
// Use passed in parentId as override for new item
|
||||||
@@ -1075,19 +1193,20 @@ public class LocationLootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MONEY) ||
|
_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.MONEY)
|
||||||
_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.AMMO)
|
|| _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 = itemTemplate.Properties.StackMaxSize == 1
|
var stackCount =
|
||||||
|
itemTemplate.Properties.StackMaxSize == 1
|
||||||
? 1
|
? 1
|
||||||
: _randomUtil.GetInt(itemTemplate.Properties.StackMinRandom.Value, itemTemplate.Properties.StackMaxRandom.Value);
|
: _randomUtil.GetInt(
|
||||||
|
itemTemplate.Properties.StackMinRandom.Value,
|
||||||
|
itemTemplate.Properties.StackMaxRandom.Value
|
||||||
|
);
|
||||||
|
|
||||||
rootItem.Upd = new Upd
|
rootItem.Upd = new Upd { StackObjectsCount = stackCount };
|
||||||
{
|
|
||||||
StackObjectsCount = stackCount
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// No spawn point, use default template
|
// No spawn point, use default template
|
||||||
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.WEAPON))
|
else if (_itemHelper.IsOfBaseclass(chosenTpl, BaseClasses.WEAPON))
|
||||||
@@ -1120,11 +1239,16 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
Items = items,
|
Items = items,
|
||||||
Width = width,
|
Width = width,
|
||||||
Height = height
|
Height = height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Item> GetArmorItems(string chosenTpl, Item? rootItem, List<Item> items, TemplateItem armorDbTemplate)
|
protected List<Item> GetArmorItems(
|
||||||
|
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)
|
||||||
@@ -1165,7 +1289,8 @@ public class LocationLootGenerator(
|
|||||||
string chosenTpl,
|
string chosenTpl,
|
||||||
Dictionary<string, List<StaticAmmoDetails>> cartridgePool,
|
Dictionary<string, List<StaticAmmoDetails>> cartridgePool,
|
||||||
string? parentId,
|
string? parentId,
|
||||||
ref List<Item> items)
|
ref List<Item> items
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<Item> children = [];
|
List<Item> children = [];
|
||||||
|
|
||||||
@@ -1175,7 +1300,10 @@ public class LocationLootGenerator(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
children = _itemHelper.ReparentItemAndChildren(defaultPreset.Items.FirstOrDefault(), defaultPreset.Items);
|
children = _itemHelper.ReparentItemAndChildren(
|
||||||
|
defaultPreset.Items.FirstOrDefault(),
|
||||||
|
defaultPreset.Items
|
||||||
|
);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -1190,7 +1318,7 @@ public class LocationLootGenerator(
|
|||||||
tpl = chosenTpl,
|
tpl = chosenTpl,
|
||||||
defaultId = defaultPreset.Id,
|
defaultId = defaultPreset.Id,
|
||||||
defaultName = defaultPreset.Name,
|
defaultName = defaultPreset.Name,
|
||||||
parentId
|
parentId,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -1214,11 +1342,7 @@ public class LocationLootGenerator(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"location-missing_root_item",
|
"location-missing_root_item",
|
||||||
new
|
new { tpl = chosenTpl, parentId }
|
||||||
{
|
|
||||||
tpl = chosenTpl,
|
|
||||||
parentId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1237,11 +1361,7 @@ public class LocationLootGenerator(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"location-unable_to_reparent_item",
|
"location-unable_to_reparent_item",
|
||||||
new
|
new { tpl = chosenTpl, parentId }
|
||||||
{
|
|
||||||
tpl = chosenTpl,
|
|
||||||
parentId
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
_logger.Error(e.StackTrace);
|
_logger.Error(e.StackTrace);
|
||||||
@@ -1285,7 +1405,8 @@ public class LocationLootGenerator(
|
|||||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||||
Item? rootItem,
|
Item? rootItem,
|
||||||
TemplateItem itemTemplate,
|
TemplateItem itemTemplate,
|
||||||
List<Item> items)
|
List<Item> items
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<Item> magazineWithCartridges = [rootItem];
|
List<Item> magazineWithCartridges = [rootItem];
|
||||||
_itemHelper.FillMagazineWithRandomCartridge(
|
_itemHelper.FillMagazineWithRandomCartridge(
|
||||||
@@ -1305,40 +1426,20 @@ public class LocationLootGenerator(
|
|||||||
public record ContainerGroupCount
|
public record ContainerGroupCount
|
||||||
{
|
{
|
||||||
[JsonPropertyName("containerIdsWithProbability")]
|
[JsonPropertyName("containerIdsWithProbability")]
|
||||||
public Dictionary<string, double>? ContainerIdsWithProbability
|
public Dictionary<string, double>? ContainerIdsWithProbability { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("chosenCount")]
|
[JsonPropertyName("chosenCount")]
|
||||||
public double? ChosenCount
|
public double? ChosenCount { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ContainerItem
|
public class ContainerItem
|
||||||
{
|
{
|
||||||
[JsonPropertyName("items")]
|
[JsonPropertyName("items")]
|
||||||
public List<Item>? Items
|
public List<Item>? Items { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("width")]
|
[JsonPropertyName("width")]
|
||||||
public int? Width
|
public int? Width { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("height")]
|
[JsonPropertyName("height")]
|
||||||
public int? Height
|
public int? Height { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,18 +58,16 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
// Choose one at random + add to results array
|
// Choose one at random + add to results array
|
||||||
var chosenSealedContainer = _randomUtil.GetArrayValue(sealedWeaponContainerPool);
|
var chosenSealedContainer = _randomUtil.GetArrayValue(sealedWeaponContainerPool);
|
||||||
result.Add([
|
result.Add(
|
||||||
|
[
|
||||||
new Item
|
new Item
|
||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = chosenSealedContainer.Id,
|
Template = chosenSealedContainer.Id,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 1, SpawnedInSession = true },
|
||||||
{
|
},
|
||||||
StackObjectsCount = 1,
|
]
|
||||||
SpawnedInSession = true
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,10 +83,20 @@ public class LootGenerator(
|
|||||||
// Pool has items we could add as loot, proceed
|
// Pool has items we could add as loot, proceed
|
||||||
if (rewardPoolResults.ItemPool.Count > 0)
|
if (rewardPoolResults.ItemPool.Count > 0)
|
||||||
{
|
{
|
||||||
var randomisedItemCount = _randomUtil.GetInt(options.ItemCount.Min, options.ItemCount.Max);
|
var randomisedItemCount = _randomUtil.GetInt(
|
||||||
|
options.ItemCount.Min,
|
||||||
|
options.ItemCount.Max
|
||||||
|
);
|
||||||
for (var index = 0; index < randomisedItemCount; index++)
|
for (var index = 0; index < randomisedItemCount; index++)
|
||||||
{
|
{
|
||||||
if (!FindAndAddRandomItemToLoot(rewardPoolResults.ItemPool, itemTypeCounts, options, result))
|
if (
|
||||||
|
!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--;
|
||||||
@@ -105,9 +113,8 @@ public class LootGenerator(
|
|||||||
);
|
);
|
||||||
if (randomisedWeaponPresetCount > 0)
|
if (randomisedWeaponPresetCount > 0)
|
||||||
{
|
{
|
||||||
var weaponDefaultPresets = globalDefaultPresets.Where(preset =>
|
var weaponDefaultPresets = globalDefaultPresets
|
||||||
_itemHelper.IsOfBaseclass(preset.Encyclopedia, BaseClasses.WEAPON)
|
.Where(preset => _itemHelper.IsOfBaseclass(preset.Encyclopedia, BaseClasses.WEAPON))
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (weaponDefaultPresets.Any())
|
if (weaponDefaultPresets.Any())
|
||||||
@@ -140,9 +147,8 @@ public class LootGenerator(
|
|||||||
var armorDefaultPresets = globalDefaultPresets.Where(preset =>
|
var armorDefaultPresets = globalDefaultPresets.Where(preset =>
|
||||||
_itemHelper.ArmorItemCanHoldMods(preset.Encyclopedia)
|
_itemHelper.ArmorItemCanHoldMods(preset.Encyclopedia)
|
||||||
);
|
);
|
||||||
var levelFilteredArmorPresets = armorDefaultPresets.Where(armor =>
|
var levelFilteredArmorPresets = armorDefaultPresets
|
||||||
IsArmorOfDesiredProtectionLevel(armor, options)
|
.Where(armor => IsArmorOfDesiredProtectionLevel(armor, options))
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Add some armors to rewards
|
// Add some armors to rewards
|
||||||
@@ -195,7 +201,9 @@ 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 presetWithUniqueIds = _itemHelper.ReplaceIDs(_cloner.Clone(preset.Items));
|
var presetWithUniqueIds = _itemHelper.ReplaceIDs(
|
||||||
|
_cloner.Clone(preset.Items)
|
||||||
|
);
|
||||||
|
|
||||||
// Add to results
|
// Add to results
|
||||||
result.Add(presetWithUniqueIds);
|
result.Add(presetWithUniqueIds);
|
||||||
@@ -203,7 +211,6 @@ public class LootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-preset item to be added
|
// Non-preset item to be added
|
||||||
@@ -211,11 +218,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = itemTpl,
|
Template = itemTpl,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = randomisedItemCount, SpawnedInSession = true },
|
||||||
{
|
|
||||||
StackObjectsCount = randomisedItemCount,
|
|
||||||
SpawnedInSession = true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
var splitResults = _itemHelper.SplitStack(newLootItem);
|
var splitResults = _itemHelper.SplitStack(newLootItem);
|
||||||
foreach (var splitItem in splitResults)
|
foreach (var splitItem in splitResults)
|
||||||
@@ -242,7 +245,8 @@ public class LootGenerator(
|
|||||||
List<string> itemTypeWhitelist,
|
List<string> itemTypeWhitelist,
|
||||||
bool useRewardItemBlacklist,
|
bool useRewardItemBlacklist,
|
||||||
bool allowBossItems,
|
bool allowBossItems,
|
||||||
bool blockSeasonalItemsOutOfSeason)
|
bool blockSeasonalItemsOutOfSeason
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var itemsDb = _databaseService.GetItems().Values;
|
var itemsDb = _databaseService.GetItems().Values;
|
||||||
var itemBlacklist = new HashSet<string>();
|
var itemBlacklist = new HashSet<string>();
|
||||||
@@ -256,7 +260,9 @@ 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 => _itemHelper.IsOfBaseclasses(templateItem.Parent, itemTypeBlacklist))
|
.Where(templateItem =>
|
||||||
|
_itemHelper.IsOfBaseclasses(templateItem.Parent, itemTypeBlacklist)
|
||||||
|
)
|
||||||
.Select(templateItem => templateItem.Id);
|
.Select(templateItem => templateItem.Id);
|
||||||
|
|
||||||
itemBlacklist.UnionWith([.. rewardItemBlacklist, .. itemsMatchingTypeBlacklist]);
|
itemBlacklist.UnionWith([.. rewardItemBlacklist, .. itemsMatchingTypeBlacklist]);
|
||||||
@@ -272,19 +278,16 @@ public class LootGenerator(
|
|||||||
itemBlacklist.UnionWith(_seasonalEventService.GetInactiveSeasonalEventItems());
|
itemBlacklist.UnionWith(_seasonalEventService.GetInactiveSeasonalEventItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = itemsDb.Where(item =>
|
var items = itemsDb
|
||||||
!itemBlacklist.Contains(item.Id) &&
|
.Where(item =>
|
||||||
string.Equals(item.Type, "item", StringComparison.OrdinalIgnoreCase) &&
|
!itemBlacklist.Contains(item.Id)
|
||||||
!item.Properties.QuestItem.GetValueOrDefault(false) &&
|
&& string.Equals(item.Type, "item", StringComparison.OrdinalIgnoreCase)
|
||||||
itemTypeWhitelist.Contains(item.Parent)
|
&& !item.Properties.QuestItem.GetValueOrDefault(false)
|
||||||
|
&& itemTypeWhitelist.Contains(item.Parent)
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return new ItemRewardPoolResults
|
return new ItemRewardPoolResults { ItemPool = items, Blacklist = itemBlacklist };
|
||||||
{
|
|
||||||
ItemPool = items,
|
|
||||||
Blacklist = itemBlacklist
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -326,7 +329,7 @@ public class LootGenerator(
|
|||||||
itemTypeCounts[itemTypeId.Key] = new ItemLimit
|
itemTypeCounts[itemTypeId.Key] = new ItemLimit
|
||||||
{
|
{
|
||||||
Current = 0,
|
Current = 0,
|
||||||
Max = limits[itemTypeId.Key]
|
Max = limits[itemTypeId.Key],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,13 +344,19 @@ public class LootGenerator(
|
|||||||
/// <param name="options">item filters</param>
|
/// <param name="options">item filters</param>
|
||||||
/// <param name="result">array to add found item to</param>
|
/// <param name="result">array to add found item to</param>
|
||||||
/// <returns>true if item was valid and added to pool</returns>
|
/// <returns>true if item was valid and added to pool</returns>
|
||||||
protected bool FindAndAddRandomItemToLoot(List<TemplateItem> items, Dictionary<string, ItemLimit> itemTypeCounts,
|
protected bool FindAndAddRandomItemToLoot(
|
||||||
|
List<TemplateItem> items,
|
||||||
|
Dictionary<string, ItemLimit> itemTypeCounts,
|
||||||
LootRequest options,
|
LootRequest options,
|
||||||
List<List<Item>> result)
|
List<List<Item>> result
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var randomItem = _randomUtil.GetArrayValue(items);
|
var randomItem = _randomUtil.GetArrayValue(items);
|
||||||
|
|
||||||
var itemLimitCount = itemTypeCounts.TryGetValue(randomItem.Parent, out var randomItemLimitCount);
|
var itemLimitCount = itemTypeCounts.TryGetValue(
|
||||||
|
randomItem.Parent,
|
||||||
|
out var randomItemLimitCount
|
||||||
|
);
|
||||||
if (!itemLimitCount && randomItemLimitCount?.Current > randomItemLimitCount?.Max)
|
if (!itemLimitCount && randomItemLimitCount?.Current > randomItemLimitCount?.Max)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -363,11 +372,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = randomItem.Id,
|
Template = randomItem.Id,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 1, SpawnedInSession = true },
|
||||||
{
|
|
||||||
StackObjectsCount = 1,
|
|
||||||
SpawnedInSession = true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special case - handle items that need a stackcount > 1
|
// Special case - handle items that need a stackcount > 1
|
||||||
@@ -417,10 +422,12 @@ public class LootGenerator(
|
|||||||
/// <param name="itemBlacklist">Items to skip</param>
|
/// <param name="itemBlacklist">Items to skip</param>
|
||||||
/// <param name="result">List to add chosen preset to</param>
|
/// <param name="result">List to add chosen preset to</param>
|
||||||
/// <returns>true if preset was valid and added to pool</returns>
|
/// <returns>true if preset was valid and added to pool</returns>
|
||||||
protected bool FindAndAddRandomPresetToLoot(List<Preset> presetPool,
|
protected bool FindAndAddRandomPresetToLoot(
|
||||||
|
List<Preset> presetPool,
|
||||||
Dictionary<string, ItemLimit> itemTypeCounts,
|
Dictionary<string, ItemLimit> itemTypeCounts,
|
||||||
HashSet<string> itemBlacklist,
|
HashSet<string> itemBlacklist,
|
||||||
List<List<Item>> result)
|
List<List<Item>> result
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (presetPool.Count == 0)
|
if (presetPool.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -437,7 +444,12 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("loot-chosen_preset_missing_encyclopedia_value", chosenPreset?.Id));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"loot-chosen_preset_missing_encyclopedia_value",
|
||||||
|
chosenPreset?.Id
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -449,7 +461,9 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"$Unable to find preset with tpl: {chosenPreset.Encyclopedia}, skipping");
|
_logger.Debug(
|
||||||
|
$"$Unable to find preset with tpl: {chosenPreset.Encyclopedia}, skipping"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -464,13 +478,21 @@ 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(_localisationService.GetText("loot-item_missing_parentid", itemDbDetails.Value?.Name));
|
_logger.Error(
|
||||||
|
_localisationService.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(itemDbDetails.Value.Parent, out var itemLimitCount);
|
var hasItemLimitCount = itemTypeCounts.TryGetValue(
|
||||||
|
itemDbDetails.Value.Parent,
|
||||||
|
out var itemLimitCount
|
||||||
|
);
|
||||||
if (!hasItemLimitCount && itemLimitCount?.Current > itemLimitCount?.Max)
|
if (!hasItemLimitCount && itemLimitCount?.Current > itemLimitCount?.Max)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -499,7 +521,9 @@ 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(SealedAirdropContainerSettings containerSettings)
|
public List<List<Item>> GetSealedWeaponCaseLoot(
|
||||||
|
SealedAirdropContainerSettings containerSettings
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<List<Item>> itemsToReturn = [];
|
List<List<Item>> itemsToReturn = [];
|
||||||
|
|
||||||
@@ -513,7 +537,10 @@ public class LootGenerator(
|
|||||||
if (!weaponDetailsDb.Key)
|
if (!weaponDetailsDb.Key)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("loot-non_item_picked_as_sealed_weapon_crate_reward", chosenWeaponTpl)
|
_localisationService.GetText(
|
||||||
|
"loot-non_item_picked_as_sealed_weapon_crate_reward",
|
||||||
|
chosenWeaponTpl
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return itemsToReturn;
|
return itemsToReturn;
|
||||||
@@ -528,9 +555,14 @@ public class LootGenerator(
|
|||||||
if (chosenWeaponPreset is null)
|
if (chosenWeaponPreset is null)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText("loot-default_preset_not_found_using_random", chosenWeaponTpl)
|
_localisationService.GetText(
|
||||||
|
"loot-default_preset_not_found_using_random",
|
||||||
|
chosenWeaponTpl
|
||||||
|
)
|
||||||
|
);
|
||||||
|
chosenWeaponPreset = _randomUtil.GetArrayValue(
|
||||||
|
_presetHelper.GetPresets(chosenWeaponTpl)
|
||||||
);
|
);
|
||||||
chosenWeaponPreset = _randomUtil.GetArrayValue(_presetHelper.GetPresets(chosenWeaponTpl));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up Ids to ensure they're all unique and prevent collisions
|
// Clean up Ids to ensure they're all unique and prevent collisions
|
||||||
@@ -543,11 +575,17 @@ public class LootGenerator(
|
|||||||
// Get a random collection of weapon mods related to chosen weawpon and add them to result array
|
// Get a random collection of weapon mods related to chosen weawpon 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(GetSealedContainerNonWeaponModRewards(containerSettings, weaponDetailsDb.Value));
|
itemsToReturn.AddRange(
|
||||||
|
GetSealedContainerNonWeaponModRewards(containerSettings, weaponDetailsDb.Value)
|
||||||
|
);
|
||||||
|
|
||||||
return itemsToReturn;
|
return itemsToReturn;
|
||||||
}
|
}
|
||||||
@@ -558,8 +596,10 @@ public class LootGenerator(
|
|||||||
/// <param name="containerSettings">Sealed weapon container settings</param>
|
/// <param name="containerSettings">Sealed weapon container settings</param>
|
||||||
/// <param name="weaponDetailsDb">Details for the weapon to reward player</param>
|
/// <param name="weaponDetailsDb">Details for the weapon to reward player</param>
|
||||||
/// <returns>List of item with children lists</returns>
|
/// <returns>List of item with children lists</returns>
|
||||||
protected List<List<Item>> GetSealedContainerNonWeaponModRewards(SealedAirdropContainerSettings containerSettings,
|
protected List<List<Item>> GetSealedContainerNonWeaponModRewards(
|
||||||
TemplateItem weaponDetailsDb)
|
SealedAirdropContainerSettings containerSettings,
|
||||||
|
TemplateItem weaponDetailsDb
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<List<Item>> rewards = [];
|
List<List<Item>> rewards = [];
|
||||||
|
|
||||||
@@ -579,8 +619,7 @@ public class LootGenerator(
|
|||||||
{
|
{
|
||||||
var itemDetails = _itemHelper.GetItem(tpl);
|
var itemDetails = _itemHelper.GetItem(tpl);
|
||||||
return itemDetails.Value;
|
return itemDetails.Value;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// 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;
|
||||||
@@ -602,11 +641,7 @@ public class LootGenerator(
|
|||||||
var chosenAmmoBox = _randomUtil.GetArrayValue(ammoBoxesMatchingCaliber);
|
var chosenAmmoBox = _randomUtil.GetArrayValue(ammoBoxesMatchingCaliber);
|
||||||
var ammoBoxReward = new List<Item>
|
var ammoBoxReward = new List<Item>
|
||||||
{
|
{
|
||||||
new()
|
new() { Id = _hashUtil.Generate(), Template = chosenAmmoBox.Id },
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenAmmoBox.Id
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
_itemHelper.AddCartridgesToAmmoBox(ammoBoxReward, chosenAmmoBox);
|
_itemHelper.AddCartridgesToAmmoBox(ammoBoxReward, chosenAmmoBox);
|
||||||
rewards.Add(ammoBoxReward);
|
rewards.Add(ammoBoxReward);
|
||||||
@@ -616,13 +651,14 @@ public class LootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get all items of the desired type + not quest items + not globally blacklisted
|
// Get all items of the desired type + not quest items + not globally blacklisted
|
||||||
var rewardItemPool = _databaseService.GetItems()
|
var rewardItemPool = _databaseService
|
||||||
|
.GetItems()
|
||||||
.Values.Where(item =>
|
.Values.Where(item =>
|
||||||
item.Parent == rewardKey &&
|
item.Parent == rewardKey
|
||||||
string.Equals(item.Type, "item", StringComparison.OrdinalIgnoreCase) &&
|
&& string.Equals(item.Type, "item", StringComparison.OrdinalIgnoreCase)
|
||||||
_itemFilterService.IsItemBlacklisted(item.Id) &&
|
&& _itemFilterService.IsItemBlacklisted(item.Id)
|
||||||
!(containerSettings.AllowBossItems || _itemFilterService.IsBossItem(item.Id)) &&
|
&& !(containerSettings.AllowBossItems || _itemFilterService.IsBossItem(item.Id))
|
||||||
item.Properties.QuestItem is null
|
&& item.Properties.QuestItem is null
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!rewardItemPool.Any())
|
if (!rewardItemPool.Any())
|
||||||
@@ -641,11 +677,7 @@ public class LootGenerator(
|
|||||||
var chosenRewardItem = _randomUtil.GetArrayValue(rewardItemPool);
|
var chosenRewardItem = _randomUtil.GetArrayValue(rewardItemPool);
|
||||||
var rewardItem = new List<Item>
|
var rewardItem = new List<Item>
|
||||||
{
|
{
|
||||||
new()
|
new() { Id = _hashUtil.Generate(), Template = chosenRewardItem.Id },
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenRewardItem.Id
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rewards.Add(rewardItem);
|
rewards.Add(rewardItem);
|
||||||
@@ -662,8 +694,11 @@ public class LootGenerator(
|
|||||||
/// <param name="linkedItemsToWeapon">All items that can be attached/inserted into weapon</param>
|
/// <param name="linkedItemsToWeapon">All items that can be attached/inserted into weapon</param>
|
||||||
/// <param name="chosenWeaponPreset">The weapon preset given to player as reward</param>
|
/// <param name="chosenWeaponPreset">The weapon preset given to player as reward</param>
|
||||||
/// <returns>List of item with children lists</returns>
|
/// <returns>List of item with children lists</returns>
|
||||||
protected List<List<Item>> GetSealedContainerWeaponModRewards(SealedAirdropContainerSettings containerSettings, List<TemplateItem> linkedItemsToWeapon,
|
protected List<List<Item>> GetSealedContainerWeaponModRewards(
|
||||||
Preset chosenWeaponPreset)
|
SealedAirdropContainerSettings containerSettings,
|
||||||
|
List<TemplateItem> linkedItemsToWeapon,
|
||||||
|
Preset chosenWeaponPreset
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<List<Item>> modRewards = [];
|
List<List<Item>> modRewards = [];
|
||||||
|
|
||||||
@@ -678,7 +713,8 @@ public class LootGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get items that fulfil reward type criteria from items that fit on gun
|
// Get items that fulfil reward type criteria from items that fit on gun
|
||||||
var relatedItems = linkedItemsToWeapon?.Where(item => item?.Parent == rewardKey && !_itemFilterService.IsItemBlacklisted(item.Id)
|
var relatedItems = linkedItemsToWeapon?.Where(item =>
|
||||||
|
item?.Parent == rewardKey && !_itemFilterService.IsItemBlacklisted(item.Id)
|
||||||
);
|
);
|
||||||
if (relatedItems is null || !relatedItems.Any())
|
if (relatedItems is null || !relatedItems.Any())
|
||||||
{
|
{
|
||||||
@@ -698,11 +734,7 @@ public class LootGenerator(
|
|||||||
var chosenItem = _randomUtil.DrawRandomFromList(relatedItems.ToList());
|
var chosenItem = _randomUtil.DrawRandomFromList(relatedItems.ToList());
|
||||||
var reward = new List<Item>
|
var reward = new List<Item>
|
||||||
{
|
{
|
||||||
new()
|
new() { Id = _hashUtil.Generate(), Template = chosenItem[0].Id },
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenItem[0].Id
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
modRewards.Add(reward);
|
modRewards.Add(reward);
|
||||||
@@ -742,11 +774,7 @@ public class LootGenerator(
|
|||||||
|
|
||||||
List<Item> rewardItem =
|
List<Item> rewardItem =
|
||||||
[
|
[
|
||||||
new()
|
new() { Id = _hashUtil.Generate(), Template = chosenRewardItemTpl },
|
||||||
{
|
|
||||||
Id = _hashUtil.Generate(),
|
|
||||||
Template = chosenRewardItemTpl
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
itemsToReturn.Add(rewardItem);
|
itemsToReturn.Add(rewardItem);
|
||||||
}
|
}
|
||||||
@@ -761,47 +789,33 @@ public class LootGenerator(
|
|||||||
/// <returns>Single tpl</returns>
|
/// <returns>Single tpl</returns>
|
||||||
protected string PickRewardItem(RewardDetails rewardContainerDetails)
|
protected string PickRewardItem(RewardDetails rewardContainerDetails)
|
||||||
{
|
{
|
||||||
if (rewardContainerDetails.RewardTplPool is not null && rewardContainerDetails.RewardTplPool.Count > 0)
|
if (
|
||||||
|
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)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record ItemRewardPoolResults
|
public record ItemRewardPoolResults
|
||||||
{
|
{
|
||||||
public List<TemplateItem> ItemPool
|
public List<TemplateItem> ItemPool { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HashSet<string> Blacklist
|
public HashSet<string> Blacklist { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ItemLimit
|
public class ItemLimit
|
||||||
{
|
{
|
||||||
[JsonPropertyName("current")]
|
[JsonPropertyName("current")]
|
||||||
public int Current
|
public int Current { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonPropertyName("max")]
|
[JsonPropertyName("max")]
|
||||||
public int Max
|
public int Max { get; set; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ public class PMCLootGenerator(
|
|||||||
RagfairPriceService ragfairPriceService,
|
RagfairPriceService ragfairPriceService,
|
||||||
SeasonalEventService seasonalEventService,
|
SeasonalEventService seasonalEventService,
|
||||||
WeightedRandomHelper weightedRandomHelper,
|
WeightedRandomHelper weightedRandomHelper,
|
||||||
ConfigServer configServer)
|
ConfigServer configServer
|
||||||
|
)
|
||||||
{
|
{
|
||||||
private readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
private readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
||||||
|
|
||||||
@@ -53,7 +54,12 @@ public class PMCLootGenerator(
|
|||||||
var blacklist = GetContainerLootBlacklist();
|
var blacklist = GetContainerLootBlacklist();
|
||||||
|
|
||||||
// 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(pmcRole, allowedItemTypeWhitelist, blacklist, ItemFitsInto1By2Slot);
|
var pool = GenerateLootPool(
|
||||||
|
pmcRole,
|
||||||
|
allowedItemTypeWhitelist,
|
||||||
|
blacklist,
|
||||||
|
ItemFitsInto1By2Slot
|
||||||
|
);
|
||||||
_pocketLootPool.TryAdd(pmcRole, pool);
|
_pocketLootPool.TryAdd(pmcRole, pool);
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
@@ -83,7 +89,12 @@ public class PMCLootGenerator(
|
|||||||
blacklist.UnionWith(_pmcConfig.VestLoot.Blacklist); // Include vest-specific blacklist
|
blacklist.UnionWith(_pmcConfig.VestLoot.Blacklist); // Include vest-specific blacklist
|
||||||
|
|
||||||
// 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(pmcRole, allowedItemTypeWhitelist, blacklist, ItemFitsInto2By2Slot);
|
var pool = GenerateLootPool(
|
||||||
|
pmcRole,
|
||||||
|
allowedItemTypeWhitelist,
|
||||||
|
blacklist,
|
||||||
|
ItemFitsInto2By2Slot
|
||||||
|
);
|
||||||
_vestLootPool.TryAdd(pmcRole, pool);
|
_vestLootPool.TryAdd(pmcRole, pool);
|
||||||
|
|
||||||
return pool;
|
return pool;
|
||||||
@@ -99,7 +110,6 @@ public class PMCLootGenerator(
|
|||||||
{
|
{
|
||||||
lock (BackpackLock)
|
lock (BackpackLock)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Already exists, return values
|
// Already exists, return values
|
||||||
if (_backpackLootPool.TryGetValue(pmcRole, out var existingLootPool))
|
if (_backpackLootPool.TryGetValue(pmcRole, out var existingLootPool))
|
||||||
{
|
{
|
||||||
@@ -126,7 +136,12 @@ public class PMCLootGenerator(
|
|||||||
/// <param name="itemTplAndParentBlacklist">Item and parent blacklist</param>
|
/// <param name="itemTplAndParentBlacklist">Item and parent blacklist</param>
|
||||||
/// <param name="genericItemCheck">An optional delegate to validate the TemplateItem object being processed</param>
|
/// <param name="genericItemCheck">An optional delegate to validate the TemplateItem object being processed</param>
|
||||||
/// <returns>Dictionary of items and weights inversely tied to the items price</returns>
|
/// <returns>Dictionary of items and weights inversely tied to the items price</returns>
|
||||||
protected Dictionary<string, double> GenerateLootPool(string pmcRole, HashSet<string> allowedItemTypeWhitelist, HashSet<string> itemTplAndParentBlacklist, Func<TemplateItem, bool>? genericItemCheck)
|
protected Dictionary<string, double> GenerateLootPool(
|
||||||
|
string pmcRole,
|
||||||
|
HashSet<string> allowedItemTypeWhitelist,
|
||||||
|
HashSet<string> itemTplAndParentBlacklist,
|
||||||
|
Func<TemplateItem, bool>? genericItemCheck
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var lootPool = new Dictionary<string, double>();
|
var lootPool = new Dictionary<string, double>();
|
||||||
var items = databaseService.GetItems();
|
var items = databaseService.GetItems();
|
||||||
@@ -136,13 +151,15 @@ public class PMCLootGenerator(
|
|||||||
|
|
||||||
// Filter all items in DB to ones we want with passed in whitelist + blacklist + generic 'IsValidItem' check
|
// Filter all items in DB to ones we want with passed in whitelist + blacklist + generic 'IsValidItem' check
|
||||||
// Also run Delegate if it's not null
|
// Also run Delegate if it's not null
|
||||||
var itemTplsToAdd = items.Where(item =>
|
var itemTplsToAdd = items
|
||||||
allowedItemTypeWhitelist.Contains(item.Value.Parent) &&
|
.Where(item =>
|
||||||
itemHelper.IsValidItem(item.Value.Id) &&
|
allowedItemTypeWhitelist.Contains(item.Value.Parent)
|
||||||
!itemTplAndParentBlacklist.Contains(item.Value.Id) &&
|
&& itemHelper.IsValidItem(item.Value.Id)
|
||||||
!itemTplAndParentBlacklist.Contains(item.Value.Parent) &&
|
&& !itemTplAndParentBlacklist.Contains(item.Value.Id)
|
||||||
(genericItemCheck?.Invoke(item.Value) ?? true) // if delegate is null, force check to be true
|
&& !itemTplAndParentBlacklist.Contains(item.Value.Parent)
|
||||||
).Select(x => x.Key);
|
&& (genericItemCheck?.Invoke(item.Value) ?? true) // if delegate is null, force check to be true
|
||||||
|
)
|
||||||
|
.Select(x => x.Key);
|
||||||
|
|
||||||
// Store all items + price in above lootPool dictionary
|
// Store all items + price in above lootPool dictionary
|
||||||
foreach (var tpl in itemTplsToAdd)
|
foreach (var tpl in itemTplsToAdd)
|
||||||
@@ -202,7 +219,6 @@ public class PMCLootGenerator(
|
|||||||
logger.Error($"Unable to find price overrides for PMC: {pmcRole}");
|
logger.Error($"Unable to find price overrides for PMC: {pmcRole}");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -213,7 +229,10 @@ public class PMCLootGenerator(
|
|||||||
/// <returns>Rouble price</returns>
|
/// <returns>Rouble price</returns>
|
||||||
protected double GetItemPrice(string tpl, Dictionary<string, double>? pmcPriceOverrides = null)
|
protected double GetItemPrice(string tpl, Dictionary<string, double>? pmcPriceOverrides = null)
|
||||||
{
|
{
|
||||||
if (pmcPriceOverrides is not null && pmcPriceOverrides.TryGetValue(tpl, out var overridePrice))
|
if (
|
||||||
|
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;
|
||||||
@@ -245,7 +264,7 @@ public class PMCLootGenerator(
|
|||||||
return $"{item.Properties.Width}x{item.Properties.Height}" switch
|
return $"{item.Properties.Width}x{item.Properties.Height}" switch
|
||||||
{
|
{
|
||||||
"1x1" or "1x2" or "2x1" => true,
|
"1x1" or "1x2" or "2x1" => true,
|
||||||
_ => false
|
_ => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ using SPTarkov.Server.Core.Utils.Cloners;
|
|||||||
using SPTarkov.Server.Core.Utils.Json;
|
using SPTarkov.Server.Core.Utils.Json;
|
||||||
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
||||||
|
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Generators;
|
namespace SPTarkov.Server.Core.Generators;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
@@ -54,9 +53,16 @@ public class PlayerScavGenerator(
|
|||||||
var scavKarmaLevel = GetScavKarmaLevel(pmcDataClone);
|
var scavKarmaLevel = GetScavKarmaLevel(pmcDataClone);
|
||||||
|
|
||||||
// use karma level to get correct karmaSettings
|
// use karma level to get correct karmaSettings
|
||||||
if (!_playerScavConfig.KarmaLevel.TryGetValue(scavKarmaLevel.ToString(), out var playerScavKarmaSettings))
|
if (
|
||||||
|
!_playerScavConfig.KarmaLevel.TryGetValue(
|
||||||
|
scavKarmaLevel.ToString(),
|
||||||
|
out var playerScavKarmaSettings
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_logger.Error(_localisationService.GetText("scav-missing_karma_settings", scavKarmaLevel));
|
_logger.Error(
|
||||||
|
_localisationService.GetText("scav-missing_karma_settings", scavKarmaLevel)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
@@ -101,24 +107,20 @@ 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 = existingScavDataClone.TaskConditionCounters ?? new Dictionary<string, TaskConditionCounter>();
|
scavData.TaskConditionCounters =
|
||||||
scavData.Notes = existingScavDataClone.Notes ??
|
existingScavDataClone.TaskConditionCounters
|
||||||
new Notes
|
?? new Dictionary<string, TaskConditionCounter>();
|
||||||
{
|
scavData.Notes = existingScavDataClone.Notes ?? new Notes { DataNotes = new List<Note>() };
|
||||||
DataNotes = new List<Note>()
|
scavData.WishList =
|
||||||
};
|
existingScavDataClone.WishList
|
||||||
scavData.WishList = existingScavDataClone.WishList ?? new DictionaryOrList<string, int>(new Dictionary<string, int>(), new List<int>());
|
?? new DictionaryOrList<string, int>(new Dictionary<string, int>(), new List<int>());
|
||||||
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new Dictionary<string, bool>();
|
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? new Dictionary<string, bool>();
|
||||||
|
|
||||||
// Add additional items to player scav as loot
|
// Add additional items to player scav as loot
|
||||||
AddAdditionalLootToPlayerScavContainers(
|
AddAdditionalLootToPlayerScavContainers(
|
||||||
playerScavKarmaSettings.LootItemsToAddChancePercent,
|
playerScavKarmaSettings.LootItemsToAddChancePercent,
|
||||||
scavData,
|
scavData,
|
||||||
[
|
[EquipmentSlots.TacticalVest, EquipmentSlots.Pockets, EquipmentSlots.Backpack]
|
||||||
EquipmentSlots.TacticalVest,
|
|
||||||
EquipmentSlots.Pockets,
|
|
||||||
EquipmentSlots.Backpack
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove secure container
|
// Remove secure container
|
||||||
@@ -139,8 +141,11 @@ public class PlayerScavGenerator(
|
|||||||
/// <param name="possibleItemsToAdd">dict of tpl + % chance to be added</param>
|
/// <param name="possibleItemsToAdd">dict of tpl + % chance to be added</param>
|
||||||
/// <param name="scavData"></param>
|
/// <param name="scavData"></param>
|
||||||
/// <param name="containersToAddTo">Possible slotIds to add loot to</param>
|
/// <param name="containersToAddTo">Possible slotIds to add loot to</param>
|
||||||
protected void AddAdditionalLootToPlayerScavContainers(Dictionary<string, double> possibleItemsToAdd, BotBase scavData,
|
protected void AddAdditionalLootToPlayerScavContainers(
|
||||||
HashSet<EquipmentSlots> containersToAddTo)
|
Dictionary<string, double> possibleItemsToAdd,
|
||||||
|
BotBase scavData,
|
||||||
|
HashSet<EquipmentSlots> containersToAddTo
|
||||||
|
)
|
||||||
{
|
{
|
||||||
foreach (var tpl in possibleItemsToAdd)
|
foreach (var tpl in possibleItemsToAdd)
|
||||||
{
|
{
|
||||||
@@ -153,7 +158,9 @@ public class PlayerScavGenerator(
|
|||||||
var itemResult = _itemHelper.GetItem(tpl.Key);
|
var itemResult = _itemHelper.GetItem(tpl.Key);
|
||||||
if (!itemResult.Key)
|
if (!itemResult.Key)
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("scav-unable_to_add_item_to_player_scav", tpl));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("scav-unable_to_add_item_to_player_scav", tpl)
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +171,8 @@ public class PlayerScavGenerator(
|
|||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = itemTemplate.Id,
|
Template = itemTemplate.Id,
|
||||||
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(itemTemplate)
|
Upd = _botGeneratorHelper.GenerateExtraPropertiesForItem(itemTemplate),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = _botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
|
var result = _botGeneratorHelper.AddItemWithChildrenToEquipmentSlot(
|
||||||
@@ -197,7 +204,9 @@ public class PlayerScavGenerator(
|
|||||||
// can be empty during profile creation
|
// can be empty during profile creation
|
||||||
if (!pmcData.TradersInfo.TryGetValue(Traders.FENCE, out var fenceInfo))
|
if (!pmcData.TradersInfo.TryGetValue(Traders.FENCE, out var fenceInfo))
|
||||||
{
|
{
|
||||||
_logger.Warning(_localisationService.GetText("scav-missing_karma_level_getting_default"));
|
_logger.Warning(
|
||||||
|
_localisationService.GetText("scav-missing_karma_level_getting_default")
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,7 +248,10 @@ 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 karama level settings</param>
|
/// <param name="baseBotNode">bot template to modify according to karama level settings</param>
|
||||||
protected void AdjustBotTemplateWithKarmaSpecificSettings(KarmaLevel karmaSettings, BotType baseBotNode)
|
protected void AdjustBotTemplateWithKarmaSpecificSettings(
|
||||||
|
KarmaLevel karmaSettings,
|
||||||
|
BotType baseBotNode
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Adjust equipment chance values
|
// Adjust equipment chance values
|
||||||
foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment)
|
foreach (var equipmentKvP in karmaSettings.Modifiers.Equipment)
|
||||||
@@ -251,7 +263,12 @@ public class PlayerScavGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try add new key with value
|
// Try add new key with value
|
||||||
if (!baseBotNode.BotChances.EquipmentChances.TryAdd(equipmentKvP.Key, equipmentKvP.Value))
|
if (
|
||||||
|
!baseBotNode.BotChances.EquipmentChances.TryAdd(
|
||||||
|
equipmentKvP.Key,
|
||||||
|
equipmentKvP.Value
|
||||||
|
)
|
||||||
|
)
|
||||||
// Unable to add new, update existing
|
// Unable to add new, update existing
|
||||||
{
|
{
|
||||||
baseBotNode.BotChances.EquipmentChances[equipmentKvP.Key] += equipmentKvP.Value;
|
baseBotNode.BotChances.EquipmentChances[equipmentKvP.Key] += equipmentKvP.Value;
|
||||||
@@ -272,7 +289,6 @@ public class PlayerScavGenerator(
|
|||||||
baseBotNode.BotChances.WeaponModsChances.TryAdd(modKvP.Key, 0);
|
baseBotNode.BotChances.WeaponModsChances.TryAdd(modKvP.Key, 0);
|
||||||
baseBotNode.BotChances.WeaponModsChances[modKvP.Key] += value;
|
baseBotNode.BotChances.WeaponModsChances[modKvP.Key] += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,14 +296,19 @@ public class PlayerScavGenerator(
|
|||||||
var props = baseBotNode.BotGeneration.Items.GetType().GetProperties();
|
var props = baseBotNode.BotGeneration.Items.GetType().GetProperties();
|
||||||
foreach (var itemLimitKvP in karmaSettings.ItemLimits)
|
foreach (var itemLimitKvP in karmaSettings.ItemLimits)
|
||||||
{
|
{
|
||||||
var prop = props.FirstOrDefault(x => string.Equals(x.Name, itemLimitKvP.Key, StringComparison.OrdinalIgnoreCase));
|
var prop = props.FirstOrDefault(x =>
|
||||||
|
string.Equals(x.Name, itemLimitKvP.Key, StringComparison.OrdinalIgnoreCase)
|
||||||
|
);
|
||||||
prop.SetValue(baseBotNode.BotGeneration.Items, itemLimitKvP.Value);
|
prop.SetValue(baseBotNode.BotGeneration.Items, itemLimitKvP.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blacklist equipment, keyed by equipment slot
|
// Blacklist equipment, keyed by equipment slot
|
||||||
foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist)
|
foreach (var equipmentBlacklistKvP in karmaSettings.EquipmentBlacklist)
|
||||||
{
|
{
|
||||||
baseBotNode.BotInventory.Equipment.TryGetValue(equipmentBlacklistKvP.Key, out var equipmentDict);
|
baseBotNode.BotInventory.Equipment.TryGetValue(
|
||||||
|
equipmentBlacklistKvP.Key,
|
||||||
|
out var equipmentDict
|
||||||
|
);
|
||||||
foreach (var itemToRemove in equipmentBlacklistKvP.Value)
|
foreach (var itemToRemove in equipmentBlacklistKvP.Value)
|
||||||
{
|
{
|
||||||
equipmentDict.Remove(itemToRemove);
|
equipmentDict.Remove(itemToRemove);
|
||||||
@@ -311,7 +332,7 @@ public class PlayerScavGenerator(
|
|||||||
{
|
{
|
||||||
Common = [],
|
Common = [],
|
||||||
Mastering = [],
|
Mastering = [],
|
||||||
Points = 0
|
Points = 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,18 +378,26 @@ 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 = 1d + pmcData.Bonuses
|
var modifier =
|
||||||
.Where(x => x.Type == BonusType.ScavCooldownTimer)
|
1d
|
||||||
|
+ pmcData
|
||||||
|
.Bonuses.Where(x => x.Type == BonusType.ScavCooldownTimer)
|
||||||
.Sum(bonus => (bonus?.Value ?? 1) / 100);
|
.Sum(bonus => (bonus?.Value ?? 1) / 100);
|
||||||
|
|
||||||
var fenceInfo = _fenceService.GetFenceInfo(pmcData);
|
var fenceInfo = _fenceService.GetFenceInfo(pmcData);
|
||||||
modifier *= fenceInfo.SavageCooldownModifier ?? 1d;
|
modifier *= fenceInfo.SavageCooldownModifier ?? 1d;
|
||||||
|
|
||||||
// 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 = _databaseService.GetGlobals().Configuration.SavagePlayCooldown * modifier;
|
var scavLockDuration =
|
||||||
|
_databaseService.GetGlobals().Configuration.SavagePlayCooldown * modifier;
|
||||||
|
|
||||||
var fullProfile = _profileHelper.GetFullProfile(pmcData?.SessionId);
|
var fullProfile = _profileHelper.GetFullProfile(pmcData?.SessionId);
|
||||||
if (fullProfile?.ProfileInfo?.Edition?.StartsWith(AccountTypes.SPT_DEVELOPER, StringComparison.OrdinalIgnoreCase) ?? false)
|
if (
|
||||||
|
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;
|
||||||
@@ -376,7 +405,9 @@ public class PlayerScavGenerator(
|
|||||||
|
|
||||||
if (scavData?.Info != null)
|
if (scavData?.Info != null)
|
||||||
{
|
{
|
||||||
scavData.Info.SavageLockTime = Math.Round(_timeUtil.GetTimeStamp() + (scavLockDuration ?? 0));
|
scavData.Info.SavageLockTime = Math.Round(
|
||||||
|
_timeUtil.GetTimeStamp() + (scavLockDuration ?? 0)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scavData;
|
return scavData;
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ namespace SPTarkov.Server.Core.Generators;
|
|||||||
public class PmcWaveGenerator(
|
public class PmcWaveGenerator(
|
||||||
ISptLogger<PmcWaveGenerator> logger,
|
ISptLogger<PmcWaveGenerator> logger,
|
||||||
DatabaseService databaseService,
|
DatabaseService databaseService,
|
||||||
ConfigServer configServer)
|
ConfigServer configServer
|
||||||
|
)
|
||||||
{
|
{
|
||||||
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
protected readonly PmcConfig _pmcConfig = configServer.GetConfig<PmcConfig>();
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class RagfairAssortGenerator(
|
|||||||
BaseClasses.INVENTORY,
|
BaseClasses.INVENTORY,
|
||||||
BaseClasses.STATIONARY_CONTAINER,
|
BaseClasses.STATIONARY_CONTAINER,
|
||||||
BaseClasses.POCKETS,
|
BaseClasses.POCKETS,
|
||||||
BaseClasses.BUILT_IN_INSERTS
|
BaseClasses.BUILT_IN_INSERTS,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,7 +53,9 @@ public class RagfairAssortGenerator(
|
|||||||
List<List<Item>> results = [];
|
List<List<Item>> results = [];
|
||||||
|
|
||||||
// Get cloned items from db
|
// Get cloned items from db
|
||||||
var dbItemsClone = itemHelper.GetItems().Where(item => !string.Equals(item.Type, "Node", StringComparison.OrdinalIgnoreCase));
|
var dbItemsClone = itemHelper
|
||||||
|
.GetItems()
|
||||||
|
.Where(item => !string.Equals(item.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<string> processedArmorItems = [];
|
HashSet<string> processedArmorItems = [];
|
||||||
@@ -76,7 +78,7 @@ public class RagfairAssortGenerator(
|
|||||||
{
|
{
|
||||||
StackObjectsCount = 99999999,
|
StackObjectsCount = 99999999,
|
||||||
UnlimitedCount = true,
|
UnlimitedCount = true,
|
||||||
SptPresetId = preset.Id
|
SptPresetId = preset.Id,
|
||||||
};
|
};
|
||||||
|
|
||||||
results.Add(presetAndMods);
|
results.Add(presetAndMods);
|
||||||
@@ -91,9 +93,9 @@ public class RagfairAssortGenerator(
|
|||||||
|
|
||||||
// Skip seasonal items when not in-season
|
// Skip seasonal items when not in-season
|
||||||
if (
|
if (
|
||||||
RagfairConfig.Dynamic.RemoveSeasonalItemsWhenNotInEvent &&
|
RagfairConfig.Dynamic.RemoveSeasonalItemsWhenNotInEvent
|
||||||
!seasonalEventActive &&
|
&& !seasonalEventActive
|
||||||
seasonalItemTplBlacklist.Contains(item.Id)
|
&& seasonalItemTplBlacklist.Contains(item.Id)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -105,10 +107,7 @@ public class RagfairAssortGenerator(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ragfairAssort = CreateRagfairAssortRootItem(
|
var ragfairAssort = CreateRagfairAssortRootItem(item.Id, item.Id); // tpl and id must be the same so hideout recipe rewards work
|
||||||
item.Id,
|
|
||||||
item.Id
|
|
||||||
); // tpl and id must be the same so hideout recipe rewards work
|
|
||||||
|
|
||||||
results.Add([ragfairAssort]);
|
results.Add([ragfairAssort]);
|
||||||
}
|
}
|
||||||
@@ -147,11 +146,7 @@ public class RagfairAssortGenerator(
|
|||||||
Template = tplId,
|
Template = tplId,
|
||||||
ParentId = "hideout",
|
ParentId = "hideout",
|
||||||
SlotId = "hideout",
|
SlotId = "hideout",
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = 99999999, UnlimitedCount = true },
|
||||||
{
|
|
||||||
StackObjectsCount = 99999999,
|
|
||||||
UnlimitedCount = true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,15 @@ public class RagfairOfferGenerator(
|
|||||||
bool sellInOnePiece = false
|
bool sellInOnePiece = false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var offer = CreateOffer(userId, time, items, barterScheme, loyalLevel, quantity, sellInOnePiece);
|
var offer = CreateOffer(
|
||||||
|
userId,
|
||||||
|
time,
|
||||||
|
items,
|
||||||
|
barterScheme,
|
||||||
|
loyalLevel,
|
||||||
|
quantity,
|
||||||
|
sellInOnePiece
|
||||||
|
);
|
||||||
ragfairOfferService.AddOffer(offer);
|
ragfairOfferService.AddOffer(offer);
|
||||||
|
|
||||||
return offer;
|
return offer;
|
||||||
@@ -95,13 +103,14 @@ public class RagfairOfferGenerator(
|
|||||||
bool isPackOffer = false
|
bool isPackOffer = false
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var offerRequirements = barterScheme.Select(barter =>
|
var offerRequirements = barterScheme
|
||||||
|
.Select(barter =>
|
||||||
{
|
{
|
||||||
var offerRequirement = new OfferRequirement
|
var offerRequirement = new OfferRequirement
|
||||||
{
|
{
|
||||||
Template = barter.Template,
|
Template = barter.Template,
|
||||||
Count = Math.Round(barter.Count.Value, 2),
|
Count = Math.Round(barter.Count.Value, 2),
|
||||||
OnlyFunctional = barter.OnlyFunctional ?? false
|
OnlyFunctional = barter.OnlyFunctional ?? false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dogtags define level and side
|
// Dogtags define level and side
|
||||||
@@ -112,8 +121,7 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return offerRequirement;
|
return offerRequirement;
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Clone to avoid modifying original array
|
// Clone to avoid modifying original array
|
||||||
@@ -122,13 +130,21 @@ 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 (itemHelper.IsOfBaseclass(itemsClone[0].Template, BaseClasses.AMMO_BOX) && itemsClone.Count == 1)
|
if (
|
||||||
|
itemHelper.IsOfBaseclass(itemsClone[0].Template, BaseClasses.AMMO_BOX)
|
||||||
|
&& itemsClone.Count == 1
|
||||||
|
)
|
||||||
{
|
{
|
||||||
itemHelper.AddCartridgesToAmmoBox(itemsClone, itemHelper.GetItem(rootItem.Template).Value);
|
itemHelper.AddCartridgesToAmmoBox(
|
||||||
|
itemsClone,
|
||||||
|
itemHelper.GetItem(rootItem.Template).Value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var roubleListingPrice = Math.Round(ConvertOfferRequirementsIntoRoubles(offerRequirements));
|
var roubleListingPrice = Math.Round(ConvertOfferRequirementsIntoRoubles(offerRequirements));
|
||||||
var singleItemListingPrice = isPackOffer ? roubleListingPrice / quantity : roubleListingPrice;
|
var singleItemListingPrice = isPackOffer
|
||||||
|
? roubleListingPrice / quantity
|
||||||
|
: roubleListingPrice;
|
||||||
|
|
||||||
var offer = new RagfairOffer
|
var offer = new RagfairOffer
|
||||||
{
|
{
|
||||||
@@ -146,7 +162,7 @@ public class RagfairOfferGenerator(
|
|||||||
LoyaltyLevel = loyalLevel,
|
LoyaltyLevel = loyalLevel,
|
||||||
SellInOnePiece = isPackOffer,
|
SellInOnePiece = isPackOffer,
|
||||||
Locked = false,
|
Locked = false,
|
||||||
Quantity = quantity
|
Quantity = quantity,
|
||||||
};
|
};
|
||||||
|
|
||||||
offerCounter++;
|
offerCounter++;
|
||||||
@@ -165,11 +181,7 @@ public class RagfairOfferGenerator(
|
|||||||
// Trader offer
|
// Trader offer
|
||||||
if (isTrader)
|
if (isTrader)
|
||||||
{
|
{
|
||||||
return new RagfairOfferUser
|
return new RagfairOfferUser { Id = userId, MemberType = MemberCategory.Trader };
|
||||||
{
|
|
||||||
Id = userId,
|
|
||||||
MemberType = MemberCategory.Trader
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var isPlayerOffer = profileHelper.IsPlayer(userId);
|
var isPlayerOffer = profileHelper.IsPlayer(userId);
|
||||||
@@ -185,7 +197,7 @@ public class RagfairOfferGenerator(
|
|||||||
Rating = playerProfile.RagfairInfo.Rating ?? 0,
|
Rating = playerProfile.RagfairInfo.Rating ?? 0,
|
||||||
IsRatingGrowing = playerProfile.RagfairInfo.IsRatingGrowing,
|
IsRatingGrowing = playerProfile.RagfairInfo.IsRatingGrowing,
|
||||||
Avatar = null,
|
Avatar = null,
|
||||||
Aid = playerProfile.Aid
|
Aid = playerProfile.Aid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +213,7 @@ public class RagfairOfferGenerator(
|
|||||||
),
|
),
|
||||||
IsRatingGrowing = randomUtil.GetBool(),
|
IsRatingGrowing = randomUtil.GetBool(),
|
||||||
Avatar = null,
|
Avatar = null,
|
||||||
Aid = hashUtil.GenerateAccountId()
|
Aid = hashUtil.GenerateAccountId(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,14 +222,17 @@ 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(IEnumerable<OfferRequirement> offerRequirements)
|
protected double ConvertOfferRequirementsIntoRoubles(
|
||||||
|
IEnumerable<OfferRequirement> offerRequirements
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var roublePrice = 0d;
|
var roublePrice = 0d;
|
||||||
foreach (var requirement in offerRequirements)
|
foreach (var requirement in offerRequirements)
|
||||||
{
|
{
|
||||||
roublePrice += paymentHelper.IsMoneyTpl(requirement.Template)
|
roublePrice += paymentHelper.IsMoneyTpl(requirement.Template)
|
||||||
? Math.Round(CalculateRoublePrice(requirement.Count.Value, requirement.Template))
|
? Math.Round(CalculateRoublePrice(requirement.Count.Value, requirement.Template))
|
||||||
: ragfairPriceService.GetFleaPriceForItem(requirement.Template) * requirement.Count.Value; // Get flea price for barter offer items
|
: ragfairPriceService.GetFleaPriceForItem(requirement.Template)
|
||||||
|
* requirement.Count.Value; // Get flea price for barter offer items
|
||||||
}
|
}
|
||||||
|
|
||||||
return roublePrice;
|
return roublePrice;
|
||||||
@@ -290,7 +305,10 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generated pmc offer
|
// Generated pmc offer
|
||||||
return randomUtil.GetDouble(ragfairConfig.Dynamic.Rating.Min, ragfairConfig.Dynamic.Rating.Max);
|
return randomUtil.GetDouble(
|
||||||
|
ragfairConfig.Dynamic.Rating.Min,
|
||||||
|
ragfairConfig.Dynamic.Rating.Max
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -303,7 +321,9 @@ public class RagfairOfferGenerator(
|
|||||||
if (profileHelper.IsPlayer(userID))
|
if (profileHelper.IsPlayer(userID))
|
||||||
// player offer
|
// player offer
|
||||||
{
|
{
|
||||||
return saveServer.GetProfile(userID).CharacterData?.PmcData?.RagfairInfo?.IsRatingGrowing ?? false;
|
return saveServer
|
||||||
|
.GetProfile(userID)
|
||||||
|
.CharacterData?.PmcData?.RagfairInfo?.IsRatingGrowing ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ragfairServerHelper.IsTrader(userID))
|
if (ragfairServerHelper.IsTrader(userID))
|
||||||
@@ -328,8 +348,13 @@ public class RagfairOfferGenerator(
|
|||||||
if (profileHelper.IsPlayer(userID))
|
if (profileHelper.IsPlayer(userID))
|
||||||
{
|
{
|
||||||
// Player offer = current time + offerDurationTimeInHour;
|
// Player offer = current time + offerDurationTimeInHour;
|
||||||
var offerDurationTimeHours = databaseService.GetGlobals().Configuration.RagFair.OfferDurationTimeInHour;
|
var offerDurationTimeHours = databaseService
|
||||||
return (long) (timeUtil.GetTimeStamp() + Math.Round((double) offerDurationTimeHours * TimeUtil.OneHourAsSeconds));
|
.GetGlobals()
|
||||||
|
.Configuration.RagFair.OfferDurationTimeInHour;
|
||||||
|
return (long)(
|
||||||
|
timeUtil.GetTimeStamp()
|
||||||
|
+ Math.Round((double)offerDurationTimeHours * TimeUtil.OneHourAsSeconds)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ragfairServerHelper.IsTrader(userID))
|
if (ragfairServerHelper.IsTrader(userID))
|
||||||
@@ -339,8 +364,13 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generated fake-player offer
|
// Generated fake-player offer
|
||||||
return (long) Math.Round(
|
return (long)
|
||||||
time + randomUtil.GetDouble(ragfairConfig.Dynamic.EndTimeSeconds.Min, ragfairConfig.Dynamic.EndTimeSeconds.Max)
|
Math.Round(
|
||||||
|
time
|
||||||
|
+ randomUtil.GetDouble(
|
||||||
|
ragfairConfig.Dynamic.EndTimeSeconds.Min,
|
||||||
|
ragfairConfig.Dynamic.EndTimeSeconds.Max
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,7 +390,9 @@ public class RagfairOfferGenerator(
|
|||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0)
|
if (logger.IsLogEnabled(LogLevel.Debug) && stopwatch.ElapsedMilliseconds > 0)
|
||||||
{
|
{
|
||||||
logger.Debug($"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count} items");
|
logger.Debug(
|
||||||
|
$"Took {stopwatch.ElapsedMilliseconds}ms to GetRagfairAssorts - {assortItemsToProcess.Count} items"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopwatch.Restart();
|
stopwatch.Restart();
|
||||||
@@ -370,9 +402,12 @@ public class RagfairOfferGenerator(
|
|||||||
tasks.Add(
|
tasks.Add(
|
||||||
Task.Factory.StartNew(() =>
|
Task.Factory.StartNew(() =>
|
||||||
{
|
{
|
||||||
CreateOffersFromAssort(assortItem, replacingExpiredOffers, ragfairConfig.Dynamic);
|
CreateOffersFromAssort(
|
||||||
}
|
assortItem,
|
||||||
)
|
replacingExpiredOffers,
|
||||||
|
ragfairConfig.Dynamic
|
||||||
|
);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +443,10 @@ 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
|
||||||
if (isPreset && ragfairConfig.Dynamic.Blacklist.EnableBsgList)
|
if (isPreset && ragfairConfig.Dynamic.Blacklist.EnableBsgList)
|
||||||
{
|
{
|
||||||
RemoveBannedPlatesFromPreset(assortItemWithChildren, ragfairConfig.Dynamic.Blacklist.ArmorPlate);
|
RemoveBannedPlatesFromPreset(
|
||||||
|
assortItemWithChildren,
|
||||||
|
ragfairConfig.Dynamic.Blacklist.ArmorPlate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get number of offers to create
|
// Get number of offers to create
|
||||||
@@ -427,7 +465,12 @@ public class RagfairOfferGenerator(
|
|||||||
clonedAssort[0].ParentId = null;
|
clonedAssort[0].ParentId = null;
|
||||||
clonedAssort[0].SlotId = null;
|
clonedAssort[0].SlotId = null;
|
||||||
|
|
||||||
CreateSingleOfferForItem(hashUtil.Generate(), clonedAssort, isPreset, itemToSellDetails.Value);
|
CreateSingleOfferForItem(
|
||||||
|
hashUtil.Generate(),
|
||||||
|
clonedAssort,
|
||||||
|
isPreset,
|
||||||
|
itemToSellDetails.Value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,7 +491,9 @@ public class RagfairOfferGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var plateSlots = presetWithChildren.Where(item => itemHelper.GetRemovablePlateSlotIds().Contains(item.SlotId?.ToLower())).ToList();
|
var plateSlots = presetWithChildren
|
||||||
|
.Where(item => itemHelper.GetRemovablePlateSlotIds().Contains(item.SlotId?.ToLower()))
|
||||||
|
.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
|
||||||
{
|
{
|
||||||
@@ -500,10 +545,10 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
var isBarterOffer = randomUtil.GetChance100(ragfairConfig.Dynamic.Barter.ChancePercent);
|
var isBarterOffer = randomUtil.GetChance100(ragfairConfig.Dynamic.Barter.ChancePercent);
|
||||||
var isPackOffer =
|
var isPackOffer =
|
||||||
randomUtil.GetChance100(ragfairConfig.Dynamic.Pack.ChancePercent) &&
|
randomUtil.GetChance100(ragfairConfig.Dynamic.Pack.ChancePercent)
|
||||||
!isBarterOffer &&
|
&& !isBarterOffer
|
||||||
itemWithChildren.Count == 1 &&
|
&& itemWithChildren.Count == 1
|
||||||
itemHelper.IsOfBaseclasses(
|
&& itemHelper.IsOfBaseclasses(
|
||||||
itemWithChildren[0].Template,
|
itemWithChildren[0].Template,
|
||||||
ragfairConfig.Dynamic.Pack.ItemTypeWhitelist
|
ragfairConfig.Dynamic.Pack.ItemTypeWhitelist
|
||||||
);
|
);
|
||||||
@@ -513,15 +558,21 @@ public class RagfairOfferGenerator(
|
|||||||
{
|
{
|
||||||
var armorConfig = ragfairConfig.Dynamic.Armor;
|
var armorConfig = ragfairConfig.Dynamic.Armor;
|
||||||
|
|
||||||
var shouldRemovePlates = randomUtil.GetChance100(armorConfig.RemoveRemovablePlateChance);
|
var shouldRemovePlates = randomUtil.GetChance100(
|
||||||
if (shouldRemovePlates && itemHelper.ArmorItemHasRemovablePlateSlots(itemWithChildren[0].Template))
|
armorConfig.RemoveRemovablePlateChance
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
shouldRemovePlates
|
||||||
|
&& itemHelper.ArmorItemHasRemovablePlateSlots(itemWithChildren[0].Template)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var offerItemPlatesToRemove = itemWithChildren.Where(item =>
|
var offerItemPlatesToRemove = itemWithChildren.Where(item =>
|
||||||
armorConfig.PlateSlotIdToRemovePool.Contains(item.SlotId?.ToLower())
|
armorConfig.PlateSlotIdToRemovePool.Contains(item.SlotId?.ToLower())
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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.Select(plateItem => itemWithChildren.IndexOf(plateItem))
|
var indexesToRemove = offerItemPlatesToRemove
|
||||||
|
.Select(plateItem => itemWithChildren.IndexOf(plateItem))
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
foreach (var index in indexesToRemove.OrderByDescending(x => x))
|
foreach (var index in indexesToRemove.OrderByDescending(x => x))
|
||||||
{
|
{
|
||||||
@@ -540,7 +591,11 @@ public class RagfairOfferGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Don't randomise pack items
|
// Don't randomise pack items
|
||||||
barterScheme = CreateCurrencyBarterScheme(itemWithChildren, isPackOffer, desiredStackSize);
|
barterScheme = CreateCurrencyBarterScheme(
|
||||||
|
itemWithChildren,
|
||||||
|
isPackOffer,
|
||||||
|
desiredStackSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else if (isBarterOffer)
|
else if (isBarterOffer)
|
||||||
{
|
{
|
||||||
@@ -600,8 +655,9 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var blacklist = ragfairConfig.Dynamic.Blacklist;
|
var blacklist = ragfairConfig.Dynamic.Blacklist;
|
||||||
var childAssortItems = assortsClone.Items
|
var childAssortItems = assortsClone
|
||||||
.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
|
||||||
@@ -617,12 +673,17 @@ public class RagfairOfferGenerator(
|
|||||||
var itemDetails = itemHelper.GetItem(item.Template);
|
var itemDetails = itemHelper.GetItem(item.Template);
|
||||||
if (!itemDetails.Key)
|
if (!itemDetails.Key)
|
||||||
{
|
{
|
||||||
logger.Warning(localisationService.GetText("ragfair-tpl_not_a_valid_item", item.Template));
|
logger.Warning(
|
||||||
|
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 (blacklist.EnableBsgList && !(itemDetails.Value?.Properties?.CanSellOnRagfair ?? false))
|
if (
|
||||||
|
blacklist.EnableBsgList
|
||||||
|
&& !(itemDetails.Value?.Properties?.CanSellOnRagfair ?? false)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -642,7 +703,7 @@ public class RagfairOfferGenerator(
|
|||||||
{
|
{
|
||||||
itemId = item.Id,
|
itemId = item.Id,
|
||||||
tpl = item.Template,
|
tpl = item.Template,
|
||||||
name = trader.Base.Nickname
|
name = trader.Base.Nickname,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -652,7 +713,14 @@ public class RagfairOfferGenerator(
|
|||||||
var barterSchemeItems = barterScheme[0];
|
var barterSchemeItems = barterScheme[0];
|
||||||
var loyalLevel = assortsClone.LoyalLevelItems[item.Id];
|
var loyalLevel = assortsClone.LoyalLevelItems[item.Id];
|
||||||
|
|
||||||
CreateAndAddFleaOffer(traderID, time, items, barterSchemeItems, loyalLevel, (int?) item.Upd.StackObjectsCount ?? 1);
|
CreateAndAddFleaOffer(
|
||||||
|
traderID,
|
||||||
|
time,
|
||||||
|
items,
|
||||||
|
barterSchemeItems,
|
||||||
|
loyalLevel,
|
||||||
|
(int?)item.Upd.StackObjectsCount ?? 1
|
||||||
|
);
|
||||||
|
|
||||||
// Refresh complete, reset flag to false
|
// Refresh complete, reset flag to false
|
||||||
trader.Base.RefreshTraderRagfairOffers = false;
|
trader.Base.RefreshTraderRagfairOffers = false;
|
||||||
@@ -666,7 +734,11 @@ public class RagfairOfferGenerator(
|
|||||||
/// <param name="userID"> ID of owner of item </param>
|
/// <param name="userID"> ID of owner of item </param>
|
||||||
/// <param name="itemWithMods"> Item and mods, get condition of first item (only first array item is modified) </param>
|
/// <param name="itemWithMods"> Item and mods, get condition of first item (only first array item is modified) </param>
|
||||||
/// <param name="itemDetails"> DB details of first item</param>
|
/// <param name="itemDetails"> DB details of first item</param>
|
||||||
protected void RandomiseOfferItemUpdProperties(string userID, List<Item> itemWithMods, TemplateItem itemDetails)
|
protected void RandomiseOfferItemUpdProperties(
|
||||||
|
string userID,
|
||||||
|
List<Item> itemWithMods,
|
||||||
|
TemplateItem itemDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Add any missing properties to first item in array
|
// Add any missing properties to first item in array
|
||||||
AddMissingConditions(itemWithMods[0]);
|
AddMissingConditions(itemWithMods[0]);
|
||||||
@@ -681,7 +753,11 @@ public class RagfairOfferGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Roll random chance to randomise item condition
|
// Roll random chance to randomise item condition
|
||||||
if (randomUtil.GetChance100(ragfairConfig.Dynamic.Condition[parentId].ConditionChance * 100))
|
if (
|
||||||
|
randomUtil.GetChance100(
|
||||||
|
ragfairConfig.Dynamic.Condition[parentId].ConditionChance * 100
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
RandomiseItemCondition(parentId, itemWithMods, itemDetails);
|
RandomiseItemCondition(parentId, itemWithMods, itemDetails);
|
||||||
}
|
}
|
||||||
@@ -723,29 +799,35 @@ public class RagfairOfferGenerator(
|
|||||||
var rootItem = itemWithMods[0];
|
var rootItem = itemWithMods[0];
|
||||||
|
|
||||||
var itemConditionValues = ragfairConfig.Dynamic.Condition[conditionSettingsId];
|
var itemConditionValues = ragfairConfig.Dynamic.Condition[conditionSettingsId];
|
||||||
var maxMultiplier = randomUtil.GetDouble(itemConditionValues.Max.Min, itemConditionValues.Max.Min);
|
var maxMultiplier = randomUtil.GetDouble(
|
||||||
|
itemConditionValues.Max.Min,
|
||||||
|
itemConditionValues.Max.Min
|
||||||
|
);
|
||||||
var currentMultiplier = randomUtil.GetDouble(
|
var currentMultiplier = randomUtil.GetDouble(
|
||||||
itemConditionValues.Current.Min,
|
itemConditionValues.Current.Min,
|
||||||
itemConditionValues.Current.Max
|
itemConditionValues.Current.Max
|
||||||
);
|
);
|
||||||
|
|
||||||
// Randomise armor + plates + armor related things
|
// Randomise armor + plates + armor related things
|
||||||
if (itemHelper.ArmorItemCanHoldMods(rootItem.Template) ||
|
if (
|
||||||
itemHelper.IsOfBaseclasses(rootItem.Template, [BaseClasses.ARMOR_PLATE, BaseClasses.ARMORED_EQUIPMENT])
|
itemHelper.ArmorItemCanHoldMods(rootItem.Template)
|
||||||
|
|| itemHelper.IsOfBaseclasses(
|
||||||
|
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 => item.ParentId == BaseClasses.ARMORED_EQUIPMENT && item.SlotId == "mod_equipment_000");
|
var visorMod = itemWithMods.FirstOrDefault(item =>
|
||||||
|
item.ParentId == BaseClasses.ARMORED_EQUIPMENT && item.SlotId == "mod_equipment_000"
|
||||||
|
);
|
||||||
if (randomUtil.GetChance100(25) && visorMod != null)
|
if (randomUtil.GetChance100(25) && visorMod != null)
|
||||||
{
|
{
|
||||||
itemHelper.AddUpdObjectToItem(visorMod);
|
itemHelper.AddUpdObjectToItem(visorMod);
|
||||||
|
|
||||||
visorMod.Upd.FaceShield = new UpdFaceShield
|
visorMod.Upd.FaceShield = new UpdFaceShield { Hits = randomUtil.GetInt(1, 3) };
|
||||||
{
|
|
||||||
Hits = randomUtil.GetInt(1, 3)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -754,7 +836,12 @@ public class RagfairOfferGenerator(
|
|||||||
// Randomise Weapons
|
// Randomise Weapons
|
||||||
if (itemHelper.IsOfBaseclass(itemDetails.Id, BaseClasses.WEAPON))
|
if (itemHelper.IsOfBaseclass(itemDetails.Id, BaseClasses.WEAPON))
|
||||||
{
|
{
|
||||||
RandomiseWeaponDurability(itemWithMods[0], itemDetails, maxMultiplier, currentMultiplier);
|
RandomiseWeaponDurability(
|
||||||
|
itemWithMods[0],
|
||||||
|
itemDetails,
|
||||||
|
maxMultiplier,
|
||||||
|
currentMultiplier
|
||||||
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -770,7 +857,8 @@ 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?) Math.Round(itemDetails.Properties.MaximumNumberOfUsage.Value * (1 - maxMultiplier));
|
rootItem.Upd.Key.NumberOfUsages = (int?)
|
||||||
|
Math.Round(itemDetails.Properties.MaximumNumberOfUsage.Value * (1 - maxMultiplier));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,7 +874,9 @@ 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((double) itemDetails.Properties.MaxRepairResource * maxMultiplier);
|
var resource = Math.Round(
|
||||||
|
(double)itemDetails.Properties.MaxRepairResource * maxMultiplier
|
||||||
|
);
|
||||||
rootItem.Upd.RepairKit.Resource = resource == 0D ? 1D : resource;
|
rootItem.Upd.RepairKit.Resource = resource == 0D ? 1D : resource;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -799,7 +889,7 @@ public class RagfairOfferGenerator(
|
|||||||
rootItem.Upd.Resource = new UpdResource
|
rootItem.Upd.Resource = new UpdResource
|
||||||
{
|
{
|
||||||
UnitsConsumed = totalCapacity - remainingFuel,
|
UnitsConsumed = totalCapacity - remainingFuel,
|
||||||
Value = remainingFuel
|
Value = remainingFuel,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -821,13 +911,19 @@ public class RagfairOfferGenerator(
|
|||||||
// 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(randomUtil.GetDouble((double) lowestMaxDurability, (double) baseMaxDurability));
|
var chosenMaxDurability = Math.Round(
|
||||||
|
randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability)
|
||||||
|
);
|
||||||
|
|
||||||
// Current
|
// Current
|
||||||
var lowestCurrentDurability = randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
var lowestCurrentDurability =
|
||||||
var chosenCurrentDurability = Math.Round(randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability));
|
randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
||||||
|
var chosenCurrentDurability = Math.Round(
|
||||||
|
randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability)
|
||||||
|
);
|
||||||
|
|
||||||
item.Upd.Repairable.Durability = chosenCurrentDurability == 0 ? 1D : chosenCurrentDurability; // Never var value become 0
|
item.Upd.Repairable.Durability =
|
||||||
|
chosenCurrentDurability == 0 ? 1D : chosenCurrentDurability; // Never var value become 0
|
||||||
item.Upd.Repairable.MaxDurability = chosenMaxDurability;
|
item.Upd.Repairable.MaxDurability = chosenMaxDurability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,16 +947,22 @@ public class RagfairOfferGenerator(
|
|||||||
itemHelper.AddUpdObjectToItem(armorItem);
|
itemHelper.AddUpdObjectToItem(armorItem);
|
||||||
|
|
||||||
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
var baseMaxDurability = itemDbDetails.Properties.MaxDurability;
|
||||||
var lowestMaxDurability = randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
var lowestMaxDurability =
|
||||||
var chosenMaxDurability = Math.Round(randomUtil.GetDouble((double) lowestMaxDurability, (double) baseMaxDurability));
|
randomUtil.GetDouble(maxMultiplier, 1) * baseMaxDurability;
|
||||||
|
var chosenMaxDurability = Math.Round(
|
||||||
|
randomUtil.GetDouble((double)lowestMaxDurability, (double)baseMaxDurability)
|
||||||
|
);
|
||||||
|
|
||||||
var lowestCurrentDurability = randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
var lowestCurrentDurability =
|
||||||
var chosenCurrentDurability = Math.Round(randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability));
|
randomUtil.GetDouble(currentMultiplier, 1) * chosenMaxDurability;
|
||||||
|
var chosenCurrentDurability = Math.Round(
|
||||||
|
randomUtil.GetDouble(lowestCurrentDurability, chosenMaxDurability)
|
||||||
|
);
|
||||||
|
|
||||||
armorItem.Upd.Repairable = new UpdRepairable
|
armorItem.Upd.Repairable = new UpdRepairable
|
||||||
{
|
{
|
||||||
Durability = chosenCurrentDurability == 0D ? 1D : chosenCurrentDurability, // Never var value become 0
|
Durability = chosenCurrentDurability == 0D ? 1D : chosenCurrentDurability, // Never var value become 0
|
||||||
MaxDurability = chosenMaxDurability
|
MaxDurability = chosenMaxDurability,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -886,7 +988,7 @@ public class RagfairOfferGenerator(
|
|||||||
item.Upd.Repairable = new UpdRepairable
|
item.Upd.Repairable = new UpdRepairable
|
||||||
{
|
{
|
||||||
Durability = props.Durability,
|
Durability = props.Durability,
|
||||||
MaxDurability = props.Durability
|
MaxDurability = props.Durability,
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -894,20 +996,14 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
if (isMedkit && props.MaxHpResource > 0)
|
if (isMedkit && props.MaxHpResource > 0)
|
||||||
{
|
{
|
||||||
item.Upd.MedKit = new UpdMedKit
|
item.Upd.MedKit = new UpdMedKit { HpResource = props.MaxHpResource };
|
||||||
{
|
|
||||||
HpResource = props.MaxHpResource
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isKey)
|
if (isKey)
|
||||||
{
|
{
|
||||||
item.Upd.Key = new UpdKey
|
item.Upd.Key = new UpdKey { NumberOfUsages = 0 };
|
||||||
{
|
|
||||||
NumberOfUsages = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -915,20 +1011,14 @@ public class RagfairOfferGenerator(
|
|||||||
// Food/drink
|
// Food/drink
|
||||||
if (isConsumable)
|
if (isConsumable)
|
||||||
{
|
{
|
||||||
item.Upd.FoodDrink = new UpdFoodDrink
|
item.Upd.FoodDrink = new UpdFoodDrink { HpPercent = props.MaxResource };
|
||||||
{
|
|
||||||
HpPercent = props.MaxResource
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRepairKit)
|
if (isRepairKit)
|
||||||
{
|
{
|
||||||
item.Upd.RepairKit = new UpdRepairKit
|
item.Upd.RepairKit = new UpdRepairKit { Resource = props.MaxRepairResource };
|
||||||
{
|
|
||||||
Resource = props.MaxRepairResource
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -938,7 +1028,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(List<Item> offerItems, BarterDetails barterConfig)
|
protected List<BarterScheme> CreateBarterBarterScheme(
|
||||||
|
List<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(
|
||||||
@@ -954,13 +1047,17 @@ 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(barterConfig.ItemCountMin, barterConfig.ItemCountMax);
|
var barterItemCount = randomUtil.GetInt(
|
||||||
|
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 = desiredItemCostRouble * barterConfig.PriceRangeVariancePercent / 100;
|
var offerCostVarianceRoubles =
|
||||||
|
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();
|
||||||
@@ -969,13 +1066,15 @@ public class RagfairOfferGenerator(
|
|||||||
var min = desiredItemCostRouble - offerCostVarianceRoubles;
|
var min = desiredItemCostRouble - offerCostVarianceRoubles;
|
||||||
var max = desiredItemCostRouble + offerCostVarianceRoubles;
|
var max = desiredItemCostRouble + offerCostVarianceRoubles;
|
||||||
var itemsInsidePriceBounds = itemFleaPrices.Where(itemAndPrice =>
|
var itemsInsidePriceBounds = itemFleaPrices.Where(itemAndPrice =>
|
||||||
itemAndPrice.Price >= min &&
|
itemAndPrice.Price >= min
|
||||||
itemAndPrice.Price <= max &&
|
&& itemAndPrice.Price <= max
|
||||||
!string.Equals(itemAndPrice.Tpl, offerItems[0].Template,
|
&& !string.Equals(
|
||||||
StringComparison.OrdinalIgnoreCase) // Don't allow the item being sold to be chosen
|
itemAndPrice.Tpl,
|
||||||
|
offerItems[0].Template,
|
||||||
|
StringComparison.OrdinalIgnoreCase
|
||||||
|
) // 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
|
||||||
if (!itemsInsidePriceBounds.Any())
|
if (!itemsInsidePriceBounds.Any())
|
||||||
{
|
{
|
||||||
@@ -985,14 +1084,7 @@ public class RagfairOfferGenerator(
|
|||||||
// Choose random item from price-filtered flea items
|
// Choose random item from price-filtered flea items
|
||||||
var randomItem = randomUtil.GetArrayValue(itemsInsidePriceBounds.ToList());
|
var randomItem = randomUtil.GetArrayValue(itemsInsidePriceBounds.ToList());
|
||||||
|
|
||||||
return
|
return [new BarterScheme { Count = barterItemCount, Template = randomItem.Tpl }];
|
||||||
[
|
|
||||||
new BarterScheme
|
|
||||||
{
|
|
||||||
Count = barterItemCount,
|
|
||||||
Template = randomItem.Tpl
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1008,16 +1100,13 @@ public class RagfairOfferGenerator(
|
|||||||
|
|
||||||
// Only get prices for items that also exist in items.json
|
// Only get prices for items that also exist in items.json
|
||||||
var filteredFleaItems = fleaPrices
|
var filteredFleaItems = fleaPrices
|
||||||
.Select(kvTpl => new TplWithFleaPrice
|
.Select(kvTpl => new TplWithFleaPrice { Tpl = kvTpl.Key, Price = kvTpl.Value })
|
||||||
{
|
|
||||||
Tpl = kvTpl.Key,
|
|
||||||
Price = kvTpl.Value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.Where(item => itemHelper.GetItem(item.Tpl).Key);
|
.Where(item => itemHelper.GetItem(item.Tpl).Key);
|
||||||
|
|
||||||
var itemTypeBlacklist = ragfairConfig.Dynamic.Barter.ItemTypeBlacklist;
|
var itemTypeBlacklist = ragfairConfig.Dynamic.Barter.ItemTypeBlacklist;
|
||||||
allowedFleaPriceItemsForBarter = filteredFleaItems.Where(item => !itemHelper.IsOfBaseclasses(item.Tpl, itemTypeBlacklist)).ToList();
|
allowedFleaPriceItemsForBarter = filteredFleaItems
|
||||||
|
.Where(item => !itemHelper.IsOfBaseclasses(item.Tpl, itemTypeBlacklist))
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return allowedFleaPriceItemsForBarter;
|
return allowedFleaPriceItemsForBarter;
|
||||||
@@ -1037,15 +1126,13 @@ public class RagfairOfferGenerator(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
var currency = ragfairServerHelper.GetDynamicOfferCurrency();
|
var currency = ragfairServerHelper.GetDynamicOfferCurrency();
|
||||||
var price = ragfairPriceService.GetDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer) * multiplier;
|
var price =
|
||||||
|
ragfairPriceService.GetDynamicOfferPriceForOffer(
|
||||||
|
offerWithChildren,
|
||||||
|
currency,
|
||||||
|
isPackOffer
|
||||||
|
) * multiplier;
|
||||||
|
|
||||||
return
|
return [new BarterScheme { Count = price, Template = currency }];
|
||||||
[
|
|
||||||
new BarterScheme
|
|
||||||
{
|
|
||||||
Count = price,
|
|
||||||
Template = currency
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,29 +37,10 @@ public class RepeatableQuestGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly Dictionary<string, List<string>> _bodyPartsToClient = new()
|
private static readonly Dictionary<string, List<string>> _bodyPartsToClient = new()
|
||||||
{
|
{
|
||||||
{
|
{ BodyParts.Arms, [BodyParts.LeftArm, BodyParts.RightArm] },
|
||||||
BodyParts.Arms, [
|
{ BodyParts.Legs, [BodyParts.LeftLeg, BodyParts.RightLeg] },
|
||||||
BodyParts.LeftArm,
|
{ BodyParts.Head, [BodyParts.Head] },
|
||||||
BodyParts.RightArm
|
{ BodyParts.Chest, [BodyParts.Chest, BodyParts.Stomach] },
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BodyParts.Legs, [
|
|
||||||
BodyParts.LeftLeg,
|
|
||||||
BodyParts.RightLeg
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BodyParts.Head, [
|
|
||||||
BodyParts.Head
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
BodyParts.Chest, [
|
|
||||||
BodyParts.Chest,
|
|
||||||
BodyParts.Stomach
|
|
||||||
]
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
protected int _maxRandomNumberAttempts = 6;
|
protected int _maxRandomNumberAttempts = 6;
|
||||||
@@ -88,8 +69,8 @@ public class RepeatableQuestGenerator(
|
|||||||
var questType = _randomUtil.DrawRandomFromList(questTypePool.Types).First();
|
var questType = _randomUtil.DrawRandomFromList(questTypePool.Types).First();
|
||||||
|
|
||||||
// Get traders from whitelist and filter by quest type availability
|
// Get traders from whitelist and filter by quest type availability
|
||||||
var traders = repeatableConfig.TraderWhitelist
|
var traders = repeatableConfig
|
||||||
.Where(x => x.QuestTypes.Contains(questType))
|
.TraderWhitelist.Where(x => x.QuestTypes.Contains(questType))
|
||||||
.Select(x => x.TraderId)
|
.Select(x => x.TraderId)
|
||||||
.ToList();
|
.ToList();
|
||||||
// filter out locked traders
|
// filter out locked traders
|
||||||
@@ -98,11 +79,34 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
return questType switch
|
return questType switch
|
||||||
{
|
{
|
||||||
"Elimination" => GenerateEliminationQuest(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
"Elimination" => GenerateEliminationQuest(
|
||||||
"Completion" => GenerateCompletionQuest(sessionId, pmcLevel, traderId, repeatableConfig),
|
sessionId,
|
||||||
"Exploration" => GenerateExplorationQuest(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
pmcLevel,
|
||||||
"Pickup" => GeneratePickupQuest(sessionId, pmcLevel, traderId, questTypePool, repeatableConfig),
|
traderId,
|
||||||
_ => null
|
questTypePool,
|
||||||
|
repeatableConfig
|
||||||
|
),
|
||||||
|
"Completion" => GenerateCompletionQuest(
|
||||||
|
sessionId,
|
||||||
|
pmcLevel,
|
||||||
|
traderId,
|
||||||
|
repeatableConfig
|
||||||
|
),
|
||||||
|
"Exploration" => GenerateExplorationQuest(
|
||||||
|
sessionId,
|
||||||
|
pmcLevel,
|
||||||
|
traderId,
|
||||||
|
questTypePool,
|
||||||
|
repeatableConfig
|
||||||
|
),
|
||||||
|
"Pickup" => GeneratePickupQuest(
|
||||||
|
sessionId,
|
||||||
|
pmcLevel,
|
||||||
|
traderId,
|
||||||
|
questTypePool,
|
||||||
|
repeatableConfig
|
||||||
|
),
|
||||||
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +132,31 @@ public class RepeatableQuestGenerator(
|
|||||||
{
|
{
|
||||||
var rand = new Random();
|
var rand = new Random();
|
||||||
|
|
||||||
var eliminationConfig = _repeatableQuestHelper.GetEliminationConfigByPmcLevel(pmcLevel, repeatableConfig);
|
var eliminationConfig = _repeatableQuestHelper.GetEliminationConfigByPmcLevel(
|
||||||
|
pmcLevel,
|
||||||
|
repeatableConfig
|
||||||
|
);
|
||||||
var locationsConfig = repeatableConfig.Locations;
|
var locationsConfig = repeatableConfig.Locations;
|
||||||
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(_mathUtil, _cloner, eliminationConfig.Targets);
|
var targetsConfig = new ProbabilityObjectArray<string, BossInfo>(
|
||||||
var bodyPartsConfig = new ProbabilityObjectArray<string, List<string>>(_mathUtil, _cloner, eliminationConfig.BodyParts);
|
_mathUtil,
|
||||||
var weaponCategoryRequirementConfig =
|
_cloner,
|
||||||
new ProbabilityObjectArray<string, List<string>>(_mathUtil, _cloner, eliminationConfig.WeaponCategoryRequirements);
|
eliminationConfig.Targets
|
||||||
var weaponRequirementConfig = new ProbabilityObjectArray<string, List<string>>(_mathUtil, _cloner, eliminationConfig.WeaponRequirements);
|
);
|
||||||
|
var bodyPartsConfig = new ProbabilityObjectArray<string, List<string>>(
|
||||||
|
_mathUtil,
|
||||||
|
_cloner,
|
||||||
|
eliminationConfig.BodyParts
|
||||||
|
);
|
||||||
|
var weaponCategoryRequirementConfig = new ProbabilityObjectArray<string, List<string>>(
|
||||||
|
_mathUtil,
|
||||||
|
_cloner,
|
||||||
|
eliminationConfig.WeaponCategoryRequirements
|
||||||
|
);
|
||||||
|
var weaponRequirementConfig = new ProbabilityObjectArray<string, List<string>>(
|
||||||
|
_mathUtil,
|
||||||
|
_cloner,
|
||||||
|
eliminationConfig.WeaponRequirements
|
||||||
|
);
|
||||||
|
|
||||||
// the difficulty of the quest varies in difficulty depending on the condition
|
// the difficulty of the quest varies in difficulty depending on the condition
|
||||||
// possible conditions are
|
// possible conditions are
|
||||||
@@ -157,8 +179,7 @@ public class RepeatableQuestGenerator(
|
|||||||
// times the number of kills we have to perform):
|
// times the number of kills we have to perform):
|
||||||
|
|
||||||
// The minimum difficulty is the difficulty for the most probable (= easiest target) with no additional conditions
|
// The minimum difficulty is the difficulty for the most probable (= easiest target) with no additional conditions
|
||||||
var minDifficulty =
|
var minDifficulty = 1 / targetsConfig.MaxProbability(); // min difficulty is the lowest amount of scavs without any constraints
|
||||||
1 / targetsConfig.MaxProbability(); // min difficulty is the lowest amount of scavs without any constraints
|
|
||||||
|
|
||||||
// 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 / targetsConfig.MinProbability();
|
var maxTargetDifficulty = 1 / targetsConfig.MinProbability();
|
||||||
@@ -172,7 +193,10 @@ public class RepeatableQuestGenerator(
|
|||||||
var targetPool = questTypePool.Pool.Elimination;
|
var targetPool = questTypePool.Pool.Elimination;
|
||||||
targetsConfig = targetsConfig.Filter(x => targetPool.Targets.ContainsKey(x.Key));
|
targetsConfig = targetsConfig.Filter(x => targetPool.Targets.ContainsKey(x.Key));
|
||||||
|
|
||||||
if (targetsConfig.Count == 0 || targetsConfig.All(x => x.Data.IsBoss.GetValueOrDefault(false)))
|
if (
|
||||||
|
targetsConfig.Count == 0
|
||||||
|
|| targetsConfig.All(x => x.Data.IsBoss.GetValueOrDefault(false))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// There are no more targets left for elimination; delete it as a possible quest type
|
// There are no more targets left for elimination; delete it as a possible quest type
|
||||||
// also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination
|
// also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination
|
||||||
@@ -190,8 +214,12 @@ public class RepeatableQuestGenerator(
|
|||||||
// we use any as location if "any" is in the pool, and we don't hit the specific location random
|
// we use any as location if "any" is in the pool, and we don't hit the specific location random
|
||||||
// we use any also if the random condition is not met in case only "any" was in the pool
|
// we use any also if the random condition is not met in case only "any" was in the pool
|
||||||
var locationKey = "any";
|
var locationKey = "any";
|
||||||
if (locations.Contains("any") &&
|
if (
|
||||||
(eliminationConfig.SpecificLocationProbability < rand.NextDouble() || locations.Count <= 1)
|
locations.Contains("any")
|
||||||
|
&& (
|
||||||
|
eliminationConfig.SpecificLocationProbability < rand.NextDouble()
|
||||||
|
|| locations.Count <= 1
|
||||||
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
locationKey = "any";
|
locationKey = "any";
|
||||||
@@ -207,17 +235,21 @@ public class RepeatableQuestGenerator(
|
|||||||
locationKey = _randomUtil.DrawRandomFromList(locations).FirstOrDefault();
|
locationKey = _randomUtil.DrawRandomFromList(locations).FirstOrDefault();
|
||||||
|
|
||||||
// Get a pool of locations the chosen bot type can be eliminated on
|
// Get a pool of locations the chosen bot type can be eliminated on
|
||||||
if (!targetPool.Targets.TryGetValue(
|
if (
|
||||||
|
!targetPool.Targets.TryGetValue(
|
||||||
botTypeToEliminate,
|
botTypeToEliminate,
|
||||||
out var possibleLocationPool
|
out var possibleLocationPool
|
||||||
))
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_logger.Warning($"Bot to kill: {botTypeToEliminate} not found in elimination dict");
|
_logger.Warning(
|
||||||
|
$"Bot to kill: {botTypeToEliminate} not found in elimination dict"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.Locations
|
possibleLocationPool.Locations = possibleLocationPool
|
||||||
.Where(location => location != locationKey)
|
.Locations.Where(location => location != locationKey)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// None left after filtering
|
// None left after filtering
|
||||||
@@ -231,7 +263,11 @@ public class RepeatableQuestGenerator(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Never should reach this if everything works out
|
// Never should reach this if everything works out
|
||||||
_logger.Error(_localisationService.GetText("quest-repeatable_elimination_generation_failed_please_report"));
|
_logger.Error(
|
||||||
|
_localisationService.GetText(
|
||||||
|
"quest-repeatable_elimination_generation_failed_please_report"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,49 +303,54 @@ public class RepeatableQuestGenerator(
|
|||||||
// Draw a distance condition
|
// Draw a distance condition
|
||||||
int? distance = null;
|
int? distance = null;
|
||||||
var distanceDifficulty = 0;
|
var distanceDifficulty = 0;
|
||||||
var isDistanceRequirementAllowed = !eliminationConfig.DistLocationBlacklist.Contains(locationKey);
|
var isDistanceRequirementAllowed = !eliminationConfig.DistLocationBlacklist.Contains(
|
||||||
|
locationKey
|
||||||
|
);
|
||||||
|
|
||||||
if (targetsConfig.Data(botTypeToEliminate).IsBoss.GetValueOrDefault(false))
|
if (targetsConfig.Data(botTypeToEliminate).IsBoss.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
// Get all boss spawn information
|
// Get all boss spawn information
|
||||||
var bossSpawns = _databaseService.GetLocations()
|
var bossSpawns = _databaseService
|
||||||
|
.GetLocations()
|
||||||
.GetDictionary()
|
.GetDictionary()
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value)
|
||||||
.Where(x => x.Base?.Id != null)
|
.Where(x => x.Base?.Id != null)
|
||||||
.Select(x => new
|
.Select(x => new { x.Base.Id, BossSpawn = x.Base.BossLocationSpawn });
|
||||||
{
|
|
||||||
x.Base.Id,
|
|
||||||
BossSpawn = x.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,
|
x.Id,
|
||||||
BossSpawn = x.BossSpawn
|
BossSpawn = x.BossSpawn.Where(e => e.BossName == botTypeToEliminate),
|
||||||
.Where(e => e.BossName == botTypeToEliminate)
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
.Where(x => x.BossSpawn.Count() > 0);
|
.Where(x => x.BossSpawn.Count() > 0);
|
||||||
// remove blacklisted locations
|
// remove blacklisted locations
|
||||||
var allowedSpawns = thisBossSpawns.Where(x => !eliminationConfig.DistLocationBlacklist.Contains(x.Id));
|
var allowedSpawns = thisBossSpawns.Where(x =>
|
||||||
|
!eliminationConfig.DistLocationBlacklist.Contains(x.Id)
|
||||||
|
);
|
||||||
// if the boss spawns on nom-blacklisted locations and the current location is allowed we can generate a distance kill requirement
|
// if the boss spawns on nom-blacklisted locations and the current location is allowed we can generate a distance kill requirement
|
||||||
isDistanceRequirementAllowed = isDistanceRequirementAllowed && allowedSpawns.Count() > 0;
|
isDistanceRequirementAllowed =
|
||||||
|
isDistanceRequirementAllowed && allowedSpawns.Count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eliminationConfig.DistanceProbability > rand.NextDouble() && isDistanceRequirementAllowed)
|
if (
|
||||||
|
eliminationConfig.DistanceProbability > rand.NextDouble()
|
||||||
|
&& isDistanceRequirementAllowed
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Random distance with lower values more likely; simple distribution for starters...
|
// Random distance with lower values more likely; simple distribution for starters...
|
||||||
distance = (int) Math.Floor(
|
distance = (int)
|
||||||
Math.Abs(rand.NextDouble() - rand.NextDouble()) *
|
Math.Floor(
|
||||||
(1 + eliminationConfig.MaxDistance - eliminationConfig.MinDistance) +
|
Math.Abs(rand.NextDouble() - rand.NextDouble())
|
||||||
eliminationConfig.MinDistance ??
|
* (1 + eliminationConfig.MaxDistance - eliminationConfig.MinDistance)
|
||||||
0
|
+ eliminationConfig.MinDistance
|
||||||
|
?? 0
|
||||||
);
|
);
|
||||||
|
|
||||||
distance = (int)Math.Ceiling((decimal)(distance / 5)) * 5;
|
distance = (int)Math.Ceiling((decimal)(distance / 5)) * 5;
|
||||||
distanceDifficulty = (int) (maxDistDifficulty * distance / eliminationConfig.MaxDistance);
|
distanceDifficulty = (int)(
|
||||||
|
maxDistDifficulty * distance / eliminationConfig.MaxDistance
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
string? allowedWeaponsCategory = null;
|
string? allowedWeaponsCategory = null;
|
||||||
@@ -321,18 +362,18 @@ public class RepeatableQuestGenerator(
|
|||||||
List<string> weaponTypeBlacklist = ["Shotgun", "Pistol"];
|
List<string> weaponTypeBlacklist = ["Shotgun", "Pistol"];
|
||||||
|
|
||||||
// Filter out close range weapons from long distance requirement
|
// Filter out close range weapons from long distance requirement
|
||||||
weaponCategoryRequirementConfig
|
weaponCategoryRequirementConfig.RemoveAll(category =>
|
||||||
.RemoveAll(category => weaponTypeBlacklist
|
weaponTypeBlacklist.Contains(category.Key)
|
||||||
.Contains(category.Key));
|
);
|
||||||
}
|
}
|
||||||
else if (distance < 20)
|
else if (distance < 20)
|
||||||
{
|
{
|
||||||
List<string> weaponTypeBlacklist = ["MarksmanRifle", "DMR"];
|
List<string> weaponTypeBlacklist = ["MarksmanRifle", "DMR"];
|
||||||
|
|
||||||
// Filter out far range weapons from close distance requirement
|
// Filter out far range weapons from close distance requirement
|
||||||
weaponCategoryRequirementConfig
|
weaponCategoryRequirementConfig.RemoveAll(category =>
|
||||||
.RemoveAll(category => weaponTypeBlacklist
|
weaponTypeBlacklist.Contains(category.Key)
|
||||||
.Contains(category.Key));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pick a weighted weapon category
|
// Pick a weighted weapon category
|
||||||
@@ -344,16 +385,25 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
// 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
|
||||||
string? allowedWeapon = null;
|
string? allowedWeapon = null;
|
||||||
if (allowedWeaponsCategory is not null && eliminationConfig.WeaponRequirementProbability > rand.NextDouble())
|
if (
|
||||||
|
allowedWeaponsCategory is not null
|
||||||
|
&& eliminationConfig.WeaponRequirementProbability > rand.NextDouble()
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var weaponRequirement = weaponRequirementConfig.Draw(1, false);
|
var weaponRequirement = weaponRequirementConfig.Draw(1, false);
|
||||||
var specificAllowedWeaponCategory = weaponRequirementConfig.Data(weaponRequirement[0]);
|
var specificAllowedWeaponCategory = weaponRequirementConfig.Data(weaponRequirement[0]);
|
||||||
var allowedWeapons = _itemHelper.GetItemTplsOfBaseType(specificAllowedWeaponCategory[0]);
|
var allowedWeapons = _itemHelper.GetItemTplsOfBaseType(
|
||||||
|
specificAllowedWeaponCategory[0]
|
||||||
|
);
|
||||||
allowedWeapon = _randomUtil.GetArrayValue(allowedWeapons);
|
allowedWeapon = _randomUtil.GetArrayValue(allowedWeapons);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw how many npm kills are required
|
// Draw how many npm kills are required
|
||||||
var desiredKillCount = GetEliminationKillCount(botTypeToEliminate, targetsConfig, eliminationConfig);
|
var desiredKillCount = GetEliminationKillCount(
|
||||||
|
botTypeToEliminate,
|
||||||
|
targetsConfig,
|
||||||
|
eliminationConfig
|
||||||
|
);
|
||||||
var killDifficulty = desiredKillCount;
|
var killDifficulty = desiredKillCount;
|
||||||
|
|
||||||
// not perfectly happy here; we give difficulty = 1 to the quest reward generation when we have the most difficult mission
|
// not perfectly happy here; we give difficulty = 1 to the quest reward generation when we have the most difficult mission
|
||||||
@@ -372,7 +422,12 @@ public class RepeatableQuestGenerator(
|
|||||||
// crazy maximum difficulty will lead to a higher difficulty reward gain factor than 1
|
// crazy maximum difficulty will lead to a higher difficulty reward gain factor than 1
|
||||||
var difficulty = _mathUtil.MapToRange(curDifficulty, minDifficulty, maxDifficulty, 0.5, 2);
|
var difficulty = _mathUtil.MapToRange(curDifficulty, minDifficulty, maxDifficulty, 0.5, 2);
|
||||||
|
|
||||||
var quest = GenerateRepeatableTemplate("Elimination", traderId, repeatableConfig.Side, sessionId);
|
var quest = GenerateRepeatableTemplate(
|
||||||
|
"Elimination",
|
||||||
|
traderId,
|
||||||
|
repeatableConfig.Side,
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
|
||||||
// ASSUMPTION: All fence quests are for scavs
|
// ASSUMPTION: All fence quests are for scavs
|
||||||
if (traderId == Traders.FENCE)
|
if (traderId == Traders.FENCE)
|
||||||
@@ -427,19 +482,29 @@ public class RepeatableQuestGenerator(
|
|||||||
protected int GetEliminationKillCount(
|
protected int GetEliminationKillCount(
|
||||||
string targetKey,
|
string targetKey,
|
||||||
ProbabilityObjectArray<string, BossInfo> targetsConfig,
|
ProbabilityObjectArray<string, BossInfo> targetsConfig,
|
||||||
EliminationConfig eliminationConfig)
|
EliminationConfig eliminationConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (targetsConfig.Data(targetKey).IsBoss.GetValueOrDefault(false))
|
if (targetsConfig.Data(targetKey).IsBoss.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
return _randomUtil.RandInt(eliminationConfig.MinBossKills.Value, eliminationConfig.MaxBossKills + 1);
|
return _randomUtil.RandInt(
|
||||||
|
eliminationConfig.MinBossKills.Value,
|
||||||
|
eliminationConfig.MaxBossKills + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetsConfig.Data(targetKey).IsPmc.GetValueOrDefault(false))
|
if (targetsConfig.Data(targetKey).IsPmc.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
return _randomUtil.RandInt(eliminationConfig.MinPmcKills.Value, eliminationConfig.MaxPmcKills + 1);
|
return _randomUtil.RandInt(
|
||||||
|
eliminationConfig.MinPmcKills.Value,
|
||||||
|
eliminationConfig.MaxPmcKills + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _randomUtil.RandInt(eliminationConfig.MinKills.Value, eliminationConfig.MaxKills + 1);
|
return _randomUtil.RandInt(
|
||||||
|
eliminationConfig.MinKills.Value,
|
||||||
|
eliminationConfig.MaxKills + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double DifficultyWeighing(
|
protected double DifficultyWeighing(
|
||||||
@@ -447,7 +512,8 @@ public class RepeatableQuestGenerator(
|
|||||||
double bodyPart,
|
double bodyPart,
|
||||||
int dist,
|
int dist,
|
||||||
int kill,
|
int kill,
|
||||||
int weaponRequirement)
|
int weaponRequirement
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
|
return Math.Sqrt(Math.Sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
|
||||||
}
|
}
|
||||||
@@ -466,7 +532,7 @@ public class RepeatableQuestGenerator(
|
|||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
DynamicLocale = true,
|
DynamicLocale = true,
|
||||||
Target = new ListOrT<string>(location, null),
|
Target = new ListOrT<string>(location, null),
|
||||||
ConditionType = "Location"
|
ConditionType = "Location",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,12 +561,8 @@ public class RepeatableQuestGenerator(
|
|||||||
Value = 1,
|
Value = 1,
|
||||||
ResetOnSessionEnd = false,
|
ResetOnSessionEnd = false,
|
||||||
EnemyHealthEffects = [],
|
EnemyHealthEffects = [],
|
||||||
Daytime = new DaytimeCounter
|
Daytime = new DaytimeCounter { From = 0, To = 0 },
|
||||||
{
|
ConditionType = "Kills",
|
||||||
From = 0,
|
|
||||||
To = 0
|
|
||||||
},
|
|
||||||
ConditionType = "Kills"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (target.StartsWith("boss"))
|
if (target.StartsWith("boss"))
|
||||||
@@ -521,7 +583,7 @@ public class RepeatableQuestGenerator(
|
|||||||
killConditionProps.Distance = new CounterConditionDistance
|
killConditionProps.Distance = new CounterConditionDistance
|
||||||
{
|
{
|
||||||
CompareMethod = ">=",
|
CompareMethod = ">=",
|
||||||
Value = distance.Value
|
Value = distance.Value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -567,10 +629,18 @@ public class RepeatableQuestGenerator(
|
|||||||
var levelsConfig = repeatableConfig.RewardScaling.Levels;
|
var levelsConfig = repeatableConfig.RewardScaling.Levels;
|
||||||
var roublesConfig = repeatableConfig.RewardScaling.Roubles;
|
var roublesConfig = repeatableConfig.RewardScaling.Roubles;
|
||||||
|
|
||||||
var quest = GenerateRepeatableTemplate("Completion", traderId, repeatableConfig.Side, sessionId);
|
var quest = GenerateRepeatableTemplate(
|
||||||
|
"Completion",
|
||||||
|
traderId,
|
||||||
|
repeatableConfig.Side,
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
|
||||||
// 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(completionConfig, repeatableConfig.RewardBlacklist);
|
var itemsToRetrievePool = GetItemsToRetrievePool(
|
||||||
|
completionConfig,
|
||||||
|
repeatableConfig.RewardBlacklist
|
||||||
|
);
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -578,28 +648,30 @@ public class RepeatableQuestGenerator(
|
|||||||
(double)(_mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) * multiplier)
|
(double)(_mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) * multiplier)
|
||||||
);
|
);
|
||||||
roublesBudget = Math.Max(roublesBudget, 5000d);
|
roublesBudget = Math.Max(roublesBudget, 5000d);
|
||||||
var itemSelection = itemsToRetrievePool.Where(itemTpl => _itemHelper.GetItemPrice(itemTpl) < roublesBudget
|
var itemSelection = itemsToRetrievePool
|
||||||
)
|
.Where(itemTpl => _itemHelper.GetItemPrice(itemTpl) < roublesBudget)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 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
|
||||||
// [{"minPlayerLevel": 1, "itemIds": ["id1",...]}, {"minPlayerLevel": 15, "itemIds": ["id3",...]}]
|
// [{"minPlayerLevel": 1, "itemIds": ["id1",...]}, {"minPlayerLevel": 15, "itemIds": ["id3",...]}]
|
||||||
if (repeatableConfig.QuestConfig.Completion.UseWhitelist.GetValueOrDefault(false))
|
if (repeatableConfig.QuestConfig.Completion.UseWhitelist.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
var itemWhitelist = _databaseService.GetTemplates().RepeatableQuests.Data.Completion.ItemsWhitelist;
|
var itemWhitelist = _databaseService
|
||||||
|
.GetTemplates()
|
||||||
|
.RepeatableQuests.Data.Completion.ItemsWhitelist;
|
||||||
|
|
||||||
// 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)
|
.Where(p => p.MinPlayerLevel <= pmcLevel)
|
||||||
.SelectMany(x => x.ItemIds)
|
.SelectMany(x => x.ItemIds)
|
||||||
.ToHashSet(); //.Aggregate((a, p) => a.Concat(p.ItemIds), []);
|
.ToHashSet(); //.Aggregate((a, p) => a.Concat(p.ItemIds), []);
|
||||||
itemSelection = itemSelection.Where(x =>
|
itemSelection = itemSelection
|
||||||
|
.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);
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
// check if items are missing
|
// check if items are missing
|
||||||
// var flatList = itemSelection.reduce((a, il) => a.concat(il[0]), []);
|
// var flatList = itemSelection.reduce((a, il) => a.concat(il[0]), []);
|
||||||
@@ -608,7 +680,9 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
if (repeatableConfig.QuestConfig.Completion.UseBlacklist.GetValueOrDefault(false))
|
if (repeatableConfig.QuestConfig.Completion.UseBlacklist.GetValueOrDefault(false))
|
||||||
{
|
{
|
||||||
var itemBlacklist = _databaseService.GetTemplates().RepeatableQuests.Data.Completion.ItemsBlacklist;
|
var itemBlacklist = _databaseService
|
||||||
|
.GetTemplates()
|
||||||
|
.RepeatableQuests.Data.Completion.ItemsBlacklist;
|
||||||
|
|
||||||
// Filter and concatenate the arrays according to current player level
|
// Filter and concatenate the arrays according to current player level
|
||||||
var itemIdsBlacklisted = itemBlacklist
|
var itemIdsBlacklisted = itemBlacklist
|
||||||
@@ -616,12 +690,12 @@ public class RepeatableQuestGenerator(
|
|||||||
.SelectMany(x => x.ItemIds)
|
.SelectMany(x => x.ItemIds)
|
||||||
.ToHashSet(); //.Aggregate(List<ItemsBlacklist> , (a, p) => a.Concat(p.ItemIds) );
|
.ToHashSet(); //.Aggregate(List<ItemsBlacklist> , (a, p) => a.Concat(p.ItemIds) );
|
||||||
|
|
||||||
itemSelection = itemSelection.Where(x =>
|
itemSelection = itemSelection
|
||||||
|
.Where(x =>
|
||||||
{
|
{
|
||||||
return itemIdsBlacklisted.All(v => !_itemHelper.IsOfBaseclass(x, v)) ||
|
return itemIdsBlacklisted.All(v => !_itemHelper.IsOfBaseclass(x, v))
|
||||||
!itemIdsBlacklisted.Contains(x);
|
|| !itemIdsBlacklisted.Contains(x);
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +712,10 @@ public class RepeatableQuestGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store the indexes of items we are asking player to supply
|
// Store the indexes of items we are asking player to supply
|
||||||
var distinctItemsToRetrieveCount = _randomUtil.GetInt(1, completionConfig.UniqueItemCount.Value);
|
var distinctItemsToRetrieveCount = _randomUtil.GetInt(
|
||||||
|
1,
|
||||||
|
completionConfig.UniqueItemCount.Value
|
||||||
|
);
|
||||||
var chosenRequirementItemsTpls = new List<string>();
|
var chosenRequirementItemsTpls = new List<string>();
|
||||||
var usedItemIndexes = new HashSet<int>();
|
var usedItemIndexes = new HashSet<int>();
|
||||||
for (var i = 0; i < distinctItemsToRetrieveCount; i++)
|
for (var i = 0; i < distinctItemsToRetrieveCount; i++)
|
||||||
@@ -664,11 +741,7 @@ public class RepeatableQuestGenerator(
|
|||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"repeatable-no_reward_item_found_in_price_range",
|
"repeatable-no_reward_item_found_in_price_range",
|
||||||
new
|
new { minPrice = 0, roublesBudget }
|
||||||
{
|
|
||||||
minPrice = 0,
|
|
||||||
roublesBudget
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -699,13 +772,20 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
// 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(GenerateCompletionAvailableForFinish(tplChosen, value, repeatableConfig.QuestConfig.Completion));
|
quest.Conditions.AvailableForFinish.Add(
|
||||||
|
GenerateCompletionAvailableForFinish(
|
||||||
|
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.Where(tpl => _itemHelper.GetItemPrice(tpl) < roublesBudget)
|
itemSelection = itemSelection
|
||||||
|
.Where(tpl => _itemHelper.GetItemPrice(tpl) < roublesBudget)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (!itemSelection.Any())
|
if (!itemSelection.Any())
|
||||||
{
|
{
|
||||||
@@ -737,14 +817,18 @@ public class RepeatableQuestGenerator(
|
|||||||
/// <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<string> GetItemsToRetrievePool(Completion completionConfig, HashSet<string> itemTplBlacklist)
|
protected HashSet<string> GetItemsToRetrievePool(
|
||||||
|
Completion completionConfig,
|
||||||
|
HashSet<string> 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();
|
||||||
|
|
||||||
// Check for specific base classes which don't make sense as reward item
|
// Check for specific base classes which don't make sense as reward item
|
||||||
// also check if the price is greater than 0; there are some items whose price can not be found
|
// also check if the price is greater than 0; there are some items whose price can not be found
|
||||||
return _databaseService.GetItems()
|
return _databaseService
|
||||||
|
.GetItems()
|
||||||
.Values.Where(itemTemplate =>
|
.Values.Where(itemTemplate =>
|
||||||
{
|
{
|
||||||
// Base "Item" item has no parent, ignore it
|
// Base "Item" item has no parent, ignore it
|
||||||
@@ -764,8 +848,8 @@ public class RepeatableQuestGenerator(
|
|||||||
itemTplBlacklist,
|
itemTplBlacklist,
|
||||||
completionConfig.RequiredItemTypeBlacklist
|
completionConfig.RequiredItemTypeBlacklist
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
).Select(item => item.Id)
|
.Select(item => item.Id)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,13 +863,23 @@ public class RepeatableQuestGenerator(
|
|||||||
/// <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 GenerateCompletionAvailableForFinish(string itemTpl,
|
protected QuestCondition GenerateCompletionAvailableForFinish(
|
||||||
|
string itemTpl,
|
||||||
double value,
|
double value,
|
||||||
Completion completionConfig)
|
Completion completionConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var onlyFoundInRaid = completionConfig.RequiredItemsAreFiR;
|
var onlyFoundInRaid = completionConfig.RequiredItemsAreFiR;
|
||||||
var minDurability = _itemHelper.IsOfBaseclasses(itemTpl, [BaseClasses.WEAPON, BaseClasses.ARMOR])
|
var minDurability = _itemHelper.IsOfBaseclasses(
|
||||||
? _randomUtil.GetArrayValue([completionConfig.RequiredItemMinDurabilityMinMax.Min, completionConfig.RequiredItemMinDurabilityMinMax.Max])
|
itemTpl,
|
||||||
|
[BaseClasses.WEAPON, BaseClasses.ARMOR]
|
||||||
|
)
|
||||||
|
? _randomUtil.GetArrayValue(
|
||||||
|
[
|
||||||
|
completionConfig.RequiredItemMinDurabilityMinMax.Min,
|
||||||
|
completionConfig.RequiredItemMinDurabilityMinMax.Max,
|
||||||
|
]
|
||||||
|
)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
// Dog tags MUST NOT be FiR for them to work
|
// Dog tags MUST NOT be FiR for them to work
|
||||||
@@ -809,7 +903,7 @@ public class RepeatableQuestGenerator(
|
|||||||
DogtagLevel = 0,
|
DogtagLevel = 0,
|
||||||
OnlyFoundInRaid = onlyFoundInRaid,
|
OnlyFoundInRaid = onlyFoundInRaid,
|
||||||
IsEncoded = false,
|
IsEncoded = false,
|
||||||
ConditionType = "HandoverItem"
|
ConditionType = "HandoverItem",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,11 +924,13 @@ public class RepeatableQuestGenerator(
|
|||||||
int pmcLevel,
|
int pmcLevel,
|
||||||
string traderId,
|
string traderId,
|
||||||
QuestTypePool questTypePool,
|
QuestTypePool questTypePool,
|
||||||
RepeatableQuestConfig repeatableConfig)
|
RepeatableQuestConfig repeatableConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var explorationConfig = repeatableConfig.QuestConfig.Exploration;
|
var explorationConfig = repeatableConfig.QuestConfig.Exploration;
|
||||||
var requiresSpecificExtract =
|
var requiresSpecificExtract =
|
||||||
_randomUtil.Random.Next() < repeatableConfig.QuestConfig.Exploration.SpecificExits.Probability;
|
_randomUtil.Random.Next()
|
||||||
|
< repeatableConfig.QuestConfig.Exploration.SpecificExits.Probability;
|
||||||
|
|
||||||
if (questTypePool.Pool.Exploration.Locations.Count == 0)
|
if (questTypePool.Pool.Exploration.Locations.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -845,7 +941,9 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
// If location drawn is factory, it's possible to either get factory4_day and factory4_night or only one
|
// If location drawn is factory, it's possible to either get factory4_day and factory4_night or only one
|
||||||
// of the both
|
// of the both
|
||||||
var locationKey = _randomUtil.DrawRandomFromDict(questTypePool.Pool.Exploration.Locations)[0];
|
var locationKey = _randomUtil.DrawRandomFromDict(questTypePool.Pool.Exploration.Locations)[
|
||||||
|
0
|
||||||
|
];
|
||||||
var locationTarget = questTypePool.Pool.Exploration.Locations[locationKey];
|
var locationTarget = questTypePool.Pool.Exploration.Locations[locationKey];
|
||||||
|
|
||||||
// Remove the location from the available pool
|
// Remove the location from the available pool
|
||||||
@@ -857,25 +955,34 @@ public class RepeatableQuestGenerator(
|
|||||||
: explorationConfig.MaximumExtracts + 1;
|
: explorationConfig.MaximumExtracts + 1;
|
||||||
var numExtracts = _randomUtil.RandInt(1, exitTimesMax);
|
var numExtracts = _randomUtil.RandInt(1, exitTimesMax);
|
||||||
|
|
||||||
var quest = GenerateRepeatableTemplate("Exploration", traderId, repeatableConfig.Side, sessionId);
|
var quest = GenerateRepeatableTemplate(
|
||||||
|
"Exploration",
|
||||||
|
traderId,
|
||||||
|
repeatableConfig.Side,
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
|
||||||
var exitStatusCondition = new QuestConditionCounterCondition
|
var exitStatusCondition = new QuestConditionCounterCondition
|
||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
DynamicLocale = true,
|
DynamicLocale = true,
|
||||||
Status = ["Survived"],
|
Status = ["Survived"],
|
||||||
ConditionType = "ExitStatus"
|
ConditionType = "ExitStatus",
|
||||||
};
|
};
|
||||||
var locationCondition = new QuestConditionCounterCondition
|
var locationCondition = new QuestConditionCounterCondition
|
||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
DynamicLocale = true,
|
DynamicLocale = true,
|
||||||
Target = new ListOrT<string>(locationTarget, null),
|
Target = new ListOrT<string>(locationTarget, null),
|
||||||
ConditionType = "Location"
|
ConditionType = "Location",
|
||||||
};
|
};
|
||||||
|
|
||||||
quest.Conditions.AvailableForFinish[0].Counter.Id = _hashUtil.Generate();
|
quest.Conditions.AvailableForFinish[0].Counter.Id = _hashUtil.Generate();
|
||||||
quest.Conditions.AvailableForFinish[0].Counter.Conditions = [exitStatusCondition, locationCondition];
|
quest.Conditions.AvailableForFinish[0].Counter.Conditions =
|
||||||
|
[
|
||||||
|
exitStatusCondition,
|
||||||
|
locationCondition,
|
||||||
|
];
|
||||||
quest.Conditions.AvailableForFinish[0].Value = numExtracts;
|
quest.Conditions.AvailableForFinish[0].Value = numExtracts;
|
||||||
quest.Conditions.AvailableForFinish[0].Id = _hashUtil.Generate();
|
quest.Conditions.AvailableForFinish[0].Id = _hashUtil.Generate();
|
||||||
quest.Location = GetQuestLocationByMapId(locationKey.ToString());
|
quest.Location = GetQuestLocationByMapId(locationKey.ToString());
|
||||||
@@ -889,9 +996,10 @@ public class RepeatableQuestGenerator(
|
|||||||
var exitPool = mapExits.Where(exit => exit.Chance > 0).ToList();
|
var exitPool = mapExits.Where(exit => exit.Chance > 0).ToList();
|
||||||
|
|
||||||
// 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
|
||||||
exit.PassageRequirement is not null ||
|
.Where(exit =>
|
||||||
repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains(
|
exit.PassageRequirement is not null
|
||||||
|
|| repeatableConfig.QuestConfig.Exploration.SpecificExits.PassageRequirementWhitelist.Contains(
|
||||||
"PassageRequirement"
|
"PassageRequirement"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -899,7 +1007,9 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
if (possibleExits.Count == 0)
|
if (possibleExits.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.Error($"Unable to choose specific exit on map: {locationKey}, Possible exit pool was empty");
|
_logger.Error(
|
||||||
|
$"Unable to choose specific exit on map: {locationKey}, Possible exit pool was empty"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -914,7 +1024,13 @@ public class RepeatableQuestGenerator(
|
|||||||
|
|
||||||
// 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(numExtracts, 1, explorationConfig.MaximumExtracts.Value, 0.2, 1);
|
var difficulty = _mathUtil.MapToRange(
|
||||||
|
numExtracts,
|
||||||
|
1,
|
||||||
|
explorationConfig.MaximumExtracts.Value,
|
||||||
|
0.2,
|
||||||
|
1
|
||||||
|
);
|
||||||
quest.Rewards = _repeatableQuestRewardGenerator.GenerateReward(
|
quest.Rewards = _repeatableQuestRewardGenerator.GenerateReward(
|
||||||
pmcLevel,
|
pmcLevel,
|
||||||
difficulty,
|
difficulty,
|
||||||
@@ -944,13 +1060,21 @@ public class RepeatableQuestGenerator(
|
|||||||
int pmcLevel,
|
int pmcLevel,
|
||||||
string traderId,
|
string traderId,
|
||||||
QuestTypePool questTypePool,
|
QuestTypePool questTypePool,
|
||||||
RepeatableQuestConfig repeatableConfig)
|
RepeatableQuestConfig repeatableConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var pickupConfig = repeatableConfig.QuestConfig.Pickup;
|
var pickupConfig = repeatableConfig.QuestConfig.Pickup;
|
||||||
|
|
||||||
var quest = GenerateRepeatableTemplate("Pickup", traderId, repeatableConfig.Side, sessionId);
|
var quest = GenerateRepeatableTemplate(
|
||||||
|
"Pickup",
|
||||||
|
traderId,
|
||||||
|
repeatableConfig.Side,
|
||||||
|
sessionId
|
||||||
|
);
|
||||||
|
|
||||||
var itemTypeToFetchWithCount = _randomUtil.GetArrayValue(pickupConfig.ItemTypeToFetchWithMaxCount);
|
var itemTypeToFetchWithCount = _randomUtil.GetArrayValue(
|
||||||
|
pickupConfig.ItemTypeToFetchWithMaxCount
|
||||||
|
);
|
||||||
var itemCountToFetch = _randomUtil.RandInt(
|
var itemCountToFetch = _randomUtil.RandInt(
|
||||||
itemTypeToFetchWithCount.MinimumPickupCount.Value,
|
itemTypeToFetchWithCount.MinimumPickupCount.Value,
|
||||||
itemTypeToFetchWithCount.MaximumPickupCount + 1
|
itemTypeToFetchWithCount.MaximumPickupCount + 1
|
||||||
@@ -959,18 +1083,25 @@ public class RepeatableQuestGenerator(
|
|||||||
// 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 => x.ConditionType == "FindItem");
|
var findCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x =>
|
||||||
|
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 => x.ConditionType == "CounterCreator"
|
var counterCreatorCondition = quest.Conditions.AvailableForFinish.FirstOrDefault(x =>
|
||||||
|
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 => x.ConditionType == "Equipment"
|
var equipmentCondition = counterCreatorCondition.Counter.Conditions.FirstOrDefault(x =>
|
||||||
|
x.ConditionType == "Equipment"
|
||||||
);
|
);
|
||||||
equipmentCondition.EquipmentInclusive = [[itemTypeToFetchWithCount.ItemType]];
|
equipmentCondition.EquipmentInclusive =
|
||||||
|
[
|
||||||
|
[itemTypeToFetchWithCount.ItemType],
|
||||||
|
];
|
||||||
|
|
||||||
// Add rewards
|
// Add rewards
|
||||||
quest.Rewards = _repeatableQuestRewardGenerator.GenerateReward(
|
quest.Rewards = _repeatableQuestRewardGenerator.GenerateReward(
|
||||||
@@ -1007,7 +1138,7 @@ public class RepeatableQuestGenerator(
|
|||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
DynamicLocale = true,
|
DynamicLocale = true,
|
||||||
ExitName = exit.Name,
|
ExitName = exit.Name,
|
||||||
ConditionType = "ExitName"
|
ConditionType = "ExitName",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,7 +1158,8 @@ public class RepeatableQuestGenerator(
|
|||||||
string type,
|
string type,
|
||||||
string traderId,
|
string traderId,
|
||||||
string side,
|
string side,
|
||||||
string sessionId)
|
string sessionId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
RepeatableQuest questData = null;
|
RepeatableQuest questData = null;
|
||||||
switch (type)
|
switch (type)
|
||||||
@@ -1082,35 +1214,35 @@ public class RepeatableQuestGenerator(
|
|||||||
// Force REF templates to use prapors ID - solves missing text issue
|
// Force REF templates to use prapors ID - solves missing text issue
|
||||||
var desiredTraderId = traderId == Traders.REF ? Traders.PRAPOR : traderId;
|
var desiredTraderId = traderId == Traders.REF ? Traders.PRAPOR : traderId;
|
||||||
|
|
||||||
questClone.Name = questClone.Name
|
questClone.Name = questClone
|
||||||
.Replace("{traderId}", traderId)
|
.Name.Replace("{traderId}", traderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.Note = questClone.Note
|
questClone.Note = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.Note.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.Description = questClone.Description
|
questClone.Description = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.Description.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.SuccessMessageText = questClone.SuccessMessageText
|
questClone.SuccessMessageText = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.SuccessMessageText.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.FailMessageText = questClone.FailMessageText
|
questClone.FailMessageText = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.FailMessageText.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.StartedMessageText = questClone.StartedMessageText
|
questClone.StartedMessageText = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.StartedMessageText.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.ChangeQuestMessageText = questClone.ChangeQuestMessageText
|
questClone.ChangeQuestMessageText = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.ChangeQuestMessageText.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.AcceptPlayerMessage = questClone.AcceptPlayerMessage
|
questClone.AcceptPlayerMessage = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.AcceptPlayerMessage.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.DeclinePlayerMessage = questClone.DeclinePlayerMessage
|
questClone.DeclinePlayerMessage = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.DeclinePlayerMessage.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
questClone.CompletePlayerMessage = questClone.CompletePlayerMessage
|
questClone.CompletePlayerMessage = questClone
|
||||||
.Replace("{traderId}", desiredTraderId)
|
.CompletePlayerMessage.Replace("{traderId}", desiredTraderId)
|
||||||
.Replace("{templateId}", questClone.TemplateId);
|
.Replace("{templateId}", questClone.TemplateId);
|
||||||
|
|
||||||
questClone.QuestStatus.Id = _hashUtil.Generate();
|
questClone.QuestStatus.Id = _hashUtil.Generate();
|
||||||
|
|||||||
@@ -64,10 +64,15 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
string traderId,
|
string traderId,
|
||||||
RepeatableQuestConfig repeatableConfig,
|
RepeatableQuestConfig repeatableConfig,
|
||||||
BaseQuestConfig eliminationConfig,
|
BaseQuestConfig eliminationConfig,
|
||||||
List<string>? rewardTplBlacklist = null)
|
List<string>? rewardTplBlacklist = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Get vars to configure rewards with
|
// Get vars to configure rewards with
|
||||||
var rewardParams = GetQuestRewardValues(repeatableConfig.RewardScaling, difficulty, pmcLevel);
|
var rewardParams = GetQuestRewardValues(
|
||||||
|
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;
|
||||||
@@ -77,7 +82,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
Started = [],
|
Started = [],
|
||||||
Success = [],
|
Success = [],
|
||||||
Fail = []
|
Fail = [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start reward index to keep track
|
// Start reward index to keep track
|
||||||
@@ -95,28 +100,40 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
AvailableInGameEditions = [],
|
AvailableInGameEditions = [],
|
||||||
Index = rewardIndex,
|
Index = rewardIndex,
|
||||||
Value = rewardParams.RewardXP,
|
Value = rewardParams.RewardXP,
|
||||||
Type = RewardType.Experience
|
Type = RewardType.Experience,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add money reward
|
// Add money reward
|
||||||
rewards.Success.Add(GetMoneyReward(traderId, rewardParams.RewardRoubles.Value, rewardIndex));
|
rewards.Success.Add(
|
||||||
|
GetMoneyReward(traderId, rewardParams.RewardRoubles.Value, rewardIndex)
|
||||||
|
);
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
|
|
||||||
// Add GP coin reward
|
// Add GP coin reward
|
||||||
rewards.Success.Add(GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount.Value, rewardIndex));
|
rewards.Success.Add(
|
||||||
|
GenerateItemReward(Money.GP, rewardParams.GpCoinRewardCount.Value, rewardIndex)
|
||||||
|
);
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
|
|
||||||
// Add preset weapon to reward if checks pass
|
// Add preset weapon to reward if checks pass
|
||||||
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(traderWhitelist => traderWhitelist.TraderId == traderId
|
var traderWhitelistDetails = repeatableConfig.TraderWhitelist.FirstOrDefault(
|
||||||
|
traderWhitelist => traderWhitelist.TraderId == traderId
|
||||||
);
|
);
|
||||||
if (traderWhitelistDetails?.RewardCanBeWeapon ??
|
if (
|
||||||
(false && _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0))
|
traderWhitelistDetails?.RewardCanBeWeapon
|
||||||
|
?? (
|
||||||
|
false
|
||||||
|
&& _randomUtil.GetChance100(traderWhitelistDetails.WeaponRewardChancePercent ?? 0)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var chosenWeapon = GetRandomWeaponPresetWithinBudget(itemRewardBudget.Value, rewardIndex);
|
var chosenWeapon = GetRandomWeaponPresetWithinBudget(
|
||||||
|
itemRewardBudget.Value,
|
||||||
|
rewardIndex
|
||||||
|
);
|
||||||
if (chosenWeapon is not null)
|
if (chosenWeapon is not null)
|
||||||
{
|
{
|
||||||
rewards.Success.Add(chosenWeapon.Value.Key);
|
rewards.Success.Add(chosenWeapon.Value.Key);
|
||||||
@@ -127,11 +144,16 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(repeatableConfig, itemRewardBudget, traderId);
|
var inBudgetRewardItemPool = ChooseRewardItemsWithinBudget(
|
||||||
|
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.Where(item => !rewardTplBlacklist.Contains(item.Id)
|
var filteredRewardItemPool = inBudgetRewardItemPool.Where(item =>
|
||||||
|
!rewardTplBlacklist.Contains(item.Id)
|
||||||
);
|
);
|
||||||
if (filteredRewardItemPool.Count() > 0)
|
if (filteredRewardItemPool.Count() > 0)
|
||||||
{
|
{
|
||||||
@@ -139,7 +161,6 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug(
|
_logger.Debug(
|
||||||
@@ -159,7 +180,9 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
// Add item rewards
|
// Add item rewards
|
||||||
foreach (var itemReward in itemsToReward)
|
foreach (var itemReward in itemsToReward)
|
||||||
{
|
{
|
||||||
rewards.Success.Add(GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex));
|
rewards.Success.Add(
|
||||||
|
GenerateItemReward(itemReward.Key.Id, itemReward.Value, rewardIndex)
|
||||||
|
);
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,14 +199,16 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
Target = traderId,
|
Target = traderId,
|
||||||
Value = rewardParams.RewardReputation,
|
Value = rewardParams.RewardReputation,
|
||||||
Type = RewardType.TraderStanding,
|
Type = RewardType.TraderStanding,
|
||||||
Index = rewardIndex
|
Index = rewardIndex,
|
||||||
};
|
};
|
||||||
rewards.Success.Add(reward);
|
rewards.Success.Add(reward);
|
||||||
rewardIndex++;
|
rewardIndex++;
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward");
|
_logger.Debug(
|
||||||
|
$"Adding: {rewardParams.RewardReputation} {traderId} trader reputation reward"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,20 +225,26 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
Target = targetSkill,
|
Target = targetSkill,
|
||||||
Value = rewardParams.SkillPointReward,
|
Value = rewardParams.SkillPointReward,
|
||||||
Type = RewardType.Skill,
|
Type = RewardType.Skill,
|
||||||
Index = rewardIndex
|
Index = rewardIndex,
|
||||||
};
|
};
|
||||||
rewards.Success.Add(reward);
|
rewards.Success.Add(reward);
|
||||||
|
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}");
|
_logger.Debug(
|
||||||
|
$"Adding {rewardParams.SkillPointReward} skill points to {targetSkill}"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rewards;
|
return rewards;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected QuestRewardValues GetQuestRewardValues(RewardScaling? rewardScaling, double? difficulty, int pmcLevel)
|
protected QuestRewardValues GetQuestRewardValues(
|
||||||
|
RewardScaling? rewardScaling,
|
||||||
|
double? difficulty,
|
||||||
|
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;
|
||||||
@@ -258,61 +289,102 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
gpCoinConfig,
|
gpCoinConfig,
|
||||||
rewardSpreadConfig
|
rewardSpreadConfig
|
||||||
),
|
),
|
||||||
RewardXP = GetRewardXp(effectiveDifficulty, pmcLevel, levelsConfig, xpConfig, rewardSpreadConfig)
|
RewardXP = GetRewardXp(
|
||||||
|
effectiveDifficulty,
|
||||||
|
pmcLevel,
|
||||||
|
levelsConfig,
|
||||||
|
xpConfig,
|
||||||
|
rewardSpreadConfig
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetRewardXp(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig,
|
protected double GetRewardXp(
|
||||||
List<double>? xpConfig, double? rewardSpreadConfig)
|
double? effectiveDifficulty,
|
||||||
|
int pmcLevel,
|
||||||
|
List<double>? levelsConfig,
|
||||||
|
List<double>? xpConfig,
|
||||||
|
double? rewardSpreadConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Math.Floor(
|
return Math.Floor(
|
||||||
effectiveDifficulty *
|
effectiveDifficulty
|
||||||
_mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig) *
|
* _mathUtil.Interp1(pmcLevel, levelsConfig, xpConfig)
|
||||||
_randomUtil.GetDouble((double) (1 - rewardSpreadConfig), (double) (1 + rewardSpreadConfig)) ??
|
* _randomUtil.GetDouble(
|
||||||
0
|
(double)(1 - rewardSpreadConfig),
|
||||||
|
(double)(1 + rewardSpreadConfig)
|
||||||
|
)
|
||||||
|
?? 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetGpCoinRewardCount(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig,
|
protected double GetGpCoinRewardCount(
|
||||||
|
double? effectiveDifficulty,
|
||||||
|
int pmcLevel,
|
||||||
|
List<double>? levelsConfig,
|
||||||
List<double>? gpCoinConfig,
|
List<double>? gpCoinConfig,
|
||||||
double? rewardSpreadConfig)
|
double? rewardSpreadConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Math.Ceiling(
|
return Math.Ceiling(
|
||||||
effectiveDifficulty *
|
effectiveDifficulty
|
||||||
_mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig) *
|
* _mathUtil.Interp1(pmcLevel, levelsConfig, gpCoinConfig)
|
||||||
_randomUtil.GetDouble((double) (1 - rewardSpreadConfig), (double) (1 + rewardSpreadConfig)) ??
|
* _randomUtil.GetDouble(
|
||||||
0
|
(double)(1 - rewardSpreadConfig),
|
||||||
|
(double)(1 + rewardSpreadConfig)
|
||||||
|
)
|
||||||
|
?? 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetRewardRep(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig,
|
protected double GetRewardRep(
|
||||||
|
double? effectiveDifficulty,
|
||||||
|
int pmcLevel,
|
||||||
|
List<double>? levelsConfig,
|
||||||
List<double>? reputationConfig,
|
List<double>? reputationConfig,
|
||||||
double? rewardSpreadConfig)
|
double? rewardSpreadConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Math.Round(
|
return Math.Round(
|
||||||
100 *
|
100
|
||||||
effectiveDifficulty *
|
* effectiveDifficulty
|
||||||
_mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig) *
|
* _mathUtil.Interp1(pmcLevel, levelsConfig, reputationConfig)
|
||||||
_randomUtil.GetDouble((double) (1 - rewardSpreadConfig), (double) (1 + rewardSpreadConfig)) ??
|
* _randomUtil.GetDouble(
|
||||||
0
|
(double)(1 - rewardSpreadConfig),
|
||||||
) /
|
(double)(1 + rewardSpreadConfig)
|
||||||
100;
|
)
|
||||||
|
?? 0
|
||||||
|
) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int GetRewardNumItems(int pmcLevel, List<double>? levelsConfig, List<double>? itemsConfig)
|
protected int GetRewardNumItems(
|
||||||
|
int pmcLevel,
|
||||||
|
List<double>? levelsConfig,
|
||||||
|
List<double>? itemsConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return _randomUtil.RandInt(1, (int) Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1);
|
return _randomUtil.RandInt(
|
||||||
|
1,
|
||||||
|
(int)Math.Round(_mathUtil.Interp1(pmcLevel, levelsConfig, itemsConfig) ?? 0) + 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double GetRewardRoubles(double? effectiveDifficulty, int pmcLevel, List<double>? levelsConfig,
|
protected double GetRewardRoubles(
|
||||||
|
double? effectiveDifficulty,
|
||||||
|
int pmcLevel,
|
||||||
|
List<double>? levelsConfig,
|
||||||
List<double>? roublesConfig,
|
List<double>? roublesConfig,
|
||||||
double? rewardSpreadConfig)
|
double? rewardSpreadConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return Math.Floor(
|
return Math.Floor(
|
||||||
effectiveDifficulty *
|
effectiveDifficulty
|
||||||
_mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig) *
|
* _mathUtil.Interp1(pmcLevel, levelsConfig, roublesConfig)
|
||||||
_randomUtil.GetDouble(1d - rewardSpreadConfig.Value, 1d + rewardSpreadConfig.Value) ??
|
* _randomUtil.GetDouble(
|
||||||
0
|
1d - rewardSpreadConfig.Value,
|
||||||
|
1d + rewardSpreadConfig.Value
|
||||||
|
)
|
||||||
|
?? 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,8 +396,12 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="itemRewardBudget"> Rouble budget all item rewards must fit in </param>
|
/// <param name="itemRewardBudget"> Rouble budget all item rewards must fit in </param>
|
||||||
/// <param name="repeatableConfig"> Config for quest type </param>
|
/// <param name="repeatableConfig"> Config for quest type </param>
|
||||||
/// <returns> Dictionary of items and stack size</returns>
|
/// <returns> Dictionary of items and stack size</returns>
|
||||||
protected Dictionary<TemplateItem, int> GetRewardableItemsFromPoolWithinBudget(List<TemplateItem> itemPool,
|
protected Dictionary<TemplateItem, int> GetRewardableItemsFromPoolWithinBudget(
|
||||||
int maxItemCount, double itemRewardBudget, RepeatableQuestConfig repeatableConfig)
|
List<TemplateItem> itemPool,
|
||||||
|
int maxItemCount,
|
||||||
|
double itemRewardBudget,
|
||||||
|
RepeatableQuestConfig repeatableConfig
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var itemsToReturn = new Dictionary<TemplateItem, int>();
|
var itemsToReturn = new Dictionary<TemplateItem, int>();
|
||||||
var exhausableItemPool = new ExhaustableArray<TemplateItem>(itemPool, _randomUtil, _cloner);
|
var exhausableItemPool = new ExhaustableArray<TemplateItem>(itemPool, _randomUtil, _cloner);
|
||||||
@@ -346,7 +422,10 @@ 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 (chosenItemFromPool.Properties.StackMaxSize < repeatableConfig.RewardAmmoStackMinSize)
|
if (
|
||||||
|
chosenItemFromPool.Properties.StackMaxSize
|
||||||
|
< repeatableConfig.RewardAmmoStackMinSize
|
||||||
|
)
|
||||||
{
|
{
|
||||||
i--;
|
i--;
|
||||||
continue;
|
continue;
|
||||||
@@ -373,7 +452,9 @@ 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($"Added item: {chosenItemFromPool.Id} with price: {rewardItemStackCount * itemCost}");
|
_logger.Debug(
|
||||||
|
$"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
|
||||||
@@ -390,7 +471,9 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Reward pool empty with: {calculatedItemRewardBudget} roubles of budget remaining");
|
_logger.Debug(
|
||||||
|
$"Reward pool empty with: {calculatedItemRewardBudget} roubles of budget remaining"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,8 +493,11 @@ 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(TemplateItem itemSelected, double roublesBudget,
|
protected int CalculateAmmoStackSizeThatFitsBudget(
|
||||||
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;
|
||||||
@@ -428,20 +514,19 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return (int)Math.Max(1, Math.Min(stackSizeThatFitsBudget, stackMaxCount));
|
return (int)Math.Max(1, Math.Min(stackSizeThatFitsBudget, stackMaxCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool CanIncreaseRewardItemStackSize(TemplateItem item, int maxRoublePriceToStack,
|
protected bool CanIncreaseRewardItemStackSize(
|
||||||
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,
|
item.Id,
|
||||||
[
|
[BaseClasses.WEAPON, BaseClasses.ARMORED_EQUIPMENT, BaseClasses.AMMO]
|
||||||
BaseClasses.WEAPON,
|
)
|
||||||
BaseClasses.ARMORED_EQUIPMENT,
|
&& !_itemHelper.ItemRequiresSoftInserts(item.Id);
|
||||||
BaseClasses.AMMO
|
|
||||||
]
|
|
||||||
) &&
|
|
||||||
!_itemHelper.ItemRequiresSoftInserts(item.Id);
|
|
||||||
|
|
||||||
return isEligibleForStackSizeIncrease && _randomUtil.GetChance100(randomChanceToPass);
|
return isEligibleForStackSizeIncrease && _randomUtil.GetChance100(randomChanceToPass);
|
||||||
}
|
}
|
||||||
@@ -460,7 +545,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
{
|
{
|
||||||
new(3000, [2, 3, 4]),
|
new(3000, [2, 3, 4]),
|
||||||
new(10000, [2, 3]),
|
new(10000, [2, 3]),
|
||||||
new(int.MaxValue, [2, 3, 4]) // Default for prices 10001+ RUB
|
new(int.MaxValue, [2, 3, 4]), // Default for prices 10001+ RUB
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find the appropriate price tier and return a random stack size from its options
|
// Find the appropriate price tier and return a random stack size from its options
|
||||||
@@ -480,8 +565,11 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="roublesBudget"> Total value of items to return </param>
|
/// <param name="roublesBudget"> Total value of items to return </param>
|
||||||
/// <param name="traderId"> ID of the trader who will give player reward </param>
|
/// <param name="traderId"> ID of the trader who will give player reward </param>
|
||||||
/// <returns> List of reward items that fit budget </returns>
|
/// <returns> List of reward items that fit budget </returns>
|
||||||
protected List<TemplateItem> ChooseRewardItemsWithinBudget(RepeatableQuestConfig repeatableConfig,
|
protected List<TemplateItem> ChooseRewardItemsWithinBudget(
|
||||||
double? roublesBudget, string traderId)
|
RepeatableQuestConfig repeatableConfig,
|
||||||
|
double? roublesBudget,
|
||||||
|
string traderId
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// First filter for type and baseclass to avoid lookup in handbook for non-available items
|
// First filter for type and baseclass to avoid lookup in handbook for non-available items
|
||||||
var rewardableItemPool = GetRewardableItems(repeatableConfig, traderId);
|
var rewardableItemPool = GetRewardableItems(repeatableConfig, traderId);
|
||||||
@@ -498,11 +586,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
_localisationService.GetText(
|
_localisationService.GetText(
|
||||||
"repeatable-no_reward_item_found_in_price_range",
|
"repeatable-no_reward_item_found_in_price_range",
|
||||||
new
|
new { minPrice, roublesBudget }
|
||||||
{
|
|
||||||
minPrice,
|
|
||||||
roublesBudget
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -522,15 +606,18 @@ 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(List<TemplateItem> rewardItems, double roublesBudget,
|
protected List<TemplateItem> FilterRewardPoolWithinBudget(
|
||||||
double minPrice)
|
List<TemplateItem> rewardItems,
|
||||||
|
double roublesBudget,
|
||||||
|
double minPrice
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return rewardItems.Where(item =>
|
return rewardItems
|
||||||
|
.Where(item =>
|
||||||
{
|
{
|
||||||
var itemPrice = _presetHelper.GetDefaultPresetOrItemPrice(item.Id);
|
var itemPrice = _presetHelper.GetDefaultPresetOrItemPrice(item.Id);
|
||||||
return itemPrice < roublesBudget && itemPrice > minPrice;
|
return itemPrice < roublesBudget && itemPrice > minPrice;
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +627,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(double roublesBudget, int rewardIndex)
|
protected KeyValuePair<Reward, double>? GetRandomWeaponPresetWithinBudget(
|
||||||
|
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>(
|
||||||
@@ -568,7 +658,12 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
var chosenPreset = _cloner.Clone(randomPreset);
|
var chosenPreset = _cloner.Clone(randomPreset);
|
||||||
|
|
||||||
return new KeyValuePair<Reward, double>(
|
return new KeyValuePair<Reward, double>(
|
||||||
GeneratePresetReward(chosenPreset.Encyclopedia, 1, rewardIndex, chosenPreset.Items),
|
GeneratePresetReward(
|
||||||
|
chosenPreset.Encyclopedia,
|
||||||
|
1,
|
||||||
|
rewardIndex,
|
||||||
|
chosenPreset.Items
|
||||||
|
),
|
||||||
presetPrice
|
presetPrice
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -586,7 +681,13 @@ 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(string tpl, int count, int index, List<Item>? preset, bool foundInRaid = true)
|
protected Reward GeneratePresetReward(
|
||||||
|
string tpl,
|
||||||
|
int count,
|
||||||
|
int index,
|
||||||
|
List<Item>? preset,
|
||||||
|
bool foundInRaid = true
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var id = _hashUtil.Generate();
|
var id = _hashUtil.Generate();
|
||||||
var questRewardItem = new Reward
|
var questRewardItem = new Reward
|
||||||
@@ -601,7 +702,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
IsEncoded = false,
|
IsEncoded = false,
|
||||||
FindInRaid = foundInRaid,
|
FindInRaid = foundInRaid,
|
||||||
Type = RewardType.Item,
|
Type = RewardType.Item,
|
||||||
Items = []
|
Items = [],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get presets root item
|
// Get presets root item
|
||||||
@@ -630,7 +731,12 @@ 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(string tpl, double count, int index, bool foundInRaid = true)
|
protected Reward GenerateItemReward(
|
||||||
|
string tpl,
|
||||||
|
double count,
|
||||||
|
int index,
|
||||||
|
bool foundInRaid = true
|
||||||
|
)
|
||||||
{
|
{
|
||||||
var id = _hashUtil.Generate();
|
var id = _hashUtil.Generate();
|
||||||
var questRewardItem = new Reward
|
var questRewardItem = new Reward
|
||||||
@@ -645,18 +751,14 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
IsEncoded = false,
|
IsEncoded = false,
|
||||||
FindInRaid = foundInRaid,
|
FindInRaid = foundInRaid,
|
||||||
Type = RewardType.Item,
|
Type = RewardType.Item,
|
||||||
Items = []
|
Items = [],
|
||||||
};
|
};
|
||||||
|
|
||||||
var rootItem = new Item
|
var rootItem = new Item
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
Template = tpl,
|
Template = tpl,
|
||||||
Upd = new Upd
|
Upd = new Upd { StackObjectsCount = count, SpawnedInSession = foundInRaid },
|
||||||
{
|
|
||||||
StackObjectsCount = count,
|
|
||||||
SpawnedInSession = foundInRaid
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
questRewardItem.Items = [rootItem];
|
questRewardItem.Items = [rootItem];
|
||||||
|
|
||||||
@@ -667,17 +769,20 @@ 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 = traderId is Traders.PEACEKEEPER or Traders.FENCE ? Money.EUROS : Money.ROUBLES;
|
var currency = traderId is Traders.PEACEKEEPER or 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Picks rewardable items from items.json <br />
|
/// Picks rewardable items from items.json <br />
|
||||||
/// This means they must: <br />
|
/// This means they must: <br />
|
||||||
@@ -688,7 +793,10 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="repeatableQuestConfig"> Config </param>
|
/// <param name="repeatableQuestConfig"> Config </param>
|
||||||
/// <param name="tradderId"> ID of trader who will give reward to player </param>
|
/// <param name="tradderId"> 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(RepeatableQuestConfig repeatableQuestConfig, string traderId)
|
public List<TemplateItem> GetRewardableItems(
|
||||||
|
RepeatableQuestConfig repeatableQuestConfig,
|
||||||
|
string 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();
|
||||||
@@ -696,7 +804,8 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
// Check for specific base classes which don't make sense as reward item
|
// Check for specific base classes which don't make sense as reward item
|
||||||
// also check if the price is greater than 0; there are some items whose price can not be found
|
// also check if the price is greater than 0; there are some items whose price can not be found
|
||||||
// those are not in the game yet (e.g. AGS grenade launcher)
|
// those are not in the game yet (e.g. AGS grenade launcher)
|
||||||
return _databaseService.GetItems()
|
return _databaseService
|
||||||
|
.GetItems()
|
||||||
.Values.Where(itemTemplate =>
|
.Values.Where(itemTemplate =>
|
||||||
{
|
{
|
||||||
// Base "Item" item has no parent, ignore it
|
// Base "Item" item has no parent, ignore it
|
||||||
@@ -710,7 +819,8 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var traderWhitelist = repeatableQuestConfig.TraderWhitelist.FirstOrDefault(trader => trader.TraderId == traderId
|
var traderWhitelist = repeatableQuestConfig.TraderWhitelist.FirstOrDefault(trader =>
|
||||||
|
trader.TraderId == traderId
|
||||||
);
|
);
|
||||||
|
|
||||||
return IsValidRewardItem(
|
return IsValidRewardItem(
|
||||||
@@ -719,8 +829,7 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
repeatableQuestConfig.RewardBaseTypeBlacklist,
|
repeatableQuestConfig.RewardBaseTypeBlacklist,
|
||||||
traderWhitelist?.RewardBaseWhitelist
|
traderWhitelist?.RewardBaseWhitelist
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,10 +842,12 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
/// <param name="itemTypeBlacklist"> Specific item base types to ignore </param>
|
/// <param name="itemTypeBlacklist"> Specific item base types to ignore </param>
|
||||||
/// <param name="itemBaseWhitelist"> Default null, specific trader item base classes</param>
|
/// <param name="itemBaseWhitelist"> Default null, specific trader item base classes</param>
|
||||||
/// <returns> True if item is valid reward </returns>
|
/// <returns> True if item is valid reward </returns>
|
||||||
public bool IsValidRewardItem(string tpl,
|
public bool IsValidRewardItem(
|
||||||
|
string tpl,
|
||||||
HashSet<string> itemTplBlacklist,
|
HashSet<string> itemTplBlacklist,
|
||||||
HashSet<string> itemTypeBlacklist,
|
HashSet<string> itemTypeBlacklist,
|
||||||
List<string>? itemBaseWhitelist = null)
|
List<string>? itemBaseWhitelist = null
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Return early if not valid item to give as reward
|
// Return early if not valid item to give as reward
|
||||||
if (!_itemHelper.IsValidItem(tpl))
|
if (!_itemHelper.IsValidItem(tpl))
|
||||||
@@ -746,10 +857,10 @@ public class RepeatableQuestRewardGenerator(
|
|||||||
|
|
||||||
// Check item is not blacklisted
|
// Check item is not blacklisted
|
||||||
if (
|
if (
|
||||||
_itemFilterService.IsItemBlacklisted(tpl) ||
|
|
||||||
_itemFilterService.IsItemRewardBlacklisted(tpl) ||
|
|
||||||
itemTplBlacklist.Contains(tpl) ||
|
|
||||||
_itemFilterService.IsItemBlacklisted(tpl)
|
_itemFilterService.IsItemBlacklisted(tpl)
|
||||||
|
|| _itemFilterService.IsItemRewardBlacklisted(tpl)
|
||||||
|
|| itemTplBlacklist.Contains(tpl)
|
||||||
|
|| _itemFilterService.IsItemBlacklisted(tpl)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -53,7 +53,10 @@ public class ScavCaseRewardGenerator(
|
|||||||
// Get items that fit the price criteria as set by the scavCase config
|
// Get items that fit the price criteria as set by the scavCase config
|
||||||
var commonPricedItems = GetFilteredItemsByPrice(_dbItemsCache, rewardItemCounts.Common);
|
var commonPricedItems = GetFilteredItemsByPrice(_dbItemsCache, rewardItemCounts.Common);
|
||||||
var rarePricedItems = GetFilteredItemsByPrice(_dbItemsCache, rewardItemCounts.Rare);
|
var rarePricedItems = GetFilteredItemsByPrice(_dbItemsCache, rewardItemCounts.Rare);
|
||||||
var superRarePricedItems = GetFilteredItemsByPrice(_dbItemsCache, rewardItemCounts.Superrare);
|
var superRarePricedItems = GetFilteredItemsByPrice(
|
||||||
|
_dbItemsCache,
|
||||||
|
rewardItemCounts.Superrare
|
||||||
|
);
|
||||||
|
|
||||||
// Get randomly picked items from each item collection, the count range of which is defined in hideout/scavcase.json
|
// Get randomly picked items from each item collection, the count range of which is defined in hideout/scavcase.json
|
||||||
var randomlyPickedCommonRewards = PickRandomRewards(
|
var randomlyPickedCommonRewards = PickRandomRewards(
|
||||||
@@ -65,7 +68,8 @@ public class ScavCaseRewardGenerator(
|
|||||||
var randomlyPickedRareRewards = PickRandomRewards(
|
var randomlyPickedRareRewards = PickRandomRewards(
|
||||||
rarePricedItems,
|
rarePricedItems,
|
||||||
rewardItemCounts.Rare,
|
rewardItemCounts.Rare,
|
||||||
RewardRarity.Rare);
|
RewardRarity.Rare
|
||||||
|
);
|
||||||
|
|
||||||
var randomlyPickedSuperRareRewards = PickRandomRewards(
|
var randomlyPickedSuperRareRewards = PickRandomRewards(
|
||||||
superRarePricedItems,
|
superRarePricedItems,
|
||||||
@@ -74,9 +78,18 @@ public class ScavCaseRewardGenerator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add randomised stack sizes to ammo and money rewards
|
// Add randomised stack sizes to ammo and money rewards
|
||||||
var commonRewards = RandomiseContainerItemRewards(randomlyPickedCommonRewards, RewardRarity.Common);
|
var commonRewards = RandomiseContainerItemRewards(
|
||||||
var rareRewards = RandomiseContainerItemRewards(randomlyPickedRareRewards, RewardRarity.Rare);
|
randomlyPickedCommonRewards,
|
||||||
var superRareRewards = RandomiseContainerItemRewards(randomlyPickedSuperRareRewards, RewardRarity.SuperRare);
|
RewardRarity.Common
|
||||||
|
);
|
||||||
|
var rareRewards = RandomiseContainerItemRewards(
|
||||||
|
randomlyPickedRareRewards,
|
||||||
|
RewardRarity.Rare
|
||||||
|
);
|
||||||
|
var superRareRewards = RandomiseContainerItemRewards(
|
||||||
|
randomlyPickedSuperRareRewards,
|
||||||
|
RewardRarity.SuperRare
|
||||||
|
);
|
||||||
|
|
||||||
var result = new List<List<Item>>();
|
var result = new List<List<Item>>();
|
||||||
result = result.Concat(commonRewards).ToList();
|
result = result.Concat(commonRewards).ToList();
|
||||||
@@ -97,7 +110,8 @@ public class ScavCaseRewardGenerator(
|
|||||||
var inactiveSeasonalItems = _seasonalEventService.GetInactiveSeasonalEventItems();
|
var inactiveSeasonalItems = _seasonalEventService.GetInactiveSeasonalEventItems();
|
||||||
if (!_dbItemsCache.Any())
|
if (!_dbItemsCache.Any())
|
||||||
{
|
{
|
||||||
_dbItemsCache = _databaseService.GetItems()
|
_dbItemsCache = _databaseService
|
||||||
|
.GetItems()
|
||||||
.Values.Where(item =>
|
.Values.Where(item =>
|
||||||
{
|
{
|
||||||
// Base "Item" item has no parent, ignore it
|
// Base "Item" item has no parent, ignore it
|
||||||
@@ -118,9 +132,9 @@ public class ScavCaseRewardGenerator(
|
|||||||
|
|
||||||
// Skip item if item id is on blacklist
|
// Skip item if item id is on blacklist
|
||||||
if (
|
if (
|
||||||
item.Type != "Item" ||
|
item.Type != "Item"
|
||||||
_scavCaseConfig.RewardItemBlacklist.Contains(item.Id) ||
|
|| _scavCaseConfig.RewardItemBlacklist.Contains(item.Id)
|
||||||
_itemFilterService.IsItemBlacklisted(item.Id)
|
|| _itemFilterService.IsItemBlacklisted(item.Id)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -132,13 +146,21 @@ public class ScavCaseRewardGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_scavCaseConfig.AllowBossItemsAsRewards && _itemFilterService.IsBossItem(item.Id))
|
if (
|
||||||
|
!_scavCaseConfig.AllowBossItemsAsRewards
|
||||||
|
&& _itemFilterService.IsBossItem(item.Id)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip item if parent id is blacklisted
|
// Skip item if parent id is blacklisted
|
||||||
if (_itemHelper.IsOfBaseclasses(item.Id, _scavCaseConfig.RewardItemParentBlacklist))
|
if (
|
||||||
|
_itemHelper.IsOfBaseclasses(
|
||||||
|
item.Id,
|
||||||
|
_scavCaseConfig.RewardItemParentBlacklist
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -149,14 +171,14 @@ public class ScavCaseRewardGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_dbAmmoItemsCache.Any())
|
if (!_dbAmmoItemsCache.Any())
|
||||||
{
|
{
|
||||||
_dbAmmoItemsCache = _databaseService.GetItems()
|
_dbAmmoItemsCache = _databaseService
|
||||||
|
.GetItems()
|
||||||
.Values.Where(item =>
|
.Values.Where(item =>
|
||||||
{
|
{
|
||||||
// Base "Item" item has no parent, ignore it
|
// Base "Item" item has no parent, ignore it
|
||||||
@@ -178,8 +200,8 @@ public class ScavCaseRewardGenerator(
|
|||||||
|
|
||||||
// Skip item if item id is on blacklist
|
// Skip item if item id is on blacklist
|
||||||
if (
|
if (
|
||||||
_scavCaseConfig.RewardItemBlacklist.Contains(item.Id) ||
|
_scavCaseConfig.RewardItemBlacklist.Contains(item.Id)
|
||||||
_itemFilterService.IsItemBlacklisted(item.Id)
|
|| _itemFilterService.IsItemBlacklisted(item.Id)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -191,7 +213,10 @@ public class ScavCaseRewardGenerator(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_scavCaseConfig.AllowBossItemsAsRewards && _itemFilterService.IsBossItem(item.Id))
|
if (
|
||||||
|
!_scavCaseConfig.AllowBossItemsAsRewards
|
||||||
|
&& _itemFilterService.IsBossItem(item.Id)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -209,8 +234,7 @@ public class ScavCaseRewardGenerator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +248,8 @@ public class ScavCaseRewardGenerator(
|
|||||||
protected List<TemplateItem> PickRandomRewards(
|
protected List<TemplateItem> PickRandomRewards(
|
||||||
List<TemplateItem> items,
|
List<TemplateItem> items,
|
||||||
RewardCountAndPriceDetails itemFilters,
|
RewardCountAndPriceDetails itemFilters,
|
||||||
string rarity)
|
string rarity
|
||||||
|
)
|
||||||
{
|
{
|
||||||
List<TemplateItem> result = [];
|
List<TemplateItem> result = [];
|
||||||
|
|
||||||
@@ -304,23 +329,27 @@ public class ScavCaseRewardGenerator(
|
|||||||
{
|
{
|
||||||
// Is ammo handbook price between desired range
|
// Is ammo handbook price between desired range
|
||||||
var handbookPrice = _ragfairPriceService.GetStaticPriceForItem(ammo.Id);
|
var handbookPrice = _ragfairPriceService.GetStaticPriceForItem(ammo.Id);
|
||||||
if (_scavCaseConfig.AmmoRewards.AmmoRewardValueRangeRub.TryGetValue(rarity,
|
if (
|
||||||
out var matchingAmmoRewardForRarity) &&
|
_scavCaseConfig.AmmoRewards.AmmoRewardValueRangeRub.TryGetValue(
|
||||||
handbookPrice >= matchingAmmoRewardForRarity.Min &&
|
rarity,
|
||||||
handbookPrice <= matchingAmmoRewardForRarity.Max
|
out var matchingAmmoRewardForRarity
|
||||||
|
)
|
||||||
|
&& handbookPrice >= matchingAmmoRewardForRarity.Min
|
||||||
|
&& handbookPrice <= matchingAmmoRewardForRarity.Max
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
if (!possibleAmmoPool.Any())
|
if (!possibleAmmoPool.Any())
|
||||||
{
|
{
|
||||||
// Filtered pool is empty
|
// Filtered pool is empty
|
||||||
_logger.Warning(localisationService.GetText("scavcase-no_cartridges_found_matching_price"));
|
_logger.Warning(
|
||||||
|
localisationService.GetText("scavcase-no_cartridges_found_matching_price")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a random ammo and return it
|
// Get a random ammo and return it
|
||||||
@@ -334,7 +363,10 @@ public class ScavCaseRewardGenerator(
|
|||||||
/// <param name="rewardItems">items to convert</param>
|
/// <param name="rewardItems">items to convert</param>
|
||||||
/// <param name="rarity">The rarity desired ammo reward is for</param>
|
/// <param name="rarity">The rarity desired ammo reward is for</param>
|
||||||
/// <returns>Product array</returns>
|
/// <returns>Product array</returns>
|
||||||
protected List<List<Item>> RandomiseContainerItemRewards(List<TemplateItem> rewardItems, string rarity)
|
protected List<List<Item>> RandomiseContainerItemRewards(
|
||||||
|
List<TemplateItem> rewardItems,
|
||||||
|
string rarity
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Each array is an item + children
|
// Each array is an item + children
|
||||||
List<List<Item>> result = [];
|
List<List<Item>> result = [];
|
||||||
@@ -346,8 +378,8 @@ public class ScavCaseRewardGenerator(
|
|||||||
{
|
{
|
||||||
Id = _hashUtil.Generate(),
|
Id = _hashUtil.Generate(),
|
||||||
Template = rewardItemDb.Id,
|
Template = rewardItemDb.Id,
|
||||||
Upd = null
|
Upd = null,
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
var rootItem = resultItem.FirstOrDefault();
|
var rootItem = resultItem.FirstOrDefault();
|
||||||
|
|
||||||
@@ -357,14 +389,16 @@ public class ScavCaseRewardGenerator(
|
|||||||
}
|
}
|
||||||
// Armor or weapon = use default preset from globals.json
|
// Armor or weapon = use default preset from globals.json
|
||||||
else if (
|
else if (
|
||||||
_itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(rewardItemDb.Id) ||
|
_itemHelper.ArmorItemHasRemovableOrSoftInsertSlots(rewardItemDb.Id)
|
||||||
_itemHelper.IsOfBaseclass(rewardItemDb.Id, BaseClasses.WEAPON)
|
|| _itemHelper.IsOfBaseclass(rewardItemDb.Id, BaseClasses.WEAPON)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var preset = _presetHelper.GetDefaultPreset(rewardItemDb.Id);
|
var preset = _presetHelper.GetDefaultPreset(rewardItemDb.Id);
|
||||||
if (preset is null)
|
if (preset is null)
|
||||||
{
|
{
|
||||||
_logger.Warning($"No preset for item: {rewardItemDb.Id} {rewardItemDb.Name}, skipping");
|
_logger.Warning(
|
||||||
|
$"No preset for item: {rewardItemDb.Id} {rewardItemDb.Name}, skipping"
|
||||||
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -375,11 +409,13 @@ public class ScavCaseRewardGenerator(
|
|||||||
|
|
||||||
resultItem = presetAndMods;
|
resultItem = presetAndMods;
|
||||||
}
|
}
|
||||||
else if (_itemHelper.IsOfBaseclasses(rewardItemDb.Id, [BaseClasses.AMMO, BaseClasses.MONEY]))
|
else if (
|
||||||
|
_itemHelper.IsOfBaseclasses(rewardItemDb.Id, [BaseClasses.AMMO, BaseClasses.MONEY])
|
||||||
|
)
|
||||||
{
|
{
|
||||||
rootItem.Upd = new Upd
|
rootItem.Upd = new Upd
|
||||||
{
|
{
|
||||||
StackObjectsCount = GetRandomAmountRewardForScavCase(rewardItemDb, rarity)
|
StackObjectsCount = GetRandomAmountRewardForScavCase(rewardItemDb, rarity),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,19 +432,23 @@ public class ScavCaseRewardGenerator(
|
|||||||
/// <returns>filtered dbItems array</returns>
|
/// <returns>filtered dbItems array</returns>
|
||||||
protected List<TemplateItem> GetFilteredItemsByPrice(
|
protected List<TemplateItem> GetFilteredItemsByPrice(
|
||||||
List<TemplateItem> dbItems,
|
List<TemplateItem> dbItems,
|
||||||
RewardCountAndPriceDetails itemFilters)
|
RewardCountAndPriceDetails itemFilters
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return dbItems.Where(item =>
|
return dbItems
|
||||||
|
.Where(item =>
|
||||||
{
|
{
|
||||||
var handbookPrice = _ragfairPriceService.GetStaticPriceForItem(item.Id);
|
var handbookPrice = _ragfairPriceService.GetStaticPriceForItem(item.Id);
|
||||||
if (handbookPrice >= itemFilters.MinPriceRub && handbookPrice <= itemFilters.MaxPriceRub)
|
if (
|
||||||
|
handbookPrice >= itemFilters.MinPriceRub
|
||||||
|
&& handbookPrice <= itemFilters.MaxPriceRub
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
})
|
||||||
)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +457,9 @@ public class ScavCaseRewardGenerator(
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="scavCaseDetails">production.json/scavRecipes object</param>
|
/// <param name="scavCaseDetails">production.json/scavRecipes object</param>
|
||||||
/// <returns>ScavCaseRewardCountsAndPrices object</returns>
|
/// <returns>ScavCaseRewardCountsAndPrices object</returns>
|
||||||
protected ScavCaseRewardCountsAndPrices GetScavCaseRewardCountsAndPrices(ScavRecipe scavCaseDetails)
|
protected ScavCaseRewardCountsAndPrices GetScavCaseRewardCountsAndPrices(
|
||||||
|
ScavRecipe scavCaseDetails
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return new ScavCaseRewardCountsAndPrices
|
return new ScavCaseRewardCountsAndPrices
|
||||||
{
|
{
|
||||||
@@ -427,22 +469,22 @@ public class ScavCaseRewardGenerator(
|
|||||||
MinCount = scavCaseDetails.EndProducts.Common.Min,
|
MinCount = scavCaseDetails.EndProducts.Common.Min,
|
||||||
MaxCount = scavCaseDetails.EndProducts.Common.Max,
|
MaxCount = scavCaseDetails.EndProducts.Common.Max,
|
||||||
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Common].Min,
|
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Common].Min,
|
||||||
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Common].Max
|
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Common].Max,
|
||||||
},
|
},
|
||||||
Rare = new RewardCountAndPriceDetails
|
Rare = new RewardCountAndPriceDetails
|
||||||
{
|
{
|
||||||
MinCount = scavCaseDetails.EndProducts.Rare.Min,
|
MinCount = scavCaseDetails.EndProducts.Rare.Min,
|
||||||
MaxCount = scavCaseDetails.EndProducts.Rare.Max,
|
MaxCount = scavCaseDetails.EndProducts.Rare.Max,
|
||||||
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Rare].Min,
|
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Rare].Min,
|
||||||
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Rare].Max
|
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.Rare].Max,
|
||||||
},
|
},
|
||||||
Superrare = new RewardCountAndPriceDetails
|
Superrare = new RewardCountAndPriceDetails
|
||||||
{
|
{
|
||||||
MinCount = scavCaseDetails.EndProducts.Superrare.Min,
|
MinCount = scavCaseDetails.EndProducts.Superrare.Min,
|
||||||
MaxCount = scavCaseDetails.EndProducts.Superrare.Max,
|
MaxCount = scavCaseDetails.EndProducts.Superrare.Max,
|
||||||
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.SuperRare].Min,
|
MinPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.SuperRare].Min,
|
||||||
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.SuperRare].Max
|
MaxPriceRub = _scavCaseConfig.RewardItemValueRangeRub[RewardRarity.SuperRare].Max,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +500,7 @@ public class ScavCaseRewardGenerator(
|
|||||||
{
|
{
|
||||||
BaseClasses.AMMO => GetRandomisedAmmoRewardStackSize(itemToCalculate),
|
BaseClasses.AMMO => GetRandomisedAmmoRewardStackSize(itemToCalculate),
|
||||||
BaseClasses.MONEY => GetRandomisedMoneyRewardStackSize(itemToCalculate, rarity),
|
BaseClasses.MONEY => GetRandomisedMoneyRewardStackSize(itemToCalculate, rarity),
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,7 +543,7 @@ public class ScavCaseRewardGenerator(
|
|||||||
_scavCaseConfig.MoneyRewards.GpCount.GetByJsonProp<MinMax<int>>(rarity).Min,
|
_scavCaseConfig.MoneyRewards.GpCount.GetByJsonProp<MinMax<int>>(rarity).Min,
|
||||||
_scavCaseConfig.MoneyRewards.GpCount.GetByJsonProp<MinMax<int>>(rarity).Max
|
_scavCaseConfig.MoneyRewards.GpCount.GetByJsonProp<MinMax<int>>(rarity).Max
|
||||||
),
|
),
|
||||||
_ => 1
|
_ => 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-9
@@ -42,7 +42,9 @@ public class ExternalInventoryMagGen(
|
|||||||
var defaultMagazineTpl = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weapon);
|
var defaultMagazineTpl = _botWeaponGeneratorHelper.GetWeaponsDefaultMagazineTpl(weapon);
|
||||||
var isShotgun = _itemHelper.IsOfBaseclass(weapon.Id, BaseClasses.SHOTGUN);
|
var isShotgun = _itemHelper.IsOfBaseclass(weapon.Id, BaseClasses.SHOTGUN);
|
||||||
|
|
||||||
var randomizedMagazineCount = _botWeaponGeneratorHelper.GetRandomizedMagazineCount(inventoryMagGen.GetMagCount());
|
var randomizedMagazineCount = _botWeaponGeneratorHelper.GetRandomizedMagazineCount(
|
||||||
|
inventoryMagGen.GetMagCount()
|
||||||
|
);
|
||||||
for (var i = 0; i < randomizedMagazineCount; i++)
|
for (var i = 0; i < randomizedMagazineCount; i++)
|
||||||
{
|
{
|
||||||
var magazineWithAmmo = _botWeaponGeneratorHelper.CreateMagazineWithAmmo(
|
var magazineWithAmmo = _botWeaponGeneratorHelper.CreateMagazineWithAmmo(
|
||||||
@@ -73,7 +75,9 @@ public class ExternalInventoryMagGen(
|
|||||||
{
|
{
|
||||||
if (_logger.IsLogEnabled(LogLevel.Debug))
|
if (_logger.IsLogEnabled(LogLevel.Debug))
|
||||||
{
|
{
|
||||||
_logger.Debug($"Failed {fitAttempts} times to add magazine {magazineTpl} to bot inventory, stopping");
|
_logger.Debug(
|
||||||
|
$"Failed {fitAttempts} times to add magazine {magazineTpl} to bot inventory, stopping"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -110,7 +114,10 @@ public class ExternalInventoryMagGen(
|
|||||||
if (magTemplate is null)
|
if (magTemplate is null)
|
||||||
{
|
{
|
||||||
_logger.Error(
|
_logger.Error(
|
||||||
_localisationService.GetText("bot-unable_to_find_default_magazine_item", magazineTpl)
|
_localisationService.GetText(
|
||||||
|
"bot-unable_to_find_default_magazine_item",
|
||||||
|
magazineTpl
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -165,27 +172,34 @@ public class ExternalInventoryMagGen(
|
|||||||
/// <param name="weaponTpl"> Weapon to get mag for </param>
|
/// <param name="weaponTpl"> Weapon to get mag for </param>
|
||||||
/// <param name="magazineBlacklist"> Blacklisted magazines </param>
|
/// <param name="magazineBlacklist"> Blacklisted magazines </param>
|
||||||
/// <returns> Item of chosen magazine </returns>
|
/// <returns> Item of chosen magazine </returns>
|
||||||
public TemplateItem? GetRandomExternalMagazineForInternalMagazineGun(string weaponTpl, List<string> magazineBlacklist)
|
public TemplateItem? GetRandomExternalMagazineForInternalMagazineGun(
|
||||||
|
string weaponTpl,
|
||||||
|
List<string> magazineBlacklist
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// The mag Slot data for the weapon
|
// The mag Slot data for the weapon
|
||||||
var magSlot = _itemHelper.GetItem(weaponTpl).Value.Properties.Slots.FirstOrDefault(x => x.Name == "mod_magazine");
|
var magSlot = _itemHelper
|
||||||
|
.GetItem(weaponTpl)
|
||||||
|
.Value.Properties.Slots.FirstOrDefault(x => x.Name == "mod_magazine");
|
||||||
if (magSlot is null)
|
if (magSlot is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All possible mags that fit into the weapon excluding blacklisted
|
// All possible mags that fit into the weapon excluding blacklisted
|
||||||
var magazinePool = magSlot.Props.Filters[0]
|
var magazinePool = magSlot
|
||||||
|
.Props.Filters[0]
|
||||||
.Filter.Where(x => !magazineBlacklist.Contains(x))
|
.Filter.Where(x => !magazineBlacklist.Contains(x))
|
||||||
.Select(x => _itemHelper.GetItem(x).Value
|
.Select(x => _itemHelper.GetItem(x).Value);
|
||||||
);
|
|
||||||
if (magazinePool is null)
|
if (magazinePool is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-internal magazines that fit into the weapon
|
// Non-internal magazines that fit into the weapon
|
||||||
var externalMagazineOnlyPool = magazinePool.Where(x => x.Properties.ReloadMagType != ReloadMode.InternalMagazine);
|
var externalMagazineOnlyPool = magazinePool.Where(x =>
|
||||||
|
x.Properties.ReloadMagType != ReloadMode.InternalMagazine
|
||||||
|
);
|
||||||
if (externalMagazineOnlyPool is null || !externalMagazineOnlyPool.Any())
|
if (externalMagazineOnlyPool is null || !externalMagazineOnlyPool.Any())
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+5
-4
@@ -5,9 +5,9 @@ using SPTarkov.Server.Core.Models.Enums;
|
|||||||
namespace SPTarkov.Server.Core.Generators.WeaponGen.Implementations;
|
namespace SPTarkov.Server.Core.Generators.WeaponGen.Implementations;
|
||||||
|
|
||||||
[Injectable]
|
[Injectable]
|
||||||
public class InternalMagazineInventoryMagGen(
|
public class InternalMagazineInventoryMagGen(BotWeaponGeneratorHelper _botWeaponGeneratorHelper)
|
||||||
BotWeaponGeneratorHelper _botWeaponGeneratorHelper
|
: InventoryMagGen,
|
||||||
) : InventoryMagGen, IInventoryMagGen
|
IInventoryMagGen
|
||||||
{
|
{
|
||||||
public int GetPriority()
|
public int GetPriority()
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,8 @@ public class InternalMagazineInventoryMagGen(
|
|||||||
|
|
||||||
public bool CanHandleInventoryMagGen(InventoryMagGen inventoryMagGen)
|
public bool CanHandleInventoryMagGen(InventoryMagGen inventoryMagGen)
|
||||||
{
|
{
|
||||||
return inventoryMagGen.GetMagazineTemplate().Properties.ReloadMagType == ReloadMode.InternalMagazine;
|
return inventoryMagGen.GetMagazineTemplate().Properties.ReloadMagType
|
||||||
|
== ReloadMode.InternalMagazine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Process(InventoryMagGen inventoryMagGen)
|
public void Process(InventoryMagGen inventoryMagGen)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user