Add new endpoint to calcualte a reduced raid time for scavs and send the maps base.EscapeTimeLimit
value to client for PMC raids
This commit is contained in:
parent
1350fdb78b
commit
ac459335c0
@ -793,5 +793,106 @@
|
|||||||
"minFillStaticMagazinePercent": 50,
|
"minFillStaticMagazinePercent": 50,
|
||||||
"makeWishingTreeAlwaysGiveGift": true,
|
"makeWishingTreeAlwaysGiveGift": true,
|
||||||
"allowDuplicateItemsInStaticContainers": true,
|
"allowDuplicateItemsInStaticContainers": true,
|
||||||
"looseLootBlacklist": {}
|
"looseLootBlacklist": {},
|
||||||
|
"scavRaidTimeSettings": {
|
||||||
|
"bigmap": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"factory4_day": {
|
||||||
|
"reducedChancePercent": 60,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"factory4_night": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"interchange": {
|
||||||
|
"reducedChancePercent": 50,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rezervbase": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"laboratory": {
|
||||||
|
"reducedChancePercent": 30,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lighthouse": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shoreline": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 25,
|
||||||
|
"40": 10,
|
||||||
|
"60": 1,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tarkovstreets": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 25,
|
||||||
|
"40": 10,
|
||||||
|
"60": 1,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"woods": {
|
||||||
|
"reducedChancePercent": 40,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 25,
|
||||||
|
"40": 10,
|
||||||
|
"60": 1,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"reducedChancePercent": 25,
|
||||||
|
"reductionPercentWeights": {
|
||||||
|
"20": 12,
|
||||||
|
"40": 5,
|
||||||
|
"60": 2,
|
||||||
|
"80": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import { IGameEmptyCrcRequestData } from "@spt-aki/models/eft/game/IGameEmptyCrc
|
|||||||
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
|
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
|
||||||
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
|
import { IGameLogoutResponseData } from "@spt-aki/models/eft/game/IGameLogoutResponseData";
|
||||||
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
|
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
|
||||||
|
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
|
||||||
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
|
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
|
||||||
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
|
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
|
||||||
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
|
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
|
||||||
@ -157,6 +158,16 @@ class GameCallbacks implements OnLoad
|
|||||||
{
|
{
|
||||||
return this.httpResponse.nullResponse();
|
return this.httpResponse.nullResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle singleplayer/settings/getRaidTime
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
public getRaidTime(url: string, request: IGetRaidTimeRequest, sessionID: string): any
|
||||||
|
{
|
||||||
|
return this.httpResponse.noBody(this.gameController.getRaidTime(sessionID, request));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {GameCallbacks};
|
export {GameCallbacks};
|
||||||
|
@ -17,7 +17,7 @@ export class ApplicationContext
|
|||||||
*
|
*
|
||||||
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
|
* const activePlayerSessionId = this.applicationContext.getLatestValue(ContextVariableType.SESSION_ID).getValue<string>();
|
||||||
*
|
*
|
||||||
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.MATCH_INFO).getValue<IStartOfflineRaidRequestData>();
|
* const matchInfo = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION).getValue<IGetRaidConfigurationRequestData>();
|
||||||
* @param type
|
* @param type
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
export enum ContextVariableType
|
export enum ContextVariableType {
|
||||||
{
|
|
||||||
/** Logged in users session id */
|
/** Logged in users session id */
|
||||||
SESSION_ID = 0,
|
SESSION_ID = 0,
|
||||||
/** Currently acive raid information */
|
/** Currently acive raid information */
|
||||||
@ -7,5 +6,5 @@ export enum ContextVariableType
|
|||||||
/** Timestamp when client first connected */
|
/** Timestamp when client first connected */
|
||||||
CLIENT_START_TIMESTAMP = 2,
|
CLIENT_START_TIMESTAMP = 2,
|
||||||
/** When player is loading into map and loot is requested */
|
/** When player is loading into map and loot is requested */
|
||||||
REGISTER_PLAYER_REQUEST = 3,
|
REGISTER_PLAYER_REQUEST = 3
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
|||||||
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
||||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||||
|
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||||
import { ILooseLoot } from "@spt-aki/models/eft/common/ILooseLoot";
|
import { ILooseLoot } from "@spt-aki/models/eft/common/ILooseLoot";
|
||||||
@ -14,7 +15,10 @@ import { ICheckVersionResponse } from "@spt-aki/models/eft/game/ICheckVersionRes
|
|||||||
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
|
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
|
||||||
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
|
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
|
||||||
import { IGameKeepAliveResponse } from "@spt-aki/models/eft/game/IGameKeepAliveResponse";
|
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 { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
|
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";
|
import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||||
import { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
import { AccountTypes } from "@spt-aki/models/enums/AccountTypes";
|
||||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||||
@ -68,6 +72,7 @@ export class GameController
|
|||||||
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
@inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService,
|
||||||
@inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService,
|
@inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService,
|
||||||
@inject("GiftService") protected giftService: GiftService,
|
@inject("GiftService") protected giftService: GiftService,
|
||||||
|
@inject("WeightedRandomHelper") protected weightedRandomHelper: WeightedRandomHelper,
|
||||||
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||||
)
|
)
|
||||||
@ -475,6 +480,53 @@ export class GameController
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* singleplayer/settings/getRaidTime
|
||||||
|
*/
|
||||||
|
public getRaidTime(sessionId: string, request: IGetRaidTimeRequest): IGetRaidTimeResponse
|
||||||
|
{
|
||||||
|
const baseEscapeTimeMinutes = this.databaseServer.getTables().locations[request.Location.toLowerCase()].base.EscapeTimeLimit;
|
||||||
|
const result: IGetRaidTimeResponse = {
|
||||||
|
RaidTimeMinutes: baseEscapeTimeMinutes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pmc raid, send default
|
||||||
|
if (request.Side.toLowerCase() === "pmc")
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're scav
|
||||||
|
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 = this.weightedRandomHelper.getWeightedValue<string>(
|
||||||
|
mapSettings.reductionPercentWeights,
|
||||||
|
);
|
||||||
|
|
||||||
|
// How many minutes raid will be
|
||||||
|
const newRaidTime = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, Number.parseInt(chosenRaidReductionPercent)));
|
||||||
|
|
||||||
|
// Update result object with new time
|
||||||
|
result.RaidTimeMinutes = newRaidTime;
|
||||||
|
|
||||||
|
this.logger.debug(`Reduced: ${request.Location} raid time by: ${chosenRaidReductionPercent}% to ${newRaidTime} minutes`)
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BSG have two values for shotgun dispersion, we make sure both have the same value
|
* BSG have two values for shotgun dispersion, we make sure both have the same value
|
||||||
*/
|
*/
|
||||||
|
@ -38,6 +38,14 @@ export interface ILocationConfig extends IBaseConfig
|
|||||||
allowDuplicateItemsInStaticContainers: boolean;
|
allowDuplicateItemsInStaticContainers: boolean;
|
||||||
/** Key: map, value: loose loot ids to ignore */
|
/** Key: map, value: loose loot ids to ignore */
|
||||||
looseLootBlacklist: Record<string, string[]>;
|
looseLootBlacklist: Record<string, string[]>;
|
||||||
|
/** Key: map, value: settings to control how long scav raids are*/
|
||||||
|
scavRaidTimeSettings: Record<string, IScavRaidTimeLocationSettings>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IScavRaidTimeLocationSettings
|
||||||
|
{
|
||||||
|
reducedChancePercent: number
|
||||||
|
reductionPercentWeights: Record<string, number>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IContainerRandomistionSettings
|
export interface IContainerRandomistionSettings
|
||||||
|
@ -89,6 +89,14 @@ export class GameStaticRouter extends StaticRouter
|
|||||||
return this.gameCallbacks.reportNickname(url, info, sessionID);
|
return this.gameCallbacks.reportNickname(url, info, sessionID);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
new RouteAction(
|
||||||
|
"/singleplayer/settings/getRaidTime",
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
(url: string, info: any, sessionID: string, output: string): any =>
|
||||||
|
{
|
||||||
|
return this.gameCallbacks.getRaidTime(url, info, sessionID);
|
||||||
|
},
|
||||||
|
)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,13 @@ export class HttpResponseUtil
|
|||||||
return this.clearString(this.jsonUtil.serialize(data));
|
return this.clearString(this.jsonUtil.serialize(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Game client needs server responses in a particular format
|
||||||
|
* @param data
|
||||||
|
* @param err
|
||||||
|
* @param errmsg
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
public getBody<T>(data: T, err = 0, errmsg = null): IGetBodyResponseData<T>
|
public getBody<T>(data: T, err = 0, errmsg = null): IGetBodyResponseData<T>
|
||||||
{
|
{
|
||||||
return this.clearString(this.getUnclearedBody(data, err, errmsg));
|
return this.clearString(this.getUnclearedBody(data, err, errmsg));
|
||||||
|
@ -231,6 +231,18 @@ export class RandomUtil
|
|||||||
return Number.parseFloat(((percent * number) / 100).toFixed(toFixed));
|
return Number.parseFloat(((percent * number) / 100).toFixed(toFixed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce a value by a percentage
|
||||||
|
* @param number Value to reduce
|
||||||
|
* @param percentage Percentage to reduce value by
|
||||||
|
* @returns Reduced value
|
||||||
|
*/
|
||||||
|
public reduceValueByPercent(number: number, percentage: number): number
|
||||||
|
{
|
||||||
|
const reductionAmount = number * (percentage / 100);
|
||||||
|
return number - reductionAmount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if number passes a check out of 100
|
* Check if number passes a check out of 100
|
||||||
* @param chancePercent value check needs to be above
|
* @param chancePercent value check needs to be above
|
||||||
|
Loading…
Reference in New Issue
Block a user