Move raid adjustment code into own service
Rename various parts of sytem to better match what it does
This commit is contained in:
parent
a7e003dca3
commit
dde5c7e8af
@ -7,5 +7,5 @@ export enum ContextVariableType {
|
||||
CLIENT_START_TIMESTAMP = 2,
|
||||
/** When player is loading into map and loot is requested */
|
||||
REGISTER_PLAYER_REQUEST = 3,
|
||||
LOOT_MULTIPLER_CHANGE = 4,
|
||||
RAID_ADJUSTMENTS = 4,
|
||||
}
|
||||
|
@ -5,10 +5,8 @@ import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
|
||||
import { ILooseLoot } from "@spt-aki/models/eft/common/ILooseLoot";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { BodyPartHealth } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
@ -17,7 +15,7 @@ import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupRes
|
||||
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
|
||||
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
|
||||
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
|
||||
import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
|
||||
import { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
|
||||
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
|
||||
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||
import { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
||||
@ -40,6 +38,7 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
|
||||
import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -74,7 +73,7 @@ export class GameController
|
||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||
@inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService,
|
||||
@inject("GiftService") protected giftService: GiftService,
|
||||
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
|
||||
@inject("RaidTimeAdjustmentService") protected raidTimeAdjustmentService: RaidTimeAdjustmentService,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
)
|
||||
@ -565,130 +564,7 @@ export class GameController
|
||||
*/
|
||||
public getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse
|
||||
{
|
||||
const db = this.databaseServer.getTables()
|
||||
|
||||
const mapBase: ILocationBase = db.locations[request.Location.toLowerCase()].base;
|
||||
const baseEscapeTimeMinutes = mapBase.EscapeTimeLimit;
|
||||
|
||||
// Prep result object to return
|
||||
const result: IGetRaidTimeResponse = {
|
||||
RaidTimeMinutes: baseEscapeTimeMinutes,
|
||||
ExitChanges: [],
|
||||
NewSurviveTimeSeconds: null,
|
||||
OriginalSurvivalTimeSeconds: db.globals.config.exp.match_end.survived_seconds_requirement
|
||||
}
|
||||
|
||||
// Pmc raid, send default
|
||||
if (request.Side.toLowerCase() === "pmc")
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// We're scav adjust values
|
||||
let mapSettings = this.locationConfig.scavRaidTimeSettings[request.Location.toLowerCase()];
|
||||
if (!mapSettings)
|
||||
{
|
||||
this.logger.warning(`Unable to find scav raid time settings for map: ${request.Location}, using defaults`);
|
||||
mapSettings = this.locationConfig.scavRaidTimeSettings.default;
|
||||
}
|
||||
|
||||
// Chance of reducing raid time for scav, not guaranteed
|
||||
if (!this.randomUtil.getChance100(mapSettings.reducedChancePercent))
|
||||
{
|
||||
// Send default
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the weighted percent to reduce the raid time by
|
||||
const chosenRaidReductionPercent = Number.parseInt(this.weightedRandomHelper.getWeightedValue<string>(
|
||||
mapSettings.reductionPercentWeights,
|
||||
));
|
||||
|
||||
if (mapSettings.reduceLootByPercent)
|
||||
{
|
||||
// Store time reduction percent in app context so loot gen can pick it up later
|
||||
this.applicationContext.addValue(ContextVariableType.LOOT_MULTIPLER_CHANGE,
|
||||
{
|
||||
dynamicLootPercent: Math.max(chosenRaidReductionPercent, mapSettings.minDynamicLootPercent),
|
||||
staticLootPercent: Math.max(chosenRaidReductionPercent, mapSettings.minStaticLootPercent)
|
||||
});
|
||||
}
|
||||
|
||||
// How many minutes raid will be
|
||||
const newRaidTimeMinutes = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, chosenRaidReductionPercent));
|
||||
|
||||
// Update result object with new time
|
||||
result.RaidTimeMinutes = newRaidTimeMinutes;
|
||||
|
||||
this.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);
|
||||
|
||||
const exitAdjustments = this.getExitAdjustments(mapBase, newRaidTimeMinutes);
|
||||
if (exitAdjustments)
|
||||
{
|
||||
result.ExitChanges.push(...exitAdjustments);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust exit times to handle scavs entering raids part-way through
|
||||
* @param mapBase Map base file player is on
|
||||
* @param newRaidTimeMinutes How long raid is in minutes
|
||||
* @returns List of exit changes to send to client
|
||||
*/
|
||||
protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[]
|
||||
{
|
||||
const result = [];
|
||||
// Adjust train exits only
|
||||
for (const exit of mapBase.exits)
|
||||
{
|
||||
if (exit.PassageRequirement !== "Train")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare train adjustment object
|
||||
const exitChange: ExtractChange = {
|
||||
Name: exit.Name,
|
||||
MinTime: null,
|
||||
MaxTime: null,
|
||||
Chance: null
|
||||
}
|
||||
|
||||
// If raid is after last moment train can leave, assume train has already left, disable extract
|
||||
const latestPossibleDepartureMinutes = (exit.MaxTime + exit.Count) / 60;
|
||||
if (newRaidTimeMinutes < latestPossibleDepartureMinutes)
|
||||
{
|
||||
exitChange.Chance = 0;
|
||||
|
||||
this.logger.debug(`Train Exit: ${exit.Name} disabled as new raid time ${newRaidTimeMinutes} minutes is below ${latestPossibleDepartureMinutes} minutes`);
|
||||
|
||||
result.push(exitChange);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// What minute we simulate the player joining a raid at
|
||||
const simulatedRaidEntryTimeMinutes = mapBase.EscapeTimeLimit - newRaidTimeMinutes;
|
||||
|
||||
// How many seconds to reduce extract arrival times by, negative values seem to make extract turn red in game
|
||||
const reductionSeconds = simulatedRaidEntryTimeMinutes * 60;
|
||||
|
||||
exitChange.MinTime = exit.MinTime - reductionSeconds;
|
||||
exitChange.MaxTime = exit.MaxTime - reductionSeconds;
|
||||
|
||||
this.logger.debug(`Train appears between: ${exitChange.MinTime} and ${exitChange.MaxTime} seconds raid time`);
|
||||
|
||||
result.push(exitChange);
|
||||
}
|
||||
|
||||
return result.length > 0
|
||||
? result
|
||||
: null ;
|
||||
return this.raidTimeAdjustmentService.getRaidAdjustments(sessionId, request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -14,14 +14,15 @@ import { IGetLocationRequestData } from "@spt-aki/models/eft/location/IGetLocati
|
||||
import { AirdropTypeEnum } from "@spt-aki/models/enums/AirdropType";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { IAirdropConfig } from "@spt-aki/models/spt/config/IAirdropConfig";
|
||||
import { ILocationConfig, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
|
||||
import { ILootMultiplerChange } from "@spt-aki/models/spt/location/ILootMultiplerChange";
|
||||
import { ILocationConfig } from "@spt-aki/models/spt/config/ILocationConfig";
|
||||
import { IRaidChanges } from "@spt-aki/models/spt/location/IRaidChanges";
|
||||
import { ILocations } from "@spt-aki/models/spt/server/ILocations";
|
||||
import { LootRequest } from "@spt-aki/models/spt/services/LootRequest";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
@ -41,6 +42,7 @@ export class LocationController
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("LocationGenerator") protected locationGenerator: LocationGenerator,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("RaidTimeAdjustmentService") protected raidTimeAdjustmentService: RaidTimeAdjustmentService,
|
||||
@inject("LootGenerator") protected lootGenerator: LootGenerator,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||
@ -89,15 +91,11 @@ export class LocationController
|
||||
|
||||
// Check for a loot multipler adjustment in app context and apply if one is found
|
||||
let locationConfigCopy: ILocationConfig;
|
||||
const lootMultiplierAdjustment = this.applicationContext.getLatestValue(ContextVariableType.LOOT_MULTIPLER_CHANGE)?.getValue<ILootMultiplerChange>();
|
||||
if (lootMultiplierAdjustment)
|
||||
const raidAdjustments = this.applicationContext.getLatestValue(ContextVariableType.RAID_ADJUSTMENTS)?.getValue<IRaidChanges>();
|
||||
if (raidAdjustments)
|
||||
{
|
||||
this.logger.debug(`Adjusting dynamic loot multipliers to ${lootMultiplierAdjustment.dynamicLootPercent}% and static loot multipliers to ${lootMultiplierAdjustment.staticLootPercent}% of original`)
|
||||
locationConfigCopy = this.jsonUtil.clone(this.locationConfig); // Clone values so they can be used to reset originals later
|
||||
|
||||
// Change loot multipler values before they're used below
|
||||
this.adjustLootMultipliers(this.locationConfig.looseLootMultiplier, lootMultiplierAdjustment.dynamicLootPercent);
|
||||
this.adjustLootMultipliers(this.locationConfig.staticLootMultiplier, lootMultiplierAdjustment.staticLootPercent);
|
||||
this.raidTimeAdjustmentService.makeAdjustmentsToMap(raidAdjustments, output);
|
||||
}
|
||||
|
||||
const staticAmmoDist = this.jsonUtil.clone(db.loot.staticAmmo);
|
||||
@ -125,31 +123,18 @@ export class LocationController
|
||||
this.logger.success(this.localisationService.getText("location-generated_success", name));
|
||||
|
||||
// Reset loot multipliers back to original values
|
||||
if (lootMultiplierAdjustment)
|
||||
if (raidAdjustments)
|
||||
{
|
||||
this.logger.debug("Resetting loot multipliers back to their original values");
|
||||
this.locationConfig.staticLootMultiplier = locationConfigCopy.staticLootMultiplier;
|
||||
this.locationConfig.looseLootMultiplier = locationConfigCopy.looseLootMultiplier;
|
||||
|
||||
this.applicationContext.clearValues(ContextVariableType.LOOT_MULTIPLER_CHANGE);
|
||||
this.applicationContext.clearValues(ContextVariableType.RAID_ADJUSTMENTS);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the loot multiplier values passed in to be a % of their original value
|
||||
* @param mapLootMultiplers Multiplers to adjust
|
||||
* @param loosePercent Percent to change values to
|
||||
*/
|
||||
protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void
|
||||
{
|
||||
for (const key in mapLootMultiplers)
|
||||
{
|
||||
mapLootMultiplers[key] = this.randomUtil.getPercentOfValue(mapLootMultiplers[key], loosePercent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client/locations
|
||||
* Get all maps base location properties without loot data
|
||||
|
@ -216,6 +216,7 @@ import { RagfairOfferService } from "@spt-aki/services/RagfairOfferService";
|
||||
import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService";
|
||||
import { RagfairRequiredItemsService } from "@spt-aki/services/RagfairRequiredItemsService";
|
||||
import { RagfairTaxService } from "@spt-aki/services/RagfairTaxService";
|
||||
import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService";
|
||||
import { RepairService } from "@spt-aki/services/RepairService";
|
||||
import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { TraderAssortService } from "@spt-aki/services/TraderAssortService";
|
||||
@ -707,6 +708,7 @@ export class Container
|
||||
depContainer.register<PmcChatResponseService>("PmcChatResponseService", PmcChatResponseService);
|
||||
depContainer.register<GiftService>("GiftService", GiftService);
|
||||
depContainer.register<MailSendService>("MailSendService", MailSendService);
|
||||
depContainer.register<RaidTimeAdjustmentService>("RaidTimeAdjustmentService", RaidTimeAdjustmentService);
|
||||
}
|
||||
|
||||
private static registerServers(depContainer: DependencyContainer): void
|
||||
|
@ -1,5 +0,0 @@
|
||||
export interface ILootMultiplerChange
|
||||
{
|
||||
dynamicLootPercent: number
|
||||
staticLootPercent: number
|
||||
}
|
9
project/src/models/spt/location/IRaidChanges.ts
Normal file
9
project/src/models/spt/location/IRaidChanges.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export interface IRaidChanges
|
||||
{
|
||||
/** What percentage of dynamic loot should the map contain */
|
||||
dynamicLootPercent: number
|
||||
/** What percentage of static loot should the map contain */
|
||||
staticLootPercent: number
|
||||
/** How many seconds into the raid is the player simulated to spawn in at */
|
||||
simulatedRaidStartSeconds: number
|
||||
}
|
223
project/src/services/RaidTimeAdjustmentService.ts
Normal file
223
project/src/services/RaidTimeAdjustmentService.ts
Normal file
@ -0,0 +1,223 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
|
||||
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
|
||||
import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { ILocationConfig, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
|
||||
import { IRaidChanges } from "@spt-aki/models/spt/location/IRaidChanges";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
@injectable()
|
||||
export class RaidTimeAdjustmentService
|
||||
{
|
||||
protected locationConfig: ILocationConfig;
|
||||
|
||||
constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
|
||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
)
|
||||
{
|
||||
this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make alterations to the base map data passed in
|
||||
* Loot multipliers/waves/wave start times
|
||||
* @param raidAdjustments Changes to process on map
|
||||
* @param mapBase Map to adjust
|
||||
*/
|
||||
public makeAdjustmentsToMap(raidAdjustments: IRaidChanges, mapBase: ILocationBase): void
|
||||
{
|
||||
this.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
|
||||
this.adjustLootMultipliers(this.locationConfig.looseLootMultiplier, raidAdjustments.dynamicLootPercent);
|
||||
this.adjustLootMultipliers(this.locationConfig.staticLootMultiplier, raidAdjustments.staticLootPercent);
|
||||
|
||||
// Make alterations to bot spawn waves now player is simulated spawning later
|
||||
this.adjustWaves(mapBase, raidAdjustments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the loot multiplier values passed in to be a % of their original value
|
||||
* @param mapLootMultiplers Multiplers to adjust
|
||||
* @param loosePercent Percent to change values to
|
||||
*/
|
||||
protected adjustLootMultipliers(mapLootMultiplers: LootMultiplier, loosePercent: number): void
|
||||
{
|
||||
for (const key in mapLootMultiplers)
|
||||
{
|
||||
mapLootMultiplers[key] = this.randomUtil.getPercentOfValue(mapLootMultiplers[key], loosePercent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust bot waves to act as if player spawned later
|
||||
* @param mapBase map to adjust
|
||||
* @param raidAdjustments Map adjustments
|
||||
*/
|
||||
protected adjustWaves(mapBase: ILocationBase, raidAdjustments: IRaidChanges): void
|
||||
{
|
||||
// Remove waves that spawned before the player joined
|
||||
const originalWaveCount = mapBase.waves.length;
|
||||
mapBase.waves = mapBase.waves.filter(x => x.time_max > raidAdjustments.simulatedRaidStartSeconds);
|
||||
|
||||
// Adjust wave min/max times to match new simulated start
|
||||
for (const wave of mapBase.waves)
|
||||
{
|
||||
wave.time_min -= raidAdjustments.simulatedRaidStartSeconds;
|
||||
wave.time_max -= raidAdjustments.simulatedRaidStartSeconds;
|
||||
}
|
||||
|
||||
this.logger.debug(`Removed ${originalWaveCount - mapBase.waves.length} wave from map due to simulated raid start time of ${raidAdjustments.simulatedRaidStartSeconds / 60} minutes`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a randomised adjustment to the raid based on map data in location.json
|
||||
* @param sessionId Session id
|
||||
* @param request Raid adjustment request
|
||||
* @returns Response to send to client
|
||||
*/
|
||||
public getRaidAdjustments(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse
|
||||
{
|
||||
const db = this.databaseServer.getTables()
|
||||
|
||||
const mapBase: ILocationBase = db.locations[request.Location.toLowerCase()].base;
|
||||
const baseEscapeTimeMinutes = mapBase.EscapeTimeLimit;
|
||||
|
||||
// Prep result object to return
|
||||
const result: IGetRaidTimeResponse = {
|
||||
RaidTimeMinutes: baseEscapeTimeMinutes,
|
||||
ExitChanges: [],
|
||||
NewSurviveTimeSeconds: null,
|
||||
OriginalSurvivalTimeSeconds: db.globals.config.exp.match_end.survived_seconds_requirement
|
||||
}
|
||||
|
||||
// Pmc raid, send default
|
||||
if (request.Side.toLowerCase() === "pmc")
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// We're scav adjust values
|
||||
let mapSettings = this.locationConfig.scavRaidTimeSettings[request.Location.toLowerCase()];
|
||||
if (!mapSettings)
|
||||
{
|
||||
this.logger.warning(`Unable to find scav raid time settings for map: ${request.Location}, using defaults`);
|
||||
mapSettings = this.locationConfig.scavRaidTimeSettings.default;
|
||||
}
|
||||
|
||||
// Chance of reducing raid time for scav, not guaranteed
|
||||
if (!this.randomUtil.getChance100(mapSettings.reducedChancePercent))
|
||||
{
|
||||
// Send default
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get the weighted percent to reduce the raid time by
|
||||
const chosenRaidReductionPercent = Number.parseInt(this.weightedRandomHelper.getWeightedValue<string>(
|
||||
mapSettings.reductionPercentWeights,
|
||||
));
|
||||
|
||||
// How many minutes raid will last
|
||||
const newRaidTimeMinutes = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, chosenRaidReductionPercent));
|
||||
|
||||
// Time player spawns into the raid if it was online
|
||||
const simulatedRaidStartTimeMinutes = baseEscapeTimeMinutes - newRaidTimeMinutes;
|
||||
|
||||
if (mapSettings.reduceLootByPercent)
|
||||
{
|
||||
// Store time reduction percent in app context so loot gen can pick it up later
|
||||
this.applicationContext.addValue(ContextVariableType.RAID_ADJUSTMENTS,
|
||||
{
|
||||
dynamicLootPercent: Math.max(chosenRaidReductionPercent, mapSettings.minDynamicLootPercent),
|
||||
staticLootPercent: Math.max(chosenRaidReductionPercent, mapSettings.minStaticLootPercent),
|
||||
simulatedRaidStartSeconds: simulatedRaidStartTimeMinutes * 60
|
||||
});
|
||||
}
|
||||
|
||||
// Update result object with new time
|
||||
result.RaidTimeMinutes = newRaidTimeMinutes;
|
||||
|
||||
this.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);
|
||||
|
||||
const exitAdjustments = this.getExitAdjustments(mapBase, newRaidTimeMinutes);
|
||||
if (exitAdjustments)
|
||||
{
|
||||
result.ExitChanges.push(...exitAdjustments);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust exit times to handle scavs entering raids part-way through
|
||||
* @param mapBase Map base file player is on
|
||||
* @param newRaidTimeMinutes How long raid is in minutes
|
||||
* @returns List of exit changes to send to client
|
||||
*/
|
||||
protected getExitAdjustments(mapBase: ILocationBase, newRaidTimeMinutes: number): ExtractChange[]
|
||||
{
|
||||
const result = [];
|
||||
// Adjust train exits only
|
||||
for (const exit of mapBase.exits)
|
||||
{
|
||||
if (exit.PassageRequirement !== "Train")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare train adjustment object
|
||||
const exitChange: ExtractChange = {
|
||||
Name: exit.Name,
|
||||
MinTime: null,
|
||||
MaxTime: null,
|
||||
Chance: null
|
||||
}
|
||||
|
||||
// If raid is after last moment train can leave, assume train has already left, disable extract
|
||||
const latestPossibleDepartureMinutes = (exit.MaxTime + exit.Count) / 60;
|
||||
if (newRaidTimeMinutes < latestPossibleDepartureMinutes)
|
||||
{
|
||||
exitChange.Chance = 0;
|
||||
|
||||
this.logger.debug(`Train Exit: ${exit.Name} disabled as new raid time ${newRaidTimeMinutes} minutes is below ${latestPossibleDepartureMinutes} minutes`);
|
||||
|
||||
result.push(exitChange);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// What minute we simulate the player joining a raid at
|
||||
const simulatedRaidEntryTimeMinutes = mapBase.EscapeTimeLimit - newRaidTimeMinutes;
|
||||
|
||||
// How many seconds to reduce extract arrival times by, negative values seem to make extract turn red in game
|
||||
const reductionSeconds = simulatedRaidEntryTimeMinutes * 60;
|
||||
|
||||
exitChange.MinTime = exit.MinTime - reductionSeconds;
|
||||
exitChange.MaxTime = exit.MaxTime - reductionSeconds;
|
||||
|
||||
this.logger.debug(`Train appears between: ${exitChange.MinTime} and ${exitChange.MaxTime} seconds raid time`);
|
||||
|
||||
result.push(exitChange);
|
||||
}
|
||||
|
||||
return result.length > 0
|
||||
? result
|
||||
: null ;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user