From 7a798d2b604f25b97495331128017475b4c41f57 Mon Sep 17 00:00:00 2001 From: Dev Date: Mon, 27 Nov 2023 15:02:35 +0000 Subject: [PATCH] Reworked `singleplayer/settings/getRaidTime` endpoint Handles adjustments to train extract appearance times Handles time needed to be alive in a raid to get a Success raid status Added extra reduction percent weight: 30% --- project/assets/configs/location.json | 11 +++ project/src/controllers/GameController.ts | 93 +++++++++++++++++-- .../models/eft/game/IGetRaidTimeRequest.ts | 5 + .../models/eft/game/IGetRaidTimeResponse.ts | 15 +++ 4 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 project/src/models/eft/game/IGetRaidTimeRequest.ts create mode 100644 project/src/models/eft/game/IGetRaidTimeResponse.ts diff --git a/project/assets/configs/location.json b/project/assets/configs/location.json index 39409143..9ebf8df3 100644 --- a/project/assets/configs/location.json +++ b/project/assets/configs/location.json @@ -799,6 +799,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -808,6 +809,7 @@ "reducedChancePercent": 60, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -817,6 +819,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -826,6 +829,7 @@ "reducedChancePercent": 50, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -835,6 +839,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -844,6 +849,7 @@ "reducedChancePercent": 30, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -853,6 +859,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 @@ -862,6 +869,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 25, + "30": 15, "40": 10, "60": 1, "80": 1 @@ -871,6 +879,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 25, + "30": 15, "40": 10, "60": 1, "80": 1 @@ -880,6 +889,7 @@ "reducedChancePercent": 40, "reductionPercentWeights": { "20": 25, + "30": 12, "40": 10, "60": 1, "80": 1 @@ -889,6 +899,7 @@ "reducedChancePercent": 25, "reductionPercentWeights": { "20": 12, + "30": 7, "40": 5, "60": 2, "80": 1 diff --git a/project/src/controllers/GameController.ts b/project/src/controllers/GameController.ts index c5fc0bfe..f6b2f86b 100644 --- a/project/src/controllers/GameController.ts +++ b/project/src/controllers/GameController.ts @@ -8,6 +8,7 @@ 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 { Exit, 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"; @@ -16,7 +17,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 { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse"; +import { ExtractChange, IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse"; import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails"; import { IGetRaidConfigurationRequestData } from "@spt-aki/models/eft/match/IGetRaidConfigurationRequestData"; import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile"; @@ -485,9 +486,15 @@ export class GameController */ public getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse { - const baseEscapeTimeMinutes = this.databaseServer.getTables().locations[request.Location.toLowerCase()].base.EscapeTimeLimit; + const mapBase: ILocationBase = this.databaseServer.getTables().locations[request.Location.toLowerCase()].base; + const baseEscapeTimeMinutes = mapBase.EscapeTimeLimit; + + // Prep result object to return const result: IGetRaidTimeResponse = { - RaidTimeMinutes: baseEscapeTimeMinutes + RaidTimeMinutes: baseEscapeTimeMinutes, + ExitChanges: [], + NewSurviveTimeSeconds: null, + OriginalSurvivalTimeSeconds: baseEscapeTimeMinutes } // Pmc raid, send default @@ -496,7 +503,7 @@ export class GameController return result; } - // We're scav + // We're scav adjust values let mapSettings = this.locationConfig.scavRaidTimeSettings[request.Location.toLowerCase()]; if (!mapSettings) { @@ -517,16 +524,88 @@ export class GameController ); // How many minutes raid will be - const newRaidTime = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, Number.parseInt(chosenRaidReductionPercent))); + const newRaidTimeMinutes = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, Number.parseInt(chosenRaidReductionPercent))); // Update result object with new time - result.RaidTimeMinutes = newRaidTime; + result.RaidTimeMinutes = newRaidTimeMinutes; - this.logger.debug(`Reduced: ${request.Location} raid time by: ${chosenRaidReductionPercent}% to ${newRaidTime} minutes`) + this.logger.debug(`Reduced: ${request.Location} raid time by: ${chosenRaidReductionPercent}% to ${newRaidTimeMinutes} minutes`) + + // get our new total raid time as seconds + const newRaidTimeSeconds = newRaidTimeMinutes * 60; + + const originalSurvivalTimeSeconds = this.databaseServer.getTables().globals.config.exp.match_end.survived_seconds_requirement; + result.OriginalSurvivalTimeSeconds = originalSurvivalTimeSeconds; + + // Calculate how long player needs to be in raid to get a `survived` extract status + result.NewSurviveTimeSeconds = Math.max(originalSurvivalTimeSeconds - newRaidTimeSeconds, 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 ; + } + /** * BSG have two values for shotgun dispersion, we make sure both have the same value */ diff --git a/project/src/models/eft/game/IGetRaidTimeRequest.ts b/project/src/models/eft/game/IGetRaidTimeRequest.ts new file mode 100644 index 00000000..bf3fd3e7 --- /dev/null +++ b/project/src/models/eft/game/IGetRaidTimeRequest.ts @@ -0,0 +1,5 @@ +export interface IGetRaidTimeRequest +{ + Side: string, + Location: string +} \ No newline at end of file diff --git a/project/src/models/eft/game/IGetRaidTimeResponse.ts b/project/src/models/eft/game/IGetRaidTimeResponse.ts new file mode 100644 index 00000000..0e5825cb --- /dev/null +++ b/project/src/models/eft/game/IGetRaidTimeResponse.ts @@ -0,0 +1,15 @@ +export interface IGetRaidTimeResponse +{ + RaidTimeMinutes: number + NewSurviveTimeSeconds: number + OriginalSurvivalTimeSeconds: number + ExitChanges: ExtractChange[] +} + +export interface ExtractChange +{ + Name: string + MinTime?: number + MaxTime?: number + Chance?: number +} \ No newline at end of file