Add system that adjusts the loot multipliers for a scav raid based on the percentage of the raid time remaining
Controlled per location Most maps are capped at 40/50% min Added multiple config proeprties to configure how system works Added ability to remove all AppContext values by key During `getRaidTime()` loot % modifier values are stored in app context, Then, during `generate()` those values are retreived and applied if found After loot generation values are reset to their original value
This commit is contained in:
parent
f9cf3242c8
commit
9c2725e2fe
@ -796,6 +796,9 @@
|
|||||||
"looseLootBlacklist": {},
|
"looseLootBlacklist": {},
|
||||||
"scavRaidTimeSettings": {
|
"scavRaidTimeSettings": {
|
||||||
"bigmap": {
|
"bigmap": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
@ -806,7 +809,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"factory4_day": {
|
"factory4_day": {
|
||||||
"reducedChancePercent": 60,
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
|
"reducedChancePercent": 50,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
"30": 7,
|
"30": 7,
|
||||||
@ -816,6 +822,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"factory4_night": {
|
"factory4_night": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
@ -826,6 +835,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interchange": {
|
"interchange": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 50,
|
"reducedChancePercent": 50,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
@ -836,7 +848,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rezervbase": {
|
"rezervbase": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
|
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
"30": 7,
|
"30": 7,
|
||||||
@ -846,6 +862,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"laboratory": {
|
"laboratory": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 30,
|
"reducedChancePercent": 30,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
@ -856,6 +875,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lighthouse": {
|
"lighthouse": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
@ -866,6 +888,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shoreline": {
|
"shoreline": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 25,
|
"20": 25,
|
||||||
@ -876,6 +901,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tarkovstreets": {
|
"tarkovstreets": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 25,
|
"20": 25,
|
||||||
@ -886,6 +914,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"woods": {
|
"woods": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 40,
|
||||||
"reducedChancePercent": 40,
|
"reducedChancePercent": 40,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 25,
|
"20": 25,
|
||||||
@ -896,6 +927,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"default": {
|
"default": {
|
||||||
|
"reduceLootByPercent": true,
|
||||||
|
"minDynamicLootPercent": 50,
|
||||||
|
"minStaticLootPercent": 50,
|
||||||
"reducedChancePercent": 25,
|
"reducedChancePercent": 25,
|
||||||
"reductionPercentWeights": {
|
"reductionPercentWeights": {
|
||||||
"20": 12,
|
"20": 12,
|
||||||
|
@ -61,4 +61,12 @@ export class ApplicationContext
|
|||||||
list.add(new ContextVariable(value, type));
|
list.add(new ContextVariable(value, type));
|
||||||
this.variables.set(type, list);
|
this.variables.set(type, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clearValues(type: ContextVariableType): void
|
||||||
|
{
|
||||||
|
this.variables.has(type)
|
||||||
|
{
|
||||||
|
this.variables.delete(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@ 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,
|
||||||
|
LOOT_MULTIPLER_CHANGE = 4,
|
||||||
}
|
}
|
||||||
|
@ -598,12 +598,22 @@ export class GameController
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the weighted percent to reduce the raid time by
|
// Get the weighted percent to reduce the raid time by
|
||||||
const chosenRaidReductionPercent = this.weightedRandomHelper.getWeightedValue<string>(
|
const chosenRaidReductionPercent = Number.parseInt(this.weightedRandomHelper.getWeightedValue<string>(
|
||||||
mapSettings.reductionPercentWeights,
|
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
|
// How many minutes raid will be
|
||||||
const newRaidTimeMinutes = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, Number.parseInt(chosenRaidReductionPercent)));
|
const newRaidTimeMinutes = Math.floor(this.randomUtil.reduceValueByPercent(baseEscapeTimeMinutes, chosenRaidReductionPercent));
|
||||||
|
|
||||||
// Update result object with new time
|
// Update result object with new time
|
||||||
result.RaidTimeMinutes = newRaidTimeMinutes;
|
result.RaidTimeMinutes = newRaidTimeMinutes;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { inject, injectable } from "tsyringe";
|
import { inject, injectable } from "tsyringe";
|
||||||
|
|
||||||
|
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||||
|
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||||
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
|
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
|
||||||
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
|
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
|
||||||
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||||
@ -12,7 +14,8 @@ import { IGetLocationRequestData } from "@spt-aki/models/eft/location/IGetLocati
|
|||||||
import { AirdropTypeEnum } from "@spt-aki/models/enums/AirdropType";
|
import { AirdropTypeEnum } from "@spt-aki/models/enums/AirdropType";
|
||||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||||
import { IAirdropConfig } from "@spt-aki/models/spt/config/IAirdropConfig";
|
import { IAirdropConfig } from "@spt-aki/models/spt/config/IAirdropConfig";
|
||||||
import { ILocationConfig } from "@spt-aki/models/spt/config/ILocationConfig";
|
import { ILocationConfig, LootMultiplier } from "@spt-aki/models/spt/config/ILocationConfig";
|
||||||
|
import { ILootMultiplerChange } from "@spt-aki/models/spt/location/ILootMultiplerChange";
|
||||||
import { ILocations } from "@spt-aki/models/spt/server/ILocations";
|
import { ILocations } from "@spt-aki/models/spt/server/ILocations";
|
||||||
import { LootRequest } from "@spt-aki/models/spt/services/LootRequest";
|
import { LootRequest } from "@spt-aki/models/spt/services/LootRequest";
|
||||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
@ -42,6 +45,7 @@ export class LocationController
|
|||||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||||
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
@inject("TimeUtil") protected timeUtil: TimeUtil,
|
||||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||||
|
@inject("ApplicationContext") protected applicationContext: ApplicationContext,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP);
|
this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP);
|
||||||
@ -83,10 +87,23 @@ export class LocationController
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
const staticAmmoDist = this.jsonUtil.clone(db.loot.staticAmmo);
|
const staticAmmoDist = this.jsonUtil.clone(db.loot.staticAmmo);
|
||||||
|
|
||||||
// Create containers and add loot to them
|
// Create containers and add loot to them
|
||||||
const staticLoot = this.locationGenerator.generateStaticContainers(location.base, staticAmmoDist);
|
const staticLoot = this.locationGenerator.generateStaticContainers(output, staticAmmoDist);
|
||||||
output.Loot.push(...staticLoot);
|
output.Loot.push(...staticLoot);
|
||||||
|
|
||||||
// Add dyanmic loot to output loot
|
// Add dyanmic loot to output loot
|
||||||
@ -107,9 +124,32 @@ export class LocationController
|
|||||||
);
|
);
|
||||||
this.logger.success(this.localisationService.getText("location-generated_success", name));
|
this.logger.success(this.localisationService.getText("location-generated_success", name));
|
||||||
|
|
||||||
|
// Reset loot multipliers back to original values
|
||||||
|
if (lootMultiplierAdjustment)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
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
|
* Handle client/locations
|
||||||
* Get all maps base location properties without loot data
|
* Get all maps base location properties without loot data
|
||||||
|
@ -44,8 +44,13 @@ export interface ILocationConfig extends IBaseConfig
|
|||||||
|
|
||||||
export interface IScavRaidTimeLocationSettings
|
export interface IScavRaidTimeLocationSettings
|
||||||
{
|
{
|
||||||
reducedChancePercent: number
|
/** Should loot be reduced by same percent length of raid is reduced by */
|
||||||
reductionPercentWeights: Record<string, number>
|
reduceLootByPercent: boolean;
|
||||||
|
minStaticLootPercent: number;
|
||||||
|
minDynamicLootPercent: number;
|
||||||
|
/** Chance raid time is reduced */
|
||||||
|
reducedChancePercent: number;
|
||||||
|
reductionPercentWeights: Record<string, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IContainerRandomistionSettings
|
export interface IContainerRandomistionSettings
|
||||||
|
5
project/src/models/spt/location/ILootMultiplerChange.ts
Normal file
5
project/src/models/spt/location/ILootMultiplerChange.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export interface ILootMultiplerChange
|
||||||
|
{
|
||||||
|
dynamicLootPercent: number
|
||||||
|
staticLootPercent: number
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user