insurance service done with raidtimeadjustmentservice
This commit is contained in:
@@ -34,7 +34,7 @@ public class TraderHelper(
|
||||
/// <param name="traderID">Traders Id to get</param>
|
||||
/// <param name="sessionID">Players id</param>
|
||||
/// <returns>Trader base</returns>
|
||||
public TraderBase GetTrader(string traderID, string sessionID)
|
||||
public TraderBase? GetTrader(string traderID, string sessionID)
|
||||
{
|
||||
if (traderID == "ragfair")
|
||||
{
|
||||
@@ -274,7 +274,7 @@ public class TraderHelper(
|
||||
/// </summary>
|
||||
/// <param name="traderId">Traders id</param>
|
||||
/// <returns>Traders key</returns>
|
||||
public Trader GetTraderById(string traderId)
|
||||
public Trader? GetTraderById(string traderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ public record LocationBase
|
||||
public List<object>? Doors { get; set; }
|
||||
|
||||
[JsonPropertyName("EscapeTimeLimit")]
|
||||
public int? EscapeTimeLimit { get; set; }
|
||||
public double? EscapeTimeLimit { get; set; }
|
||||
|
||||
// BSG fucked up another property name
|
||||
[JsonPropertyName("escape_time_limit")]
|
||||
|
||||
@@ -14,7 +14,7 @@ public record Trader
|
||||
public TraderBase? Base { get; set; }
|
||||
|
||||
[JsonPropertyName("dialogue")]
|
||||
public Dictionary<string, List<string>>? Dialogue { get; set; }
|
||||
public Dictionary<string, List<string>?>? Dialogue { get; set; }
|
||||
|
||||
[JsonPropertyName("questassort")]
|
||||
public Dictionary<string, Dictionary<string, string>>? QuestAssort { get; set; }
|
||||
|
||||
@@ -5,13 +5,13 @@ namespace Core.Models.Eft.Game;
|
||||
public record GetRaidTimeResponse
|
||||
{
|
||||
[JsonPropertyName("RaidTimeMinutes")]
|
||||
public int? RaidTimeMinutes { get; set; }
|
||||
public double? RaidTimeMinutes { get; set; }
|
||||
|
||||
[JsonPropertyName("NewSurviveTimeSeconds")]
|
||||
public int? NewSurviveTimeSeconds { get; set; }
|
||||
public double? NewSurviveTimeSeconds { get; set; }
|
||||
|
||||
[JsonPropertyName("OriginalSurvivalTimeSeconds")]
|
||||
public int? OriginalSurvivalTimeSeconds { get; set; }
|
||||
public double? OriginalSurvivalTimeSeconds { get; set; }
|
||||
|
||||
[JsonPropertyName("ExitChanges")]
|
||||
public List<ExtractChange>? ExitChanges { get; set; }
|
||||
@@ -23,11 +23,11 @@ public record ExtractChange
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("MinTime")]
|
||||
public int? MinTime { get; set; }
|
||||
public double? MinTime { get; set; }
|
||||
|
||||
[JsonPropertyName("MaxTime")]
|
||||
public int? MaxTime { get; set; }
|
||||
public double? MaxTime { get; set; }
|
||||
|
||||
[JsonPropertyName("Chance")]
|
||||
public int? Chance { get; set; }
|
||||
public double? Chance { get; set; }
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ public record ScavRaidTimeSettings
|
||||
public ScavRaidTimeConfigSettings Settings { get; set; }
|
||||
|
||||
[JsonPropertyName("maps")]
|
||||
public Dictionary<string, ScavRaidTimeLocationSettings> Maps { get; set; }
|
||||
public Dictionary<string, ScavRaidTimeLocationSettings?>? Maps { get; set; }
|
||||
}
|
||||
|
||||
public record ScavRaidTimeConfigSettings
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace Core.Models.Spt.Location;
|
||||
public record RaidChanges
|
||||
{
|
||||
[JsonPropertyName("dynamicLootPercent")]
|
||||
public float? DynamicLootPercent { get; set; }
|
||||
public double? DynamicLootPercent { get; set; }
|
||||
|
||||
[JsonPropertyName("staticLootPercent")]
|
||||
public float? StaticLootPercent { get; set; }
|
||||
public double? StaticLootPercent { get; set; }
|
||||
|
||||
[JsonPropertyName("simulatedRaidStartSeconds")]
|
||||
public int? SimulatedRaidStartSeconds { get; set; }
|
||||
|
||||
@@ -1,13 +1,39 @@
|
||||
using SptCommon.Annotations;
|
||||
using Core.Helpers;
|
||||
using SptCommon.Annotations;
|
||||
using Core.Models.Eft.Common;
|
||||
using Core.Models.Eft.Common.Tables;
|
||||
using Core.Models.Eft.Profile;
|
||||
using Core.Models.Enums;
|
||||
using Core.Models.Spt.Config;
|
||||
using Core.Models.Spt.Services;
|
||||
using Core.Models.Utils;
|
||||
using Core.Servers;
|
||||
using Core.Utils;
|
||||
using Core.Utils.Cloners;
|
||||
using Insurance = Core.Models.Eft.Profile.Insurance;
|
||||
|
||||
namespace Core.Services;
|
||||
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class InsuranceService
|
||||
public class InsuranceService(
|
||||
ISptLogger<InsuranceService> _logger,
|
||||
DatabaseService _databaseService,
|
||||
RandomUtil _randomUtil,
|
||||
ItemHelper _itemHelper,
|
||||
HashUtil _hashUtil,
|
||||
TimeUtil _timeUtil,
|
||||
SaveServer _saveServer,
|
||||
TraderHelper _traderHelper,
|
||||
ProfileHelper _profileHelper,
|
||||
LocalisationService _localisationService,
|
||||
MailSendService _mailSendService,
|
||||
ConfigServer _configServer,
|
||||
ICloner _cloner
|
||||
)
|
||||
{
|
||||
protected InsuranceConfig _insuranceConfig = _configServer.GetConfig<InsuranceConfig>();
|
||||
protected Dictionary<string, Dictionary<string, List<Item>>?> _insured = new Dictionary<string, Dictionary<string, List<Item>>?>();
|
||||
|
||||
/// <summary>
|
||||
/// Does player have insurance dictionary exists
|
||||
/// </summary>
|
||||
@@ -15,7 +41,7 @@ public class InsuranceService
|
||||
/// <returns>True if exists</returns>
|
||||
public bool InsuranceDictionaryExists(string sessionId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _insured.TryGetValue(sessionId, out var _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -23,14 +49,17 @@ public class InsuranceService
|
||||
/// </summary>
|
||||
/// <param name="sessionId">Profile id (session id)</param>
|
||||
/// <returns>Item list</returns>
|
||||
public Dictionary<string, List<Item>> GetInsurance(string sessionId)
|
||||
public Dictionary<string, List<Item>>? GetInsurance(string sessionId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _insured[sessionId];
|
||||
}
|
||||
|
||||
public void ResetInsurance(string sessionId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (!_insured.TryAdd(sessionId, new Dictionary<string, List<Item>>()))
|
||||
{
|
||||
_insured[sessionId] = new Dictionary<string, List<Item>>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,7 +71,70 @@ public class InsuranceService
|
||||
/// <param name="mapId">Id of the location player died/exited that caused the insurance to be issued on</param>
|
||||
public void StartPostRaidInsuranceLostProcess(PmcData pmcData, string sessionID, string mapId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// Get insurance items for each trader
|
||||
var globals = _databaseService.GetGlobals();
|
||||
foreach (var trader in GetInsurance(sessionID))
|
||||
{
|
||||
var traderEnum = _traderHelper.GetTraderById(trader.Key);
|
||||
if (traderEnum is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("insurance-trader_missing_from_enum", trader.Key));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var traderBase = _traderHelper.GetTrader(trader.Key, sessionID);
|
||||
if (traderBase is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("insurance-unable_to_find_trader_by_id", trader.Key));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var dialogueTemplates = _databaseService.GetTrader(trader.Key).Dialogue;
|
||||
if (dialogueTemplates is null)
|
||||
{
|
||||
_logger.Error(_localisationService.GetText("insurance-trader_lacks_dialogue_property", trader.Key));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
SystemData systemData = new SystemData
|
||||
{
|
||||
Date = _timeUtil.GetDateMailFormat(),
|
||||
Time = _timeUtil.GetTimeMailFormat(),
|
||||
Location = mapId,
|
||||
};
|
||||
|
||||
// Send "i will go look for your stuff" message from trader to player
|
||||
_mailSendService.SendLocalisedNpcMessageToPlayer(
|
||||
sessionID,
|
||||
traderEnum.ToString(),
|
||||
MessageType.NPC_TRADER,
|
||||
_randomUtil.GetArrayValue(dialogueTemplates["insuranceStart"] ?? ["INSURANCE START MESSAGE MISSING"]),
|
||||
null,
|
||||
_timeUtil.GetHoursAsSeconds((int)globals.Configuration?.Insurance?.MaxStorageTimeInHour),
|
||||
systemData
|
||||
);
|
||||
|
||||
// Store insurance to send to player later in profile
|
||||
// Store insurance return details in profile + "hey i found your stuff, here you go!" message details to send to player at a later date
|
||||
_saveServer.GetProfile(sessionID)
|
||||
.InsuranceList.Add(
|
||||
new Insurance
|
||||
{
|
||||
ScheduledTime = (int)GetInsuranceReturnTimestamp(pmcData, traderBase),
|
||||
TraderId = trader.ToString(),
|
||||
MaxStorageTime = (int)GetMaxInsuranceStorageTime(traderBase),
|
||||
SystemData = systemData,
|
||||
MessageType = MessageType.INSURANCE_RETURN,
|
||||
MessageTemplateId = _randomUtil.GetArrayValue(dialogueTemplates["insuranceFound"]),
|
||||
Items = GetInsurance(sessionID)[trader.Key],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ResetInsurance(sessionID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -54,12 +146,59 @@ public class InsuranceService
|
||||
/// <returns>Timestamp to return items to player in seconds</returns>
|
||||
protected double GetInsuranceReturnTimestamp(PmcData pmcData, TraderBase trader)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// If override in config is non-zero, use that instead of trader values
|
||||
if (_insuranceConfig.ReturnTimeOverrideSeconds > 0)
|
||||
{
|
||||
_logger.Debug($"Insurance override used: returning in {_insuranceConfig.ReturnTimeOverrideSeconds} seconds");
|
||||
return _timeUtil.GetTimeStamp() + _insuranceConfig.ReturnTimeOverrideSeconds;
|
||||
}
|
||||
|
||||
var insuranceReturnTimeBonusSum = _profileHelper.GetBonusValueFromProfile(
|
||||
pmcData,
|
||||
BonusType.InsuranceReturnTime
|
||||
);
|
||||
|
||||
// A negative bonus implies a faster return, since we subtract later, invert the value here
|
||||
var insuranceReturnTimeBonusPercent = -(insuranceReturnTimeBonusSum / 100);
|
||||
|
||||
var traderMinReturnAsSeconds = trader.Insurance.MinReturnHour * TimeUtil.OneHourAsSeconds;
|
||||
var traderMaxReturnAsSeconds = trader.Insurance.MaxReturnHour * TimeUtil.OneHourAsSeconds;
|
||||
var randomisedReturnTimeSeconds = _randomUtil.GetInt((int)traderMinReturnAsSeconds, (int)traderMaxReturnAsSeconds);
|
||||
|
||||
// Check for Mark of The Unheard in players special slots (only slot item can fit)
|
||||
var globals = _databaseService.GetGlobals();
|
||||
var hasMarkOfUnheard = _itemHelper.hasItemWithTpl(
|
||||
pmcData.Inventory.Items,
|
||||
ItemTpl.MARKOFUNKNOWN_MARK_OF_THE_UNHEARD,
|
||||
"SpecialSlot"
|
||||
);
|
||||
if (hasMarkOfUnheard)
|
||||
{
|
||||
// Reduce return time by globals multipler value
|
||||
randomisedReturnTimeSeconds *= (int)globals.Configuration.Insurance.CoefOfHavingMarkOfUnknown;
|
||||
}
|
||||
|
||||
// EoD has 30% faster returns
|
||||
var editionModifier = globals.Configuration.Insurance.EditionSendingMessageTime[pmcData.Info.GameVersion];
|
||||
if (editionModifier is not null)
|
||||
{
|
||||
randomisedReturnTimeSeconds *= (int)editionModifier.Multiplier;
|
||||
}
|
||||
|
||||
// Calculate the final return time based on our bonus percent
|
||||
var finalReturnTimeSeconds = randomisedReturnTimeSeconds * (1.0 - insuranceReturnTimeBonusPercent);
|
||||
return _timeUtil.GetTimeStamp() + finalReturnTimeSeconds;
|
||||
}
|
||||
|
||||
protected double GetMaxInsuranceStorageTime(TraderBase traderBase)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (_insuranceConfig.StorageTimeOverrideSeconds > 0)
|
||||
{
|
||||
// Override exists, use instead of traders value
|
||||
return _insuranceConfig.StorageTimeOverrideSeconds;
|
||||
}
|
||||
|
||||
return _timeUtil.GetHoursAsSeconds((int)traderBase.Insurance.MaxStorageTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +207,11 @@ public class InsuranceService
|
||||
/// <param name="equipmentPkg">Gear to store - generated by GetGearLostInRaid()</param>
|
||||
public void StoreGearLostInRaidToSendLater(string sessionID, List<InsuranceEquipmentPkg> equipmentPkg)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// Process all insured items lost in-raid
|
||||
foreach (var gear in equipmentPkg)
|
||||
{
|
||||
AddGearToSend(gear);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,12 +221,38 @@ public class InsuranceService
|
||||
/// <param name="lostInsuredItems">Insured items lost in a raid</param>
|
||||
/// <param name="pmcProfile">Player profile</param>
|
||||
/// <returns>InsuranceEquipmentPkg list</returns>
|
||||
public List<InsuranceEquipmentPkg> MapInsuredItemsToTrader(
|
||||
string sessionId,
|
||||
List<Item> lostInsuredItems,
|
||||
PmcData pmcProfile)
|
||||
public List<InsuranceEquipmentPkg> MapInsuredItemsToTrader(string sessionId, List<Item> lostInsuredItems, PmcData pmcProfile)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
List<InsuranceEquipmentPkg> result = [];
|
||||
|
||||
foreach (var lostItem in lostInsuredItems)
|
||||
{
|
||||
var insuranceDetails = pmcProfile.InsuredItems.FirstOrDefault(insuredItem => insuredItem.ItemId == lostItem.Id);
|
||||
if (insuranceDetails is null)
|
||||
{
|
||||
_logger.Error($"unable to find insurance details for item id: {lostItem.Id} with tpl: {lostItem.Template}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ItemCannotBeLostOnDeath(lostItem, pmcProfile.Inventory.Items))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add insured item + details to return array
|
||||
result.Add(
|
||||
new InsuranceEquipmentPkg
|
||||
{
|
||||
SessionId = sessionId,
|
||||
ItemToReturnToPlayer = lostItem,
|
||||
PmcData = pmcProfile,
|
||||
TraderId = insuranceDetails.TId,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,7 +263,18 @@ public class InsuranceService
|
||||
/// <returns>True if item</returns>
|
||||
protected bool ItemCannotBeLostOnDeath(Item lostItem, List<Item> inventoryItems)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (lostItem.SlotId?.ToLower().StartsWith("specialslot") ?? false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// We check secure container items even tho they are omitted from lostInsuredItems, just in case
|
||||
if (_itemHelper.ItemIsInsideContainer(lostItem, "SecuredContainer", inventoryItems))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,7 +283,27 @@ public class InsuranceService
|
||||
/// <param name="gear">Gear to send</param>
|
||||
protected void AddGearToSend(InsuranceEquipmentPkg gear)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var sessionId = gear.SessionId;
|
||||
var pmcData = gear.PmcData;
|
||||
var itemToReturnToPlayer = gear.ItemToReturnToPlayer;
|
||||
var traderId = gear.TraderId;
|
||||
|
||||
// Ensure insurance array is init
|
||||
if (!InsuranceDictionaryExists(sessionId))
|
||||
{
|
||||
ResetInsurance(sessionId);
|
||||
}
|
||||
|
||||
// init trader insurance array
|
||||
if (!InsuranceTraderArrayExists(sessionId, traderId))
|
||||
{
|
||||
ResetInsuranceTraderArray(sessionId, traderId);
|
||||
}
|
||||
|
||||
AddInsuranceItemToArray(sessionId, traderId, itemToReturnToPlayer);
|
||||
|
||||
// Remove item from insured items array as its been processed
|
||||
pmcData.InsuredItems = pmcData.InsuredItems.Where(item => { return item.ItemId != itemToReturnToPlayer.Id; }).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +314,7 @@ public class InsuranceService
|
||||
/// <returns>True if exists</returns>
|
||||
protected bool InsuranceTraderArrayExists(string sessionId, string traderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return this._insured[sessionId][traderId] is not null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -124,7 +324,7 @@ public class InsuranceService
|
||||
/// <param name="traderId">Trader items insured with</param>
|
||||
public void ResetInsuranceTraderArray(string sessionId, string traderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_insured[sessionId][traderId] = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -135,7 +335,7 @@ public class InsuranceService
|
||||
/// <param name="itemToAdd">Insured item (with children)</param>
|
||||
public void AddInsuranceItemToArray(string sessionId, string traderId, Item itemToAdd)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_insured[sessionId][traderId].Add(itemToAdd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,6 +347,9 @@ public class InsuranceService
|
||||
/// <returns>price in roubles</returns>
|
||||
public double GetRoublePriceToInsureItemWithTrader(PmcData? pmcData, Item inventoryItem, string traderId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var price = _itemHelper.GetStaticItemPrice(inventoryItem.Template) *
|
||||
(_traderHelper.GetLoyaltyLevel(traderId, pmcData).InsurancePriceCoefficient / 100);
|
||||
|
||||
return Math.Ceiling(price ?? 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,28 @@
|
||||
using SptCommon.Annotations;
|
||||
using Core.Context;
|
||||
using Core.Helpers;
|
||||
using SptCommon.Annotations;
|
||||
using Core.Models.Eft.Common;
|
||||
using Core.Models.Eft.Game;
|
||||
using Core.Models.Spt.Config;
|
||||
using Core.Models.Spt.Location;
|
||||
using Core.Models.Utils;
|
||||
using Core.Servers;
|
||||
using Core.Utils;
|
||||
|
||||
namespace Core.Services;
|
||||
|
||||
[Injectable(InjectionType.Singleton)]
|
||||
public class RaidTimeAdjustmentService
|
||||
public class RaidTimeAdjustmentService(
|
||||
ISptLogger<RaidTimeAdjustmentService> _logger,
|
||||
DatabaseService _databaseService,
|
||||
RandomUtil _randomUtil,
|
||||
WeightedRandomHelper _weightedRandomHelper,
|
||||
ApplicationContext _applicationContext,
|
||||
ConfigServer _configServer
|
||||
)
|
||||
{
|
||||
protected LocationConfig _locationConfig = _configServer.GetConfig<LocationConfig>();
|
||||
|
||||
/// <summary>
|
||||
/// Make alterations to the base map data passed in
|
||||
/// Loot multipliers/waves/wave start times
|
||||
@@ -17,7 +31,20 @@ public class RaidTimeAdjustmentService
|
||||
/// <param name="mapBase">Map to adjust</param>
|
||||
public void MakeAdjustmentsToMap(RaidChanges raidAdjustments, LocationBase mapBase)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_logger.Debug(
|
||||
$"Adjusting dynamic loot multipliers to {raidAdjustments.DynamicLootPercent}% and static loot multipliers to {raidAdjustments.StaticLootPercent}% of original"
|
||||
);
|
||||
|
||||
// Change loot multipler values before they're used below
|
||||
AdjustLootMultipliers(_locationConfig.LooseLootMultiplier, raidAdjustments.DynamicLootPercent);
|
||||
AdjustLootMultipliers(_locationConfig.StaticLootMultiplier, raidAdjustments.StaticLootPercent);
|
||||
|
||||
var mapSettings = GetMapSettings(mapBase.Id);
|
||||
if (mapSettings.AdjustWaves)
|
||||
{
|
||||
// Make alterations to bot spawn waves now player is simulated spawning later
|
||||
AdjustWaves(mapBase, raidAdjustments);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,9 +52,14 @@ public class RaidTimeAdjustmentService
|
||||
/// </summary>
|
||||
/// <param name="mapLootMultipliers">Multipliers to adjust</param>
|
||||
/// <param name="loosePercent">Percent to change values to</param>
|
||||
protected void AdjustLootMultipliers(LootMultiplier mapLootMultipliers, float loosePercent)
|
||||
protected void AdjustLootMultipliers(LootMultiplier mapLootMultiplers, double? loosePercent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var props = mapLootMultiplers.GetType().GetProperties();
|
||||
foreach (var multiplier in props)
|
||||
{
|
||||
var propValue = (double)multiplier.GetValue(mapLootMultiplers);
|
||||
multiplier.SetValue(mapLootMultiplers, _randomUtil.GetPercentOfValue(propValue, loosePercent ?? 1));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,7 +69,21 @@ public class RaidTimeAdjustmentService
|
||||
/// <param name="raidAdjustments">Map adjustments</param>
|
||||
protected void AdjustWaves(LocationBase mapBase, RaidChanges raidAdjustments)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
// Remove waves that spawned before the player joined
|
||||
var originalWaveCount = mapBase.Waves.Count;
|
||||
mapBase.Waves = mapBase.Waves.Where(x => x.TimeMax > raidAdjustments.SimulatedRaidStartSeconds).ToList();
|
||||
|
||||
// Adjust wave min/max times to match new simulated start
|
||||
foreach (var wave in mapBase.Waves)
|
||||
{
|
||||
// Dont let time fall below 0
|
||||
wave.TimeMax -= Math.Max(raidAdjustments.SimulatedRaidStartSeconds ?? 1, 0);
|
||||
wave.TimeMax -= Math.Max(raidAdjustments.SimulatedRaidStartSeconds ?? 1, 0);
|
||||
}
|
||||
|
||||
_logger.Debug(
|
||||
$"Removed {originalWaveCount - mapBase.Waves.Count} wave from map due to simulated raid start time of {raidAdjustments.SimulatedRaidStartSeconds / 60} minutes"
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,7 +94,81 @@ public class RaidTimeAdjustmentService
|
||||
/// <returns>Response to send to client</returns>
|
||||
public GetRaidTimeResponse GetRaidAdjustments(string sessionId, GetRaidTimeRequest request)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var globals = _databaseService.GetGlobals();
|
||||
LocationBase mapBase = _databaseService.GetLocation(request.Location.ToLower()).Base;
|
||||
var baseEscapeTimeMinutes = mapBase.EscapeTimeLimit;
|
||||
|
||||
// Prep result object to return
|
||||
GetRaidTimeResponse result = new GetRaidTimeResponse
|
||||
{
|
||||
RaidTimeMinutes = baseEscapeTimeMinutes,
|
||||
ExitChanges = [],
|
||||
NewSurviveTimeSeconds = null,
|
||||
OriginalSurvivalTimeSeconds = globals.Configuration.Exp.MatchEnd.SurvivedSecondsRequirement,
|
||||
};
|
||||
|
||||
// Pmc raid, send default
|
||||
if (request.Side.ToLower() == "pmc")
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// We're scav adjust values
|
||||
var mapSettings = GetMapSettings(request.Location);
|
||||
|
||||
// Chance of reducing raid time for scav, not guaranteed
|
||||
if (!_randomUtil.GetChance100(mapSettings.ReducedChancePercent))
|
||||
{
|
||||
// Send default
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the weighted percent to reduce the raid time by
|
||||
var chosenRaidReductionPercent = int.Parse(
|
||||
_weightedRandomHelper.GetWeightedValue(mapSettings.ReductionPercentWeights)
|
||||
);
|
||||
var raidTimeRemainingPercent = 100 - chosenRaidReductionPercent;
|
||||
|
||||
// How many minutes raid will last
|
||||
var newRaidTimeMinutes = Math.Floor(
|
||||
_randomUtil.ReduceValueByPercent(baseEscapeTimeMinutes ?? 1, chosenRaidReductionPercent)
|
||||
);
|
||||
|
||||
// Time player spawns into the raid if it was online
|
||||
var simulatedRaidStartTimeMinutes = baseEscapeTimeMinutes - newRaidTimeMinutes;
|
||||
|
||||
if (mapSettings.ReduceLootByPercent)
|
||||
{
|
||||
// Store time reduction percent in app context so loot gen can pick it up later
|
||||
_applicationContext.AddValue(
|
||||
ContextVariableType.RAID_ADJUSTMENTS,
|
||||
new
|
||||
{
|
||||
dynamicLootPercent = Math.Max(raidTimeRemainingPercent, mapSettings.MinDynamicLootPercent),
|
||||
staticLootPercent = Math.Max(raidTimeRemainingPercent, mapSettings.MinStaticLootPercent),
|
||||
simulatedRaidStartSeconds = simulatedRaidStartTimeMinutes * 60,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Update result object with new time
|
||||
result.RaidTimeMinutes = newRaidTimeMinutes;
|
||||
|
||||
_logger.Debug($"Reduced: {request.Location} raid time by: {chosenRaidReductionPercent}% to {newRaidTimeMinutes} minutes");
|
||||
|
||||
// Calculate how long player needs to be in raid to get a `survived` extract status
|
||||
result.NewSurviveTimeSeconds = Math.Max(
|
||||
(result.OriginalSurvivalTimeSeconds - (baseEscapeTimeMinutes - newRaidTimeMinutes) * 60) ?? 0,
|
||||
0D
|
||||
);
|
||||
|
||||
var exitAdjustments = GetExitAdjustments(mapBase, newRaidTimeMinutes);
|
||||
if (exitAdjustments is not null)
|
||||
{
|
||||
result.ExitChanges.AddRange(exitAdjustments);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -58,7 +178,14 @@ public class RaidTimeAdjustmentService
|
||||
/// <returns>ScavRaidTimeLocationSettings</returns>
|
||||
protected ScavRaidTimeLocationSettings GetMapSettings(string location)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var mapSettings = _locationConfig.ScavRaidTimeSettings.Maps?[location.ToLower()];
|
||||
if (mapSettings is null)
|
||||
{
|
||||
_logger.Warning($"Unable to find scav raid time settings for map: {location}, using defaults");
|
||||
return new ScavRaidTimeLocationSettings();
|
||||
}
|
||||
|
||||
return mapSettings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,8 +194,71 @@ public class RaidTimeAdjustmentService
|
||||
/// <param name="mapBase">Map base file player is on</param>
|
||||
/// <param name="newRaidTimeMinutes">How long raid is in minutes</param>
|
||||
/// <returns>List of exit changes to send to client</returns>
|
||||
protected List<ExtractChange> GetExitAdjustments(LocationBase mapBase, int newRaidTimeMinutes)
|
||||
protected List<ExtractChange> GetExitAdjustments(LocationBase mapBase, double newRaidTimeMinutes)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
List<ExtractChange> result = [];
|
||||
// Adjust train exits only
|
||||
foreach (var exit in mapBase.Exits) {
|
||||
if (exit.PassageRequirement != "Train") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare train adjustment object
|
||||
ExtractChange exitChange = new ExtractChange {
|
||||
Name = exit.Name,
|
||||
MinTime = null,
|
||||
MaxTime = null,
|
||||
Chance = null,
|
||||
};
|
||||
|
||||
// At what minute we simulate the player joining the raid
|
||||
var simulatedRaidEntryTimeMinutes = mapBase.EscapeTimeLimit - newRaidTimeMinutes;
|
||||
|
||||
// How many seconds have elapsed in the raid when the player joins
|
||||
var reductionSeconds = simulatedRaidEntryTimeMinutes * 60;
|
||||
|
||||
// Delay between the train extract activating and it becoming available to board
|
||||
//
|
||||
// Test method for determining this value:
|
||||
// 1) Set MinTime, MaxTime, and Count for the train extract all to 120
|
||||
// 2) Load into Reserve or Lighthouse as a PMC (both have the same result)
|
||||
// 3) Board the train when it arrives
|
||||
// 4) Check the raid time on the Raid Ended Screen (it should always be the same)
|
||||
//
|
||||
// trainArrivalDelaySeconds = [raid time on raid-ended screen] - MaxTime - Count - ExfiltrationTime
|
||||
// Example: Raid Time = 5:33 = 333 seconds
|
||||
// trainArrivalDelaySeconds = 333 - 120 - 120 - 5 = 88
|
||||
//
|
||||
// I added 2 seconds just to be safe...
|
||||
//
|
||||
var trainArrivalDelaySeconds =
|
||||
_locationConfig.ScavRaidTimeSettings.Settings.TrainArrivalDelayObservedSeconds;
|
||||
|
||||
// Determine the earliest possible time in the raid when the train would leave
|
||||
var earliestPossibleDepartureMinutes =
|
||||
(exit.MinTime + exit.Count + exit.ExfiltrationTime + trainArrivalDelaySeconds) / 60;
|
||||
|
||||
// If raid is after last moment train can leave, assume train has already left, disable extract
|
||||
var mostPossibleTimeRemainingAfterDeparture = mapBase.EscapeTimeLimit - earliestPossibleDepartureMinutes;
|
||||
if (newRaidTimeMinutes < mostPossibleTimeRemainingAfterDeparture) {
|
||||
exitChange.Chance = 0;
|
||||
|
||||
_logger.Debug($"Train Exit: {exit.Name} disabled as new raid time {newRaidTimeMinutes} minutes is below {mostPossibleTimeRemainingAfterDeparture} minutes");
|
||||
|
||||
result.Add(exitChange);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reduce extract arrival times. Negative values seem to make extract turn red in game.
|
||||
exitChange.MinTime = Math.Max((exit.MinTime - reductionSeconds) ?? 0, 0);
|
||||
exitChange.MaxTime = Math.Max((exit.MaxTime - reductionSeconds) ?? 0, 0);
|
||||
|
||||
_logger.Debug($"Train appears between: {exitChange.MinTime} and {exitChange.MaxTime} seconds raid time");
|
||||
|
||||
result.Add(exitChange);
|
||||
}
|
||||
|
||||
return result.Count > 0 ? result : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class RandomUtil
|
||||
/// <param name="number">The original number to be reduced.</param>
|
||||
/// <param name="percentage">The percentage by which to reduce the number.</param>
|
||||
/// <returns>The reduced number after applying the percentage reduction.</returns>
|
||||
public float ReduceValueByPercent(float number, float percentage)
|
||||
public double ReduceValueByPercent(double number, double percentage)
|
||||
{
|
||||
var reductionAmount = number * percentage / 100;
|
||||
|
||||
|
||||
+3
-1
@@ -1,3 +1,4 @@
|
||||
using System.Runtime;
|
||||
using Core.Context;
|
||||
using Core.Models.External;
|
||||
using Core.Models.Spt.Config;
|
||||
@@ -52,7 +53,8 @@ public static class Program
|
||||
// Get the Built app and run it
|
||||
var app = serviceProvider.GetService<App>();
|
||||
app?.Run().Wait();
|
||||
|
||||
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive);
|
||||
var httpConfig = serviceProvider.GetService<ConfigServer>()?.GetConfig<HttpConfig>();
|
||||
// When we application gets started by the HttpServer it will add into the AppContext the WebApplication
|
||||
// object, which we can use here to start the webapp.
|
||||
|
||||
Reference in New Issue
Block a user