Merge branch 'master' of https://dev.sp-tarkov.com/SPT-AKI/Server into 3.8.0
# Conflicts: # project/src/controllers/HideoutController.ts
This commit is contained in:
commit
1db690afb3
@ -512,7 +512,53 @@
|
||||
"RandomTimeSpawn": false,
|
||||
"ChanceGroup": 0
|
||||
}
|
||||
]
|
||||
],
|
||||
"rezervbase": [
|
||||
{
|
||||
"sptId": "sptBearReserveNormalSpawn",
|
||||
"BossName": "sptBear",
|
||||
"BossChance": 15,
|
||||
"BossZone": "ZoneBarrack,ZonePTOR1,ZonePTOR2,ZoneSubCommand,ZoneSubStorage,ZoneRailStrorage",
|
||||
"BossPlayer": false,
|
||||
"BossDifficult": "normal",
|
||||
"BossEscortType": "sptBear",
|
||||
"BossEscortDifficult": "normal",
|
||||
"BossEscortAmount": "1",
|
||||
"Time": -1,
|
||||
"Supports": [{
|
||||
"BossEscortType": "sptBear",
|
||||
"BossEscortDifficult": [
|
||||
"normal"
|
||||
],
|
||||
"BossEscortAmount": "1"
|
||||
}
|
||||
],
|
||||
"RandomTimeSpawn": false,
|
||||
"ChanceGroup": 0
|
||||
},
|
||||
{
|
||||
"sptId": "sptUsecReserveNormalSpawn",
|
||||
"BossName": "sptUsec",
|
||||
"BossChance": 15,
|
||||
"BossZone": "ZoneBarrack,ZonePTOR1,ZonePTOR2,ZoneSubCommand,ZoneSubStorage,ZoneRailStrorage",
|
||||
"BossPlayer": false,
|
||||
"BossDifficult": "normal",
|
||||
"BossEscortType": "sptUsec",
|
||||
"BossEscortDifficult": "normal",
|
||||
"BossEscortAmount": "1",
|
||||
"Time": -1,
|
||||
"Supports": [{
|
||||
"BossEscortType": "sptUsec",
|
||||
"BossEscortDifficult": [
|
||||
"normal"
|
||||
],
|
||||
"BossEscortAmount": "1"
|
||||
}
|
||||
],
|
||||
"RandomTimeSpawn": false,
|
||||
"ChanceGroup": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"normal": {
|
||||
"factory4_day": [{
|
||||
@ -795,190 +841,194 @@
|
||||
"allowDuplicateItemsInStaticContainers": true,
|
||||
"looseLootBlacklist": {},
|
||||
"scavRaidTimeSettings": {
|
||||
"bigmap": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"reductionPercentWeights": {
|
||||
"20": 1,
|
||||
"25": 2,
|
||||
"30": 4,
|
||||
"35": 4,
|
||||
"40": 4,
|
||||
"45": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
"settings": {
|
||||
"trainArrivalDelayObservedSeconds": 90
|
||||
},
|
||||
"factory4_day": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 80,
|
||||
"reductionPercentWeights": {
|
||||
"5": 2,
|
||||
"20": 3,
|
||||
"25": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"80": 2,
|
||||
"85": 1
|
||||
"maps": {
|
||||
"bigmap": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 1,
|
||||
"25": 2,
|
||||
"30": 4,
|
||||
"35": 4,
|
||||
"40": 4,
|
||||
"45": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"factory4_night": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"reductionPercentWeights": {
|
||||
"20": 4,
|
||||
"30": 3,
|
||||
"40": 3,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"80": 1
|
||||
"factory4_day": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"5": 2,
|
||||
"20": 3,
|
||||
"25": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"75": 2
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"interchange": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"reductionPercentWeights": {
|
||||
"20": 5,
|
||||
"25": 5,
|
||||
"30": 5,
|
||||
"35": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
"factory4_night": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 75,
|
||||
"reductionPercentWeights": {
|
||||
"20": 4,
|
||||
"30": 3,
|
||||
"40": 3,
|
||||
"60": 2,
|
||||
"70": 2,
|
||||
"75": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"rezervbase": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"interchange": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 5,
|
||||
"25": 5,
|
||||
"30": 5,
|
||||
"35": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"rezervbase": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 3,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 3,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"laboratory": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
"laboratory": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"lighthouse": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 60,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"25": 2,
|
||||
"30": 4,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
"lighthouse": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"25": 2,
|
||||
"30": 4,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 2,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"shoreline": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 60,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"25": 3,
|
||||
"30": 5,
|
||||
"35": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
"shoreline": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"25": 3,
|
||||
"30": 5,
|
||||
"35": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"tarkovstreets": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 70,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"30": 4,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 4,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
"tarkovstreets": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 2,
|
||||
"30": 4,
|
||||
"40": 4,
|
||||
"50": 4,
|
||||
"60": 4,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"woods": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 60,
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 1,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
"woods": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 40,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"20": 3,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 1,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"adjustWaves": true
|
||||
},
|
||||
"default": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 50,
|
||||
"reducedChancePercent": 50,
|
||||
"reductionPercentWeights": {
|
||||
"10": 1,
|
||||
"20": 2,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
"default": {
|
||||
"reduceLootByPercent": true,
|
||||
"minDynamicLootPercent": 50,
|
||||
"minStaticLootPercent": 50,
|
||||
"reducedChancePercent": 95,
|
||||
"reductionPercentWeights": {
|
||||
"10": 1,
|
||||
"20": 2,
|
||||
"30": 5,
|
||||
"40": 5,
|
||||
"50": 5,
|
||||
"60": 2,
|
||||
"70": 1,
|
||||
"80": 1
|
||||
},
|
||||
"adjustWaves": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,33 @@
|
||||
{
|
||||
"fail": {},
|
||||
"started": {},
|
||||
"success": {
|
||||
"6507ff21644a656aee0f758f": "596b455186f77457cb50eccb",
|
||||
"6507ff21644a656aee0f74b7": "5b4794cb86f774598100d5d4",
|
||||
"6507ff20644a656aee0f744d": "5c0bbaa886f7746941031d82",
|
||||
"6507ff22644a656aee0f75d3": "5c0bbaa886f7746941031d82",
|
||||
"6507ff20644a656aee0f73e4": "596b36c586f77450d6045ad2",
|
||||
"6507ff22644a656aee0f76e1": "596b36c586f77450d6045ad2",
|
||||
"6507ff20644a656aee0f743f": "5979eee086f774311955e614",
|
||||
"6507ff22644a656aee0f75e5": "5b478ff486f7744d184ecbbf",
|
||||
"6507ff21644a656aee0f75a8": "5a27d2af86f7744e1115b323",
|
||||
"6507ff21644a656aee0f7481": "5c0bdb5286f774166e38eed4",
|
||||
"6507ff20644a656aee0f744b": "5c1234c286f77406fa13baeb",
|
||||
"6507ff20644a656aee0f7465": "596b43fb86f77457ca186186",
|
||||
"6507ff20644a656aee0f7447": "5a27b87686f77460de0252a8",
|
||||
"6507ff20644a656aee0f73d6": "5967725e86f774601a446662",
|
||||
"652376e2f6c67195e4061382": "6179b5eabca27a099552e052",
|
||||
"6507ff20644a656aee0f73bc": "6193850f60b34236ee0483de",
|
||||
"6492e44bf4287b13040fcbae": "6179b5eabca27a099552e052",
|
||||
"6492e44bf4287b13040fccf6": "647710905320c660d91c15a5",
|
||||
"64a8578f0e9876295f0f83ed": "649af47d717cb30e7e4b5e26",
|
||||
"64a8578f0e9876295f0f83ee": "649af47d717cb30e7e4b5e26",
|
||||
"64a8578f0e9876295f0f83ef": "649af47d717cb30e7e4b5e26",
|
||||
"6507ff20644a656aee0f738e": "6179b4f16e9dd54ac275e407",
|
||||
"6507ff20644a656aee0f73bc": "6193850f60b34236ee0483de",
|
||||
"6507ff20644a656aee0f73d4": "6179b4f16e9dd54ac275e407",
|
||||
"6507ff20644a656aee0f73d6": "5967725e86f774601a446662",
|
||||
"6507ff20644a656aee0f73e4": "596b36c586f77450d6045ad2",
|
||||
"6507ff20644a656aee0f743f": "5979eee086f774311955e614",
|
||||
"6507ff20644a656aee0f7447": "5a27b87686f77460de0252a8",
|
||||
"6507ff20644a656aee0f744b": "5c1234c286f77406fa13baeb",
|
||||
"6507ff20644a656aee0f744d": "5c0bbaa886f7746941031d82",
|
||||
"6507ff20644a656aee0f7465": "596b43fb86f77457ca186186",
|
||||
"6507ff21644a656aee0f7481": "5c0bdb5286f774166e38eed4",
|
||||
"6507ff21644a656aee0f7498": "6179b4f16e9dd54ac275e407",
|
||||
"6507ff21644a656aee0f74a6": "5ac242ab86f77412464f68b4",
|
||||
"6507ff21644a656aee0f757d": "639873003693c63d86328f25",
|
||||
"6507ff22644a656aee0f7624": "64f5e20652fc01298e2c61e3",
|
||||
"6507ff21644a656aee0f74b7": "5b4794cb86f774598100d5d4",
|
||||
"6507ff21644a656aee0f751c": "64f6aafd67e11a7c6206e0d0",
|
||||
"64cac5c1d45ace5bc90c74a8": "649af47d717cb30e7e4b5e26",
|
||||
"64cac5c1d45ace5bc90c74a9": "649af47d717cb30e7e4b5e26",
|
||||
"64cac5c1d45ace5bc90c74aa": "649af47d717cb30e7e4b5e26",
|
||||
"64cac5c1d45ace5bc90c74ab": "647710905320c660d91c15a5"
|
||||
},
|
||||
"fail": {}
|
||||
}
|
||||
"6507ff21644a656aee0f757d": "639873003693c63d86328f25",
|
||||
"6507ff21644a656aee0f758f": "596b455186f77457cb50eccb",
|
||||
"6507ff21644a656aee0f75a8": "5a27d2af86f7744e1115b323",
|
||||
"6507ff22644a656aee0f75d3": "5c0bbaa886f7746941031d82",
|
||||
"6507ff22644a656aee0f75e5": "5b478ff486f7744d184ecbbf",
|
||||
"6507ff22644a656aee0f7624": "64f5e20652fc01298e2c61e3",
|
||||
"6507ff22644a656aee0f76e1": "596b36c586f77450d6045ad2"
|
||||
}
|
||||
}
|
||||
|
@ -320,6 +320,7 @@ export class HideoutController
|
||||
{
|
||||
// Update existing items container tpl to point to new id (tpl)
|
||||
existingInventoryItem._tpl = hideoutStage.container;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -357,7 +358,7 @@ export class HideoutController
|
||||
* Handle HideoutPutItemsInAreaSlots
|
||||
* Create item in hideout slot item array, remove item from player inventory
|
||||
* @param pmcData Profile data
|
||||
* @param addItemToHideoutRequest request from client to place item in area slot
|
||||
* @param addItemToHideoutRequest reqeust from client to place item in area slot
|
||||
* @param sessionID Session id
|
||||
* @returns IItemEventRouterResponse object
|
||||
*/
|
||||
@ -490,7 +491,14 @@ export class HideoutController
|
||||
|
||||
const itemToReturn = hideoutArea.slots.find((x) => x.locationIndex === slotIndexToRemove).item[0];
|
||||
|
||||
const newReq = { items: [{ item_id: itemToReturn._tpl, count: 1 }], tid: "ragfair" };
|
||||
const newReq = {
|
||||
items: [{
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
item_id: itemToReturn._tpl,
|
||||
count: 1,
|
||||
}],
|
||||
tid: "ragfair",
|
||||
};
|
||||
|
||||
output = this.inventoryHelper.addItem(
|
||||
pmcData,
|
||||
@ -550,7 +558,7 @@ export class HideoutController
|
||||
* Handle HideoutSingleProductionStart event
|
||||
* Start production for an item from hideout area
|
||||
* @param pmcData Player profile
|
||||
* @param body Start production of single item request
|
||||
* @param body Start prodution of single item request
|
||||
* @param sessionID Session id
|
||||
* @returns IItemEventRouterResponse
|
||||
*/
|
||||
@ -665,6 +673,7 @@ export class HideoutController
|
||||
{
|
||||
return productionTime;
|
||||
}
|
||||
|
||||
return productionTime * fenceLevel.ScavCaseTimeModifier;
|
||||
}
|
||||
|
||||
@ -682,7 +691,7 @@ export class HideoutController
|
||||
/**
|
||||
* Start production of continuously created item
|
||||
* @param pmcData Player profile
|
||||
* @param request Continuous production request
|
||||
* @param request Continious production request
|
||||
* @param sessionID Session id
|
||||
* @returns IItemEventRouterResponse
|
||||
*/
|
||||
@ -693,6 +702,7 @@ export class HideoutController
|
||||
): IItemEventRouterResponse
|
||||
{
|
||||
this.registerProduction(pmcData, request, sessionID);
|
||||
|
||||
return this.eventOutputHolder.getOutput(sessionID);
|
||||
}
|
||||
|
||||
@ -757,7 +767,7 @@ export class HideoutController
|
||||
output: IItemEventRouterResponse,
|
||||
): IItemEventRouterResponse
|
||||
{
|
||||
// Variables for management of skill
|
||||
// Variables for managemnet of skill
|
||||
let craftingExpAmount = 0;
|
||||
|
||||
// ? move the logic of BackendCounters in new method?
|
||||
@ -781,7 +791,14 @@ export class HideoutController
|
||||
id = this.presetHelper.getDefaultPreset(id)._id;
|
||||
}
|
||||
|
||||
const newReq = { items: [{ item_id: id, count: recipe.count }], tid: "ragfair" };
|
||||
const newReq = {
|
||||
items: [{
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
item_id: id,
|
||||
count: recipe.count,
|
||||
}],
|
||||
tid: "ragfair",
|
||||
};
|
||||
|
||||
const entries = Object.entries(pmcData.Hideout.Production);
|
||||
let prodId: string;
|
||||
@ -901,7 +918,6 @@ export class HideoutController
|
||||
let prodId: string;
|
||||
for (const production of ongoingProductions)
|
||||
{
|
||||
// Production or ScavCase
|
||||
if (this.hideoutHelper.isProductionType(production[1]))
|
||||
{ // Production or ScavCase
|
||||
if ((production[1] as ScavCase).RecipeId === request.recipeId)
|
||||
@ -927,34 +943,38 @@ export class HideoutController
|
||||
// Create rewards for scav case
|
||||
const scavCaseRewards = this.scavCaseRewardGenerator.generate(request.recipeId);
|
||||
|
||||
// Add scav case rewards to player profile
|
||||
pmcData.Hideout.Production[prodId].Products = scavCaseRewards;
|
||||
|
||||
// Remove the old production from output object before its sent to client
|
||||
delete output.profileChanges[sessionID].production[request.recipeId];
|
||||
|
||||
// Get array of item created + count of them after completing hideout craft
|
||||
const itemsToAdd = pmcData.Hideout.Production[prodId].Products.map(
|
||||
(x: { _tpl: string; upd?: { StackObjectsCount?: number; }; }) =>
|
||||
{
|
||||
let id = x._tpl;
|
||||
if (this.presetHelper.hasPreset(id))
|
||||
{
|
||||
id = this.presetHelper.getDefaultPreset(id)._id;
|
||||
}
|
||||
const itemTpl = this.presetHelper.hasPreset(x._tpl)
|
||||
? this.presetHelper.getDefaultPreset(x._tpl)._id
|
||||
: x._tpl;
|
||||
|
||||
// Count of items crafted
|
||||
const numOfItems = !x.upd?.StackObjectsCount ? 1 : x.upd.StackObjectsCount;
|
||||
return { item_id: id, count: numOfItems };
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
return { item_id: itemTpl, count: numOfItems };
|
||||
},
|
||||
);
|
||||
|
||||
const newReq = { items: itemsToAdd, tid: "ragfair" };
|
||||
|
||||
const callback = () =>
|
||||
{
|
||||
// Flag as complete - will be cleaned up later by update() process
|
||||
// Flag as complete - will be cleaned up later by hideoutController.update()
|
||||
pmcData.Hideout.Production[prodId].sptIsComplete = true;
|
||||
|
||||
// Crafting complete, flag as such
|
||||
pmcData.Hideout.Production[prodId].inProgress = false;
|
||||
};
|
||||
|
||||
// Add crafted item to player inventory
|
||||
return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, true);
|
||||
}
|
||||
|
||||
@ -976,10 +996,11 @@ export class HideoutController
|
||||
|
||||
/**
|
||||
* Get quick time event list for hideout
|
||||
* // TODO: Implement this
|
||||
* // TODO - implement this
|
||||
* @param sessionId Session id
|
||||
* @returns IQteData array
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public getQteList(sessionId: string): IQteData[]
|
||||
{
|
||||
return this.databaseServer.getTables().hideout.qte;
|
||||
@ -992,6 +1013,7 @@ export class HideoutController
|
||||
* @param pmcData Profile to adjust
|
||||
* @param request QTE result object
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public handleQTEEventOutcome(
|
||||
sessionId: string,
|
||||
pmcData: IPmcData,
|
||||
@ -999,10 +1021,10 @@ export class HideoutController
|
||||
): IItemEventRouterResponse
|
||||
{
|
||||
// {
|
||||
// Action: "HideoutQuickTimeEvent",
|
||||
// results: [true, false, true, true, true, true, true, true, true, false, false, false, false, false, false],
|
||||
// id: "63b16feb5d012c402c01f6ef",
|
||||
// timestamp: 1672585349
|
||||
// "Action": "HideoutQuickTimeEvent",
|
||||
// "results": [true, false, true, true, true, true, true, true, true, false, false, false, false, false, false],
|
||||
// "id": "63b16feb5d012c402c01f6ef",
|
||||
// "timestamp": 1672585349
|
||||
// }
|
||||
|
||||
// Skill changes are done in
|
||||
@ -1036,7 +1058,7 @@ export class HideoutController
|
||||
request: IRecordShootingRangePoints,
|
||||
): IItemEventRouterResponse
|
||||
{
|
||||
// Check if counter exists, add placeholder if it doesn't
|
||||
// Check if counter exists, add placeholder if it doesnt
|
||||
if (!pmcData.Stats.Eft.OverallCounters.Items.find((x) => x.Key.includes("ShootingRangePoints")))
|
||||
{
|
||||
pmcData.Stats.Eft.OverallCounters.Items.push({ Key: ["ShootingRangePoints"], Value: 0 });
|
||||
@ -1048,7 +1070,7 @@ export class HideoutController
|
||||
);
|
||||
shootingRangeHighScore.Value = request.points;
|
||||
|
||||
// Check against live, maybe a response isn't necessary
|
||||
// Check against live, maybe a response isnt necessary
|
||||
return this.eventOutputHolder.getOutput(sessionId);
|
||||
}
|
||||
|
||||
@ -1066,7 +1088,7 @@ export class HideoutController
|
||||
{
|
||||
const output = this.eventOutputHolder.getOutput(sessionId);
|
||||
|
||||
// Create mapping of required item with corresponding item from player inventory
|
||||
// Create mapping of required item with corrisponding item from player inventory
|
||||
const items = request.items.map((reqItem) =>
|
||||
{
|
||||
const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id);
|
||||
@ -1115,7 +1137,7 @@ export class HideoutController
|
||||
return this.httpResponse.appendErrorToOutput(output);
|
||||
}
|
||||
|
||||
// Add all improvements to output object
|
||||
// Add all improvemets to output object
|
||||
const improvements = hideoutDbData.stages[profileHideoutArea.level].improvements;
|
||||
const timestamp = this.timeUtil.getTimestamp();
|
||||
|
||||
@ -1164,7 +1186,7 @@ export class HideoutController
|
||||
// Null out production data so client gets informed when response send back
|
||||
pmcData.Hideout.Production[request.recipeId] = null;
|
||||
|
||||
// TODO: handle timestamp somehow?
|
||||
// TODO - handle timestamp somehow?
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -107,17 +107,17 @@ export class InraidController
|
||||
*/
|
||||
protected savePmcProgress(sessionID: string, postRaidRequest: ISaveProgressRequestData): void
|
||||
{
|
||||
const serveProfile = this.saveServer.getProfile(sessionID);
|
||||
const locationName = serveProfile.inraid.location.toLowerCase();
|
||||
const serverProfile = this.saveServer.getProfile(sessionID);
|
||||
const locationName = serverProfile.inraid.location.toLowerCase();
|
||||
|
||||
const map: ILocationBase = this.databaseServer.getTables().locations[locationName].base;
|
||||
const mapHasInsuranceEnabled = map.Insurance;
|
||||
|
||||
let serverPmcProfile = serveProfile.characters.pmc;
|
||||
let serverPmcProfile = serverProfile.characters.pmc;
|
||||
const isDead = this.isPlayerDead(postRaidRequest.exit);
|
||||
const preRaidGear = this.inRaidHelper.getPlayerGear(serverPmcProfile.Inventory.items);
|
||||
|
||||
serveProfile.inraid.character = "pmc";
|
||||
serverProfile.inraid.character = "pmc";
|
||||
|
||||
this.inRaidHelper.updateProfileBaseStats(serverPmcProfile, postRaidRequest, sessionID);
|
||||
this.inRaidHelper.updatePmcProfileDataPostRaid(serverPmcProfile, postRaidRequest, sessionID);
|
||||
@ -220,7 +220,7 @@ export class InraidController
|
||||
activeQuestIdsInProfile,
|
||||
allQuests,
|
||||
);
|
||||
if (questAndFindItemConditionId)
|
||||
if (Object.keys(questAndFindItemConditionId)?.length > 0)
|
||||
{
|
||||
this.profileHelper.removeCompletedQuestConditionFromProfile(pmcData, questAndFindItemConditionId);
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ export class BotWeaponGeneratorHelper
|
||||
|
||||
// Iterate over each grid in the container and look for a big enough space for the item to be placed in
|
||||
let currentGridCount = 1;
|
||||
const slotGridCount = containerTemplate[1]._props.Grids.length;
|
||||
const totalSlotGridCount = containerTemplate[1]._props.Grids.length;
|
||||
for (const slotGrid of containerTemplate[1]._props.Grids)
|
||||
{
|
||||
// Grid is empty, skip
|
||||
@ -280,7 +280,7 @@ export class BotWeaponGeneratorHelper
|
||||
}
|
||||
|
||||
// If we've checked all grids in container and reached this point, there's no space for item
|
||||
if (slotGridCount >= currentGridCount)
|
||||
if (currentGridCount >= totalSlotGridCount)
|
||||
{
|
||||
return ItemAddedResult.NO_SPACE;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ export class InRaidHelper
|
||||
public updatePmcProfileDataPostRaid(pmcData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionId: string): void
|
||||
{
|
||||
// Process failed quests then copy everything
|
||||
this.processFailedQuests(sessionId, pmcData, pmcData.Quests, saveProgressRequest.profile.Quests);
|
||||
this.processFailedQuests(sessionId, pmcData, pmcData.Quests, saveProgressRequest.profile);
|
||||
pmcData.Quests = saveProgressRequest.profile.Quests;
|
||||
|
||||
// No need to do this for scav, old scav is deleted and new one generated
|
||||
@ -254,13 +254,13 @@ export class InRaidHelper
|
||||
* @param sessionId Player id
|
||||
* @param pmcData Player profile
|
||||
* @param preRaidQuests Quests prior to starting raid
|
||||
* @param postRaidQuests Quest after raid
|
||||
* @param postRaidProfile Profile sent by client
|
||||
*/
|
||||
protected processFailedQuests(
|
||||
sessionId: string,
|
||||
pmcData: IPmcData,
|
||||
preRaidQuests: IQuestStatus[],
|
||||
postRaidQuests: IQuestStatus[],
|
||||
postRaidProfile: IPostRaidPmcData,
|
||||
): void
|
||||
{
|
||||
if (!preRaidQuests)
|
||||
@ -270,24 +270,81 @@ export class InRaidHelper
|
||||
}
|
||||
|
||||
// Loop over all quests from post-raid profile
|
||||
for (const postRaidQuest of postRaidQuests)
|
||||
for (const postRaidQuest of postRaidProfile.Quests)
|
||||
{
|
||||
// Find matching pre-raid quest
|
||||
// Find matching pre-raid quest + not already failed
|
||||
const preRaidQuest = preRaidQuests?.find((x) => x.qid === postRaidQuest.qid);
|
||||
if (preRaidQuest)
|
||||
if (!preRaidQuest)
|
||||
{
|
||||
// Post-raid quest is failed but wasn't pre-raid
|
||||
// postRaidQuest.status has a weird value, need to do some nasty casting to compare it
|
||||
if (<string><unknown>postRaidQuest.status === "Fail" && preRaidQuest.status !== QuestStatus.Fail)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Already failed before raid, skip
|
||||
if (preRaidQuest.status === QuestStatus.Fail)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preRaidQuest.status === QuestStatus.Success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Quest failed inside raid, need to handle
|
||||
// postRaidQuest.status has a weird value, need to do some nasty casting to compare it
|
||||
const postRaidQuestStatus = <string><unknown>postRaidQuest.status;
|
||||
if (postRaidQuestStatus === "Fail")
|
||||
{
|
||||
// Send failed message
|
||||
const failBody: IFailQuestRequestData = {
|
||||
Action: "QuestComplete",
|
||||
qid: postRaidQuest.qid,
|
||||
removeExcessItems: true,
|
||||
};
|
||||
this.questHelper.failQuest(pmcData, failBody, sessionId);
|
||||
}
|
||||
// Restartable quests need special actions
|
||||
else if (postRaidQuestStatus === "FailRestartable")
|
||||
{
|
||||
// Does failed quest have requirement to collect items from raid
|
||||
const questDbData = this.questHelper.getQuestFromDb(postRaidQuest.qid, pmcData);
|
||||
// AvailableForFinish
|
||||
const matchingAffFindConditions = questDbData.conditions.AvailableForFinish.filter(x => x._parent === "FindItem");
|
||||
const itemsToCollect: string[] = [];
|
||||
if (matchingAffFindConditions)
|
||||
{
|
||||
// Send failed message
|
||||
const failBody: IFailQuestRequestData = {
|
||||
Action: "QuestComplete",
|
||||
qid: postRaidQuest.qid,
|
||||
removeExcessItems: true,
|
||||
};
|
||||
this.questHelper.failQuest(pmcData, failBody, sessionId);
|
||||
// Find all items the failed quest wanted
|
||||
for (const condition of matchingAffFindConditions)
|
||||
{
|
||||
itemsToCollect.push(...condition._props.target);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove quest items from profile as quest has failed and may still be alive
|
||||
// Required as restarting the quest from main menu does not remove value from CarriedQuestItems array
|
||||
postRaidProfile.Stats.Eft.CarriedQuestItems = postRaidProfile.Stats.Eft.CarriedQuestItems.filter(x => !itemsToCollect.includes(x))
|
||||
|
||||
// Remove quest item from profile now quest is failed
|
||||
// updateProfileBaseStats() has already passed by ref EFT.Stats, all changes applied to postRaid profile also apply to server profile
|
||||
for (const itemTpl of itemsToCollect)
|
||||
{
|
||||
// Look for sessioncounter and remove it
|
||||
const counterIndex = postRaidProfile.Stats.Eft.SessionCounters.Items.findIndex(x => x.Key.includes(itemTpl) && x.Key.includes("LootItem"));
|
||||
if (counterIndex > -1)
|
||||
{
|
||||
postRaidProfile.Stats.Eft.SessionCounters.Items.splice(counterIndex, 1);
|
||||
}
|
||||
|
||||
// Look for quest item and remove it
|
||||
const inventoryItemIndex = postRaidProfile.Inventory.items.findIndex(x => x._tpl === itemTpl);
|
||||
if (inventoryItemIndex > -1)
|
||||
{
|
||||
postRaidProfile.Inventory.items.splice(inventoryItemIndex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear out any completed conditions
|
||||
postRaidQuest.completedConditions = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -951,7 +951,7 @@ export class QuestHelper
|
||||
const questInDb = allQuests.find((x) => x._id === questId);
|
||||
if (!questInDb)
|
||||
{
|
||||
this.logger.warning(
|
||||
this.logger.debug(
|
||||
`Unable to find quest: ${questId} in db, cannot get 'FindItem' condition, skipping`,
|
||||
);
|
||||
continue;
|
||||
|
@ -22,6 +22,7 @@ export class WeightedRandomHelper
|
||||
{
|
||||
const itemKeys = Object.keys(itemArray);
|
||||
const weights = Object.values(itemArray);
|
||||
|
||||
const chosenItem = this.weightedRandom(itemKeys, weights);
|
||||
|
||||
return chosenItem.item;
|
||||
@ -41,18 +42,23 @@ export class WeightedRandomHelper
|
||||
* @param {number[]} weights
|
||||
* @returns {{item: any, index: number}}
|
||||
*/
|
||||
public weightedRandom(items: string | any[], weights: string | any[]): { item: any; index: number; }
|
||||
public weightedRandom(items: any[], weights: any[]): { item: any; index: number; }
|
||||
{
|
||||
if (!items || items.length === 0)
|
||||
{
|
||||
throw new Error("Items must not be empty");
|
||||
}
|
||||
|
||||
if (!weights || weights.length === 0)
|
||||
{
|
||||
throw new Error("Item weights must not be empty");
|
||||
}
|
||||
|
||||
if (items.length !== weights.length)
|
||||
{
|
||||
throw new Error("Items and weight inputs must be of the same length");
|
||||
}
|
||||
|
||||
if (!items.length)
|
||||
{
|
||||
throw new Error("Items must not be empty");
|
||||
}
|
||||
|
||||
// Preparing the cumulative weights array.
|
||||
// For example:
|
||||
// - weights = [1, 4, 3]
|
||||
|
@ -468,7 +468,7 @@ export interface IQuestStatus
|
||||
startTime: number;
|
||||
status: QuestStatus;
|
||||
statusTimers?: Record<string, number>;
|
||||
/** SPT specific property */
|
||||
/** Property does not exist in live profile data, but is used by ProfileChanges.questsStatus when sent to client*/
|
||||
completedConditions?: string[];
|
||||
availableAfter?: number;
|
||||
}
|
||||
@ -483,16 +483,6 @@ export interface TraderInfo
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
/** This object is sent to the client as part of traderRelations */
|
||||
export interface TraderData
|
||||
{
|
||||
salesSum: number;
|
||||
standing: number;
|
||||
loyalty: number;
|
||||
unlocked: boolean;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface RagfairInfo
|
||||
{
|
||||
rating: number;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Health, IQuestStatus, Productive, Skills, TraderData } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { Health, IQuestStatus, Productive, Skills } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { Item, Upd } from "@spt-aki/models/eft/common/tables/IItem";
|
||||
import { IQuest } from "@spt-aki/models/eft/common/tables/IQuest";
|
||||
import { IPmcDataRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests";
|
||||
@ -80,6 +80,16 @@ export interface Improvement
|
||||
improveCompleteTimestamp: number;
|
||||
}
|
||||
|
||||
/** Related to TraderInfo */
|
||||
export interface TraderData
|
||||
{
|
||||
salesSum: number;
|
||||
standing: number;
|
||||
loyalty: number;
|
||||
unlocked: boolean;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface Product
|
||||
{
|
||||
_id: string;
|
||||
|
@ -39,31 +39,7 @@ export interface ILocationConfig extends IBaseConfig
|
||||
/** Key: map, value: loose loot ids to ignore */
|
||||
looseLootBlacklist: Record<string, string[]>;
|
||||
/** Key: map, value: settings to control how long scav raids are*/
|
||||
scavRaidTimeSettings: Record<string, IScavRaidTimeLocationSettings>;
|
||||
}
|
||||
|
||||
export interface IScavRaidTimeLocationSettings
|
||||
{
|
||||
/** Should loot be reduced by same percent length of raid is reduced by */
|
||||
reduceLootByPercent: boolean;
|
||||
minStaticLootPercent: number;
|
||||
minDynamicLootPercent: number;
|
||||
/** Chance raid time is reduced */
|
||||
reducedChancePercent: number;
|
||||
reductionPercentWeights: Record<string, number>;
|
||||
/** Should bot waves be removed / spawn times be adjusted */
|
||||
adjustWaves: boolean;
|
||||
}
|
||||
|
||||
export interface IContainerRandomistionSettings
|
||||
{
|
||||
enabled: boolean;
|
||||
/** What maps can use the container randomisation feature */
|
||||
maps: Record<string, boolean>;
|
||||
/** Some container types don't work when randomised */
|
||||
containerTypesToNotRandomise: string[];
|
||||
containerGroupMinSizeMultiplier: number;
|
||||
containerGroupMaxSizeMultiplier: number;
|
||||
scavRaidTimeSettings: IScavRaidTimeSettings;
|
||||
}
|
||||
|
||||
export interface IFixEmptyBotWavesSettings
|
||||
@ -117,3 +93,38 @@ export interface LootMultiplier
|
||||
terminal: number;
|
||||
town: number;
|
||||
}
|
||||
|
||||
export interface IContainerRandomistionSettings
|
||||
{
|
||||
enabled: boolean;
|
||||
/** What maps can use the container randomisation feature */
|
||||
maps: Record<string, boolean>;
|
||||
/** Some container types don't work when randomised */
|
||||
containerTypesToNotRandomise: string[];
|
||||
containerGroupMinSizeMultiplier: number;
|
||||
containerGroupMaxSizeMultiplier: number;
|
||||
}
|
||||
|
||||
export interface IScavRaidTimeSettings
|
||||
{
|
||||
settings: IScavRaidTimeConfigSettings
|
||||
maps: Record<string, IScavRaidTimeLocationSettings>
|
||||
}
|
||||
|
||||
export interface IScavRaidTimeConfigSettings
|
||||
{
|
||||
trainArrivalDelayObservedSeconds: number
|
||||
}
|
||||
|
||||
export interface IScavRaidTimeLocationSettings
|
||||
{
|
||||
/** Should loot be reduced by same percent length of raid is reduced by */
|
||||
reduceLootByPercent: boolean;
|
||||
minStaticLootPercent: number;
|
||||
minDynamicLootPercent: number;
|
||||
/** Chance raid time is reduced */
|
||||
reducedChancePercent: number;
|
||||
reductionPercentWeights: Record<string, number>;
|
||||
/** Should bot waves be removed / spawn times be adjusted */
|
||||
adjustWaves: boolean;
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IHideoutImprovement, Productive, TraderData, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { ProfileChange } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
|
||||
import { IHideoutImprovement, Productive, TraderInfo } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { ProfileChange, TraderData } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
|
@ -171,11 +171,11 @@ export class RaidTimeAdjustmentService
|
||||
*/
|
||||
protected getMapSettings(location: string): IScavRaidTimeLocationSettings
|
||||
{
|
||||
const mapSettings = this.locationConfig.scavRaidTimeSettings[location.toLowerCase()];
|
||||
const mapSettings = this.locationConfig.scavRaidTimeSettings.maps[location.toLowerCase()];
|
||||
if (!mapSettings)
|
||||
{
|
||||
this.logger.warning(`Unable to find scav raid time settings for map: ${location}, using defaults`);
|
||||
return this.locationConfig.scavRaidTimeSettings.default;
|
||||
return this.locationConfig.scavRaidTimeSettings.maps.default;
|
||||
}
|
||||
|
||||
return mapSettings;
|
||||
@ -205,28 +205,48 @@ export class RaidTimeAdjustmentService
|
||||
MaxTime: null,
|
||||
Chance: null
|
||||
}
|
||||
|
||||
// At what minute we simulate the player joining the raid
|
||||
const simulatedRaidEntryTimeMinutes = mapBase.EscapeTimeLimit - newRaidTimeMinutes;
|
||||
|
||||
// How many seconds have elapsed in the raid when the player joins
|
||||
const 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...
|
||||
//
|
||||
const trainArrivalDelaySeconds = this.locationConfig.scavRaidTimeSettings.settings.trainArrivalDelayObservedSeconds;
|
||||
|
||||
// Determine the earliest possible time in the raid when the train would leave
|
||||
const 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
|
||||
const latestPossibleDepartureMinutes = (exit.MaxTime + exit.Count) / 60;
|
||||
if (newRaidTimeMinutes < latestPossibleDepartureMinutes)
|
||||
const mostPossibleTimeRemainingAfterDeparture = mapBase.EscapeTimeLimit - earliestPossibleDepartureMinutes;
|
||||
if (newRaidTimeMinutes < mostPossibleTimeRemainingAfterDeparture)
|
||||
{
|
||||
exitChange.Chance = 0;
|
||||
|
||||
this.logger.debug(`Train Exit: ${exit.Name} disabled as new raid time ${newRaidTimeMinutes} minutes is below ${latestPossibleDepartureMinutes} minutes`);
|
||||
|
||||
this.logger.debug(`Train Exit: ${exit.Name} disabled as new raid time ${newRaidTimeMinutes} minutes is below ${mostPossibleTimeRemainingAfterDeparture} 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;
|
||||
|
||||
// Reduce extract arrival times. Negative values seem to make extract turn red in game.
|
||||
exitChange.MinTime = Math.max(exit.MinTime - reductionSeconds, 0);
|
||||
exitChange.MaxTime = Math.max(exit.MaxTime - reductionSeconds, 0);
|
||||
|
||||
this.logger.debug(`Train appears between: ${exitChange.MinTime} and ${exitChange.MaxTime} seconds raid time`);
|
||||
|
||||
@ -237,4 +257,4 @@ export class RaidTimeAdjustmentService
|
||||
? result
|
||||
: null ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user