Merge branch '310-dev' of https://dev.sp-tarkov.com/SPT/Server into 310-dev

This commit is contained in:
Dev 2024-07-06 09:21:14 +01:00
commit 61da90f33d
6 changed files with 87 additions and 35 deletions

View File

@ -36,7 +36,7 @@ export class LocationCallbacks
return this.httpResponse.getBody(this.locationController.get(sessionID, info));
}
/** Handle client/location/getAirdropLoot */
/** Handle client/airdrop/loot */
public getAirdropLoot(url: string, info: IEmptyRequestData, sessionID: string): any
{
return this.httpResponse.getBody(this.locationController.getAirdropLoot());

View File

@ -11,7 +11,7 @@ import { IAirdropLootResult } from "@spt/models/eft/location/IAirdropLootResult"
import { IGetLocationRequestData } from "@spt/models/eft/location/IGetLocationRequestData";
import { AirdropTypeEnum } from "@spt/models/enums/AirdropType";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { IAirdropConfig } from "@spt/models/spt/config/IAirdropConfig";
import { AirdropLoot, IAirdropConfig } from "@spt/models/spt/config/IAirdropConfig";
import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig";
import { IRaidChanges } from "@spt/models/spt/location/IRaidChanges";
import { ILocations } from "@spt/models/spt/server/ILocations";
@ -171,15 +171,14 @@ export class LocationController
* Generates it randomly based on config/airdrop.json values
* @returns Array of LootItem objects
*/
public getAirdropLoot(): IAirdropLootResult
public getAirdropLoot(): any // TODO: need to fix
{
const airdropType = this.chooseAirdropType();
this.logger.debug(`Chose ${airdropType} for airdrop loot`);
const airdropConfig = this.getAirdropLootConfigByType(airdropType);
return { dropType: airdropType, loot: this.lootGenerator.createRandomLoot(airdropConfig) };
return { icon: airdropType, container: this.lootGenerator.createRandomLoot(airdropConfig) };
}
/**
@ -200,16 +199,17 @@ export class LocationController
*/
protected getAirdropLootConfigByType(airdropType: AirdropTypeEnum): LootRequest
{
let lootSettingsByType = this.airdropConfig.loot[airdropType];
let lootSettingsByType: AirdropLoot = this.airdropConfig.loot[airdropType];
if (!lootSettingsByType)
{
this.logger.error(
this.localisationService.getText("location-unable_to_find_airdrop_drop_config_of_type", airdropType),
);
lootSettingsByType = this.airdropConfig.loot[AirdropTypeEnum.MIXED];
lootSettingsByType = this.airdropConfig.loot[AirdropTypeEnum.COMMON];
}
return {
airdropLoot: airdropType,
weaponPresetCount: lootSettingsByType.weaponPresetCount,
armorPresetCount: lootSettingsByType.armorPresetCount,
itemCount: lootSettingsByType.itemCount,

View File

@ -228,13 +228,8 @@ export class MatchController
const parentId = this.hashUtil.generate();
for (const item of loot)
{
mailableLoot.push({
_id: item.id,
_tpl: item.tpl,
slotId: "main",
parentId: parentId,
upd: { StackObjectsCount: item.stackCount, SpawnedInSession: true },
});
item.parentId = parentId;
mailableLoot.push(item);
}
// Send message from fence giving player reward generated above

View File

@ -17,6 +17,8 @@ import { LocalisationService } from "@spt/services/LocalisationService";
import { RagfairLinkedItemService } from "@spt/services/RagfairLinkedItemService";
import { HashUtil } from "@spt/utils/HashUtil";
import { RandomUtil } from "@spt/utils/RandomUtil";
import { AirdropTypeEnum } from "@spt/models/enums/AirdropType";
import { ItemTpl } from "@spt/models/enums/ItemTpl";
type ItemLimit = { current: number, max: number };
@ -43,9 +45,41 @@ export class LootGenerator
* @param options parameters to adjust how loot is generated
* @returns An array of loot items
*/
public createRandomLoot(options: LootRequest): LootItem[]
public createRandomLoot(options: LootRequest): Item[]
{
const result: LootItem[] = [];
const result: Item[] = [];
let airdropContainerParentID = "";
if (options.airdropLoot)
{
airdropContainerParentID = this.hashUtil.generate();
let airdropContainer = {
_id: airdropContainerParentID,
_tpl: "",
upd: {
SpawnedInSession: true,
StackObjectsCount: 1
}
}
switch (options.airdropLoot) {
case AirdropTypeEnum.MEDICAL:
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_MEDICAL_CRATE
break;
case AirdropTypeEnum.SUPPLY:
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_SUPPLY_CRATE
break;
case AirdropTypeEnum.WEAPON:
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_WEAPON_CRATE
break;
case AirdropTypeEnum.COMMON:
default:
airdropContainer._tpl = ItemTpl.LOOTCONTAINER_AIRDROP_COMMON_SUPPLY_CRATE
break;
}
result.push(airdropContainer);
}
const itemTypeCounts = this.initItemLimitCounter(options.itemLimits);
@ -86,10 +120,12 @@ export class LootGenerator
// Choose one at random + add to results array
const chosenSealedContainer = this.randomUtil.getArrayValue(sealedWeaponContainerPool);
result.push({
id: this.hashUtil.generate(),
tpl: chosenSealedContainer._id,
isPreset: false,
stackCount: 1,
_id: this.hashUtil.generate(),
_tpl: chosenSealedContainer._id,
upd: {
StackObjectsCount: 1,
SpawnedInSession: true
}
});
}
}
@ -185,6 +221,19 @@ export class LootGenerator
}
}
for (const item of result) {
if (item._id == airdropContainerParentID)
{
continue;
}
if (!item.parentId)
{
item.parentId = airdropContainerParentID;
item.slotId = "main"
}
}
return result;
}
@ -242,7 +291,7 @@ export class LootGenerator
items: [string, ITemplateItem][],
itemTypeCounts: Record<string, { current: number, max: number }>,
options: LootRequest,
result: LootItem[],
result: Item[],
): boolean
{
const randomItem = this.randomUtil.getArrayValue(items)[1];
@ -259,20 +308,22 @@ export class LootGenerator
return false;
}
const newLootItem: LootItem = {
id: this.hashUtil.generate(),
tpl: randomItem._id,
isPreset: false,
stackCount: 1,
const newLootItem: Item = {
_id: this.hashUtil.generate(),
_tpl: randomItem._id,
upd: {
StackObjectsCount: 1,
SpawnedInSession: true
}
};
// Special case - handle items that need a stackcount > 1
if (randomItem._props.StackMaxSize > 1)
{
newLootItem.stackCount = this.getRandomisedStackCount(randomItem, options);
newLootItem.upd.StackObjectsCount = this.getRandomisedStackCount(randomItem, options);
}
newLootItem.tpl = randomItem._id;
newLootItem._tpl = randomItem._id;
result.push(newLootItem);
if (itemLimitCount)
@ -317,7 +368,7 @@ export class LootGenerator
presetPool: IPreset[],
itemTypeCounts: Record<string, { current: number, max: number }>,
itemBlacklist: string[],
result: LootItem[],
result: Item[],
): boolean
{
// Choose random preset and get details from item db using encyclopedia value (encyclopedia === tplId)
@ -367,8 +418,12 @@ export class LootGenerator
return false;
}
const presetAndMods: Item[] = this.itemHelper.replaceIDs(chosenPreset._items);
this.itemHelper.remapRootItemId(presetAndMods);
// Add chosen preset tpl to result array
result.push({ tpl: chosenPreset._items[0]._tpl, isPreset: true, stackCount: 1 });
presetAndMods.forEach(item => {
result.push(item)
});
if (itemLimitCount)
{

View File

@ -1,7 +1,7 @@
export enum AirdropTypeEnum
{
MIXED = "mixed",
WEAPONARMOR = "weaponarmor",
FOODMEDICAL = "foodmedical",
BARTER = "barter",
COMMON = "common",
SUPPLY = "supply",
MEDICAL = "medical",
WEAPON = "weapon"
}

View File

@ -1,7 +1,9 @@
import { MinMax } from "@spt/models/common/MinMax";
import { AirdropTypeEnum } from "@spt/models/enums/AirdropType";
export interface LootRequest
{
airdropLoot?: AirdropTypeEnum
weaponPresetCount: MinMax
armorPresetCount: MinMax
itemCount: MinMax