Handle changes to airdrop endpoint
Reworked airdrop loot generation to incorporate 'radar' drops Added `forced loot` system to LootGenerator service, can now explicitly define what items it contains Fixed airdrop system sending incorrect icon to client
This commit is contained in:
parent
3bbe167450
commit
80762d6a00
@ -3,10 +3,12 @@
|
||||
"mixed": 5,
|
||||
"weaponArmor": 2,
|
||||
"foodMedical": 1,
|
||||
"barter": 1
|
||||
"barter": 1,
|
||||
"radar": 0
|
||||
},
|
||||
"loot": {
|
||||
"mixed": {
|
||||
"icon": "Common",
|
||||
"weaponPresetCount": {
|
||||
"min": 3,
|
||||
"max": 5
|
||||
@ -108,6 +110,7 @@
|
||||
"allowBossItems": false
|
||||
},
|
||||
"weaponArmor": {
|
||||
"icon": "Weapon",
|
||||
"weaponPresetCount": {
|
||||
"min": 6,
|
||||
"max": 8
|
||||
@ -180,6 +183,7 @@
|
||||
"allowBossItems": false
|
||||
},
|
||||
"foodMedical": {
|
||||
"icon": "Medical",
|
||||
"weaponPresetCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
@ -260,6 +264,7 @@
|
||||
"allowBossItems": false
|
||||
},
|
||||
"barter": {
|
||||
"icon": "Supply",
|
||||
"weaponPresetCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
@ -339,6 +344,39 @@
|
||||
},
|
||||
"armorLevelWhitelist": [0],
|
||||
"allowBossItems": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"radar": {
|
||||
"icon": "Supply",
|
||||
"weaponPresetCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"armorPresetCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"itemCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"weaponCrateCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"itemBlacklist": [],
|
||||
"itemTypeWhitelist": [],
|
||||
"itemLimits": {},
|
||||
"itemStackLimits": {},
|
||||
"armorLevelWhitelist": [],
|
||||
"allowBossItems": false,
|
||||
"useForcedLoot": true,
|
||||
"forcedLoot": {
|
||||
"66d9f7256916142b3b02276e": {"min": 2, "max": 4 }
|
||||
}
|
||||
}
|
||||
},
|
||||
"customAirdropMapping": {
|
||||
"66da1b49099cf6adcc07a36b": "radar",
|
||||
"66da1b546916142b3b022777": "radar"
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { LocationController } from "@spt/controllers/LocationController";
|
||||
import { IEmptyRequestData } from "@spt/models/eft/common/IEmptyRequestData";
|
||||
import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocationsSourceDestinationBase";
|
||||
import { IGetBodyResponseData } from "@spt/models/eft/httpResponse/IGetBodyResponseData";
|
||||
import { IGetAirdropLootRequest } from "@spt/models/eft/location/IGetAirdropLootRequest";
|
||||
import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse";
|
||||
import { HttpResponseUtil } from "@spt/utils/HttpResponseUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
@ -25,9 +26,9 @@ export class LocationCallbacks {
|
||||
/** Handle client/airdrop/loot */
|
||||
public getAirdropLoot(
|
||||
url: string,
|
||||
info: IEmptyRequestData,
|
||||
info: IGetAirdropLootRequest,
|
||||
sessionID: string,
|
||||
): IGetBodyResponseData<IGetAirdropLootResponse> {
|
||||
return this.httpResponse.getBody(this.locationController.getAirdropLoot());
|
||||
return this.httpResponse.getBody(this.locationController.getAirdropLoot(info));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { ILocationsGenerateAllResponse } from "@spt/models/eft/common/ILocationsSourceDestinationBase";
|
||||
import { IGetAirdropLootRequest } from "@spt/models/eft/location/IGetAirdropLootRequest";
|
||||
import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig";
|
||||
@ -50,7 +51,11 @@ export class LocationController {
|
||||
}
|
||||
|
||||
/** Handle client/airdrop/loot */
|
||||
public getAirdropLoot(): IGetAirdropLootResponse {
|
||||
public getAirdropLoot(request: IGetAirdropLootRequest): IGetAirdropLootResponse {
|
||||
if (request.containerId) {
|
||||
return this.airdropService.generateCustomAirdropLoot(request);
|
||||
}
|
||||
|
||||
return this.airdropService.generateAirdropLoot();
|
||||
}
|
||||
}
|
||||
|
@ -153,6 +153,32 @@ export class LootGenerator {
|
||||
return result;
|
||||
}
|
||||
|
||||
public createForcedLoot(airdropConfig: LootRequest) {
|
||||
const result: IItem[] = [];
|
||||
|
||||
const forcedItems = Object.keys(airdropConfig.forcedLoot);
|
||||
|
||||
for (const tpl of forcedItems) {
|
||||
const details = airdropConfig.forcedLoot[tpl];
|
||||
const randomisedItemCount = this.randomUtil.getInt(details.min, details.max);
|
||||
|
||||
// Add forced loot item to result
|
||||
const newLootItem: IItem = {
|
||||
_id: this.hashUtil.generate(),
|
||||
_tpl: tpl,
|
||||
upd: {
|
||||
StackObjectsCount: randomisedItemCount,
|
||||
SpawnedInSession: true,
|
||||
},
|
||||
};
|
||||
|
||||
const splitResults = this.itemHelper.splitStack(newLootItem);
|
||||
result.push(...splitResults);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected getItemRewardPool(
|
||||
itemTplBlacklist: string[],
|
||||
itemTypeWhitelist: string[],
|
||||
|
@ -3,4 +3,5 @@ export enum AirdropTypeEnum {
|
||||
SUPPLY = "barter",
|
||||
FOOD_MEDICAL = "foodMedical",
|
||||
WEAPON_ARMOR = "weaponArmor",
|
||||
RADAR = "radar",
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export interface IAirdropConfig extends IBaseConfig {
|
||||
airdropTypeWeightings: Record<AirdropTypeEnum, number>;
|
||||
/** What rewards will the loot crate contain, keyed by drop type e.g. mixed/weaponArmor/foodMedical/barter */
|
||||
loot: Record<string, IAirdropLoot>;
|
||||
customAirdropMapping: Record<string, AirdropTypeEnum>;
|
||||
}
|
||||
|
||||
/** Chance map will have an airdrop occur out of 100 - locations not included count as 0% */
|
||||
@ -23,6 +24,7 @@ export interface IAirdropChancePercent {
|
||||
|
||||
/** Loot inside crate */
|
||||
export interface IAirdropLoot {
|
||||
icon: AirdropTypeEnum;
|
||||
/** Min/max of weapons inside crate */
|
||||
weaponPresetCount?: MinMax;
|
||||
/** Min/max of armors (head/chest/rig) inside crate */
|
||||
@ -43,4 +45,6 @@ export interface IAirdropLoot {
|
||||
armorLevelWhitelist?: number[];
|
||||
/** Should boss items be added to airdrop crate */
|
||||
allowBossItems: boolean;
|
||||
useForcedLoot?: boolean;
|
||||
forcedLoot?: Record<string, MinMax>;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { MinMax } from "@spt/models/common/MinMax";
|
||||
import { AirdropTypeEnum } from "@spt/models/enums/AirdropType";
|
||||
|
||||
export interface LootRequest {
|
||||
weaponPresetCount: MinMax;
|
||||
@ -13,4 +14,10 @@ export interface LootRequest {
|
||||
armorLevelWhitelist: number[];
|
||||
allowBossItems: boolean;
|
||||
useRewarditemBlacklist?: boolean;
|
||||
useForcedLoot?: boolean;
|
||||
forcedLoot?: Record<string, MinMax>;
|
||||
}
|
||||
|
||||
export interface IAirdropLootRequest extends LootRequest {
|
||||
icon?: AirdropTypeEnum;
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ import { LootGenerator } from "@spt/generators/LootGenerator";
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { WeightedRandomHelper } from "@spt/helpers/WeightedRandomHelper";
|
||||
import { IItem } from "@spt/models/eft/common/tables/IItem";
|
||||
import { IGetAirdropLootRequest } from "@spt/models/eft/location/IGetAirdropLootRequest";
|
||||
import { IGetAirdropLootResponse } from "@spt/models/eft/location/IGetAirdropLootResponse";
|
||||
import { AirdropTypeEnum } from "@spt/models/enums/AirdropType";
|
||||
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
|
||||
import { ItemTpl } from "@spt/models/enums/ItemTpl";
|
||||
import { IAirdropConfig, IAirdropLoot } from "@spt/models/spt/config/IAirdropConfig";
|
||||
import { LootRequest } from "@spt/models/spt/services/LootRequest";
|
||||
import { IAirdropLootRequest, LootRequest } from "@spt/models/spt/services/LootRequest";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
@ -36,21 +37,36 @@ export class AirdropService {
|
||||
this.airdropConfig = this.configServer.getConfig(ConfigTypes.AIRDROP);
|
||||
}
|
||||
|
||||
public generateCustomAirdropLoot(request: IGetAirdropLootRequest): IGetAirdropLootResponse {
|
||||
const customAirdropInformation = this.airdropConfig.customAirdropMapping[request.containerId];
|
||||
if (!customAirdropInformation) {
|
||||
this.logger.warning(
|
||||
`Unable to find data for custom airdrop ${request.containerId}, returning random airdrop instead`,
|
||||
);
|
||||
|
||||
return this.generateAirdropLoot();
|
||||
}
|
||||
|
||||
return this.generateAirdropLoot(customAirdropInformation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle client/location/getAirdropLoot
|
||||
* Get loot for an airdrop container
|
||||
* Generates it randomly based on config/airdrop.json values
|
||||
* @returns Array of LootItem objects
|
||||
*/
|
||||
public generateAirdropLoot(): IGetAirdropLootResponse {
|
||||
const airdropType = this.chooseAirdropType();
|
||||
public generateAirdropLoot(forcedAirdropType = null): IGetAirdropLootResponse {
|
||||
const airdropType = forcedAirdropType ? forcedAirdropType : this.chooseAirdropType();
|
||||
this.logger.debug(`Chose ${airdropType} for airdrop loot`);
|
||||
|
||||
// Common/weapon/etc
|
||||
const airdropConfig = this.getAirdropLootConfigByType(airdropType);
|
||||
|
||||
// generate loot to put into airdrop crate
|
||||
const crateLoot = this.lootGenerator.createRandomLoot(airdropConfig);
|
||||
const crateLoot = airdropConfig.useForcedLoot
|
||||
? this.lootGenerator.createForcedLoot(airdropConfig)
|
||||
: this.lootGenerator.createRandomLoot(airdropConfig);
|
||||
|
||||
// Create airdrop crate and add to result in first spot
|
||||
const airdropCrateItem = this.getAirdropCrateItem(airdropType);
|
||||
@ -58,7 +74,7 @@ export class AirdropService {
|
||||
// Add crate to front of array
|
||||
crateLoot.unshift(airdropCrateItem);
|
||||
|
||||
// Reparent loot items to create we added above
|
||||
// Reparent loot items to crate we added above
|
||||
for (const item of crateLoot) {
|
||||
if (item._id === airdropCrateItem._id) {
|
||||
// Crate itself, don't alter
|
||||
@ -72,7 +88,7 @@ export class AirdropService {
|
||||
}
|
||||
}
|
||||
|
||||
return { icon: airdropType, container: crateLoot };
|
||||
return { icon: airdropConfig.icon, container: crateLoot };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,6 +119,9 @@ export class AirdropService {
|
||||
case AirdropTypeEnum.COMMON:
|
||||
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_COMMON_SUPPLY_CRATE;
|
||||
break;
|
||||
case AirdropTypeEnum.RADAR:
|
||||
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_TECHNICAL_SUPPLY_CRATE_EVENT_1;
|
||||
break;
|
||||
default:
|
||||
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_COMMON_SUPPLY_CRATE;
|
||||
break;
|
||||
@ -126,7 +145,7 @@ export class AirdropService {
|
||||
* @param airdropType Type of airdrop to get settings for
|
||||
* @returns LootRequest
|
||||
*/
|
||||
protected getAirdropLootConfigByType(airdropType: AirdropTypeEnum): LootRequest {
|
||||
protected getAirdropLootConfigByType(airdropType: AirdropTypeEnum): IAirdropLootRequest {
|
||||
let lootSettingsByType: IAirdropLoot = this.airdropConfig.loot[airdropType];
|
||||
if (!lootSettingsByType) {
|
||||
this.logger.error(
|
||||
@ -136,6 +155,7 @@ export class AirdropService {
|
||||
}
|
||||
|
||||
return {
|
||||
icon: lootSettingsByType.icon,
|
||||
weaponPresetCount: lootSettingsByType.weaponPresetCount,
|
||||
armorPresetCount: lootSettingsByType.armorPresetCount,
|
||||
itemCount: lootSettingsByType.itemCount,
|
||||
@ -150,6 +170,8 @@ export class AirdropService {
|
||||
itemStackLimits: lootSettingsByType.itemStackLimits,
|
||||
armorLevelWhitelist: lootSettingsByType.armorLevelWhitelist,
|
||||
allowBossItems: lootSettingsByType.allowBossItems,
|
||||
useForcedLoot: lootSettingsByType.useForcedLoot,
|
||||
forcedLoot: lootSettingsByType.forcedLoot,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user