Added tiered flea system with placeholder values - Allow items to be locked to a specific level - defaults to off

Unlocks have a priority order, it will be filtered by whatever is first in the dictionary
e.g.

pistol: unlock level 20
weapon: unlock  level 30

A pistol will be unlocked at level 20,
A shotgun will be unlocked at level 30

if the order was different:
weapon: unlock level 30
pistol: unlock level 20

The pistol would be unlocked at level 30 as its a weapon and gets picked up by the weapon filter first
This commit is contained in:
Dev 2024-09-25 17:16:44 +01:00
parent 4fbed1c191
commit c7a44456bb
3 changed files with 140 additions and 2 deletions

View File

@ -330,5 +330,61 @@
"newPriceHandbookMultiplier": 11
}
}
},
"tieredFlea": {
"enabled": false,
"unlocks": {
"57864a3d24597754843f8721": 35,
"57864bb7245977548b3b66c2": 35,
"57864a66245977548f04a81f": 25,
"57864ada245977548638de91": 20,
"590c745b86f7743cc433c5f2": 35,
"5447bedf4bdc2d87278b4568": 50,
"5447bed64bdc2d97278b4568": 40,
"5447b6254bdc2dc3278b4568": 35,
"5447b6194bdc2d67278b4567": 35,
"5447b5f14bdc2d61278b4567": 35,
"5447b5e04bdc2d62278b4567": 20,
"5447b6094bdc2dc3278b4567": 15,
"5447bee84bdc2dc3278b4569": 15,
"617f1ef5e8b54b0998387733": 10,
"5447b5cf4bdc2d65278b4567": 5,
"55818acf4bdc2dde698b456b": 20,
"55818ad54bdc2ddc698b4569": 23,
"55818add4bdc2d5b648b456f": 25,
"55818ae44bdc2dde698b456c": 30,
"55818aeb4bdc2ddc698b456a": 45,
"543be5cb4bdc2deb348b4568": 50,
"5c164d2286f774194c5e69fa": 40,
"5c99f98d86f7745c314214b3": 35
},
"ammoTiersEnabled": true,
"ammoTplUnlocks": {
"619636be6db0f2477964e710": 50,
"5fc382c1016cce60e8341b20": 50,
"5efb0cabfb3e451d70735af5": 35,
"64b8ee384b75259c590fa89b": 35,
"5d6e6911a4b9361bd5780d52": 35,
"5e85aa1a988a8701445df1f5": 35,
"6576f93989f0062e741ba952": 25,
"56dff061d2720bb5668b4567": 45,
"56dff2ced2720bb4668b4567": 40,
"64b7af434b75259c590fa893": 45,
"60194943740c5d77f6705eea": 35,
"5656d7c34bdc2d9d198b4587": 35,
"5e023e53d4353e3302577c4c": 25,
"5887431f2459777e1612938f": 30,
"59e77a2386f7742ee578960a": 35
}
}
}

View File

@ -15,13 +15,14 @@ import { IItemEventRouterResponse } from "@spt/models/eft/itemEvent/IItemEventRo
import { ISptProfile, ISystemData } from "@spt/models/eft/profile/ISptProfile";
import { IRagfairOffer } from "@spt/models/eft/ragfair/IRagfairOffer";
import { ISearchRequestData, OfferOwnerType } from "@spt/models/eft/ragfair/ISearchRequestData";
import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { MemberCategory } from "@spt/models/enums/MemberCategory";
import { MessageType } from "@spt/models/enums/MessageType";
import { RagfairSort } from "@spt/models/enums/RagfairSort";
import { Traders } from "@spt/models/enums/Traders";
import { IQuestConfig } from "@spt/models/spt/config/IQuestConfig";
import { IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { IRagfairConfig, ITieredFlea } from "@spt/models/spt/config/IRagfairConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { EventOutputHolder } from "@spt/routers/EventOutputHolder";
import { ConfigServer } from "@spt/servers/ConfigServer";
@ -85,12 +86,14 @@ export class RagfairOfferHelper {
pmcData: IPmcData,
): IRagfairOffer[] {
const playerIsFleaBanned = this.profileHelper.playerIsFleaBanned(pmcData);
const tieredFlea = this.ragfairConfig.tieredFlea;
const tieredFleaLimitTypes = Object.keys(tieredFlea.unlocks);
return this.ragfairOfferService.getOffers().filter((offer) => {
if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) {
return false;
}
return this.isDisplayableOffer(
const isDisplayable = this.isDisplayableOffer(
searchRequest,
itemsToAdd,
traderAssorts,
@ -98,9 +101,53 @@ export class RagfairOfferHelper {
pmcData,
playerIsFleaBanned,
);
if (!isDisplayable) {
return false;
}
// Not trader offer + tiered flea enabled
if (tieredFlea.enabled && offer.user.memberType !== MemberCategory.TRADER) {
if (
this.offerIsHiddenFromPlayerTieredFlea(tieredFlea, offer, tieredFleaLimitTypes, pmcData.Info.Level)
) {
return false;
}
}
return true;
});
}
protected offerIsHiddenFromPlayerTieredFlea(
tieredFlea: ITieredFlea,
offer: IRagfairOffer,
tieredFleaLimitTypes: string[],
playerLevel: number,
): boolean {
if (tieredFlea.ammoTplUnlocks && this.itemHelper.isOfBaseclass(offer.items[0]._tpl, BaseClasses.AMMO)) {
const unlockLevel = tieredFlea.ammoTplUnlocks[offer.items[0]._tpl];
if (unlockLevel && playerLevel < unlockLevel) {
return true;
}
}
// Optimisation - Ensure the item has at least one of the limited base types
else if (this.itemHelper.isOfBaseclasses(offer.items[0]._tpl, tieredFleaLimitTypes)) {
// Loop over all flea types to find the matching one
for (const tieredItemType of tieredFleaLimitTypes) {
if (this.itemHelper.isOfBaseclass(offer.items[0]._tpl, tieredItemType)) {
if (playerLevel < tieredFlea.unlocks[tieredItemType]) {
return true;
}
break;
}
}
}
return false;
}
/**
* Get matching offers that require the desired item and filter out offers from non traders if player is below ragfair unlock level
* @param searchRequest Search request from client
@ -110,11 +157,22 @@ export class RagfairOfferHelper {
public getOffersThatRequireItem(searchRequest: ISearchRequestData, pmcData: IPmcData): IRagfairOffer[] {
// Get all offers that requre the desired item and filter out offers from non traders if player below ragifar unlock
const requiredOffers = this.ragfairRequiredItemsService.getRequiredItemsById(searchRequest.neededSearchId);
const tieredFlea = this.ragfairConfig.tieredFlea;
const tieredFleaLimitTypes = Object.keys(tieredFlea.unlocks);
return requiredOffers.filter((offer: IRagfairOffer) => {
if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) {
return false;
}
if (tieredFlea.enabled && offer.user.memberType !== MemberCategory.TRADER) {
if (
this.offerIsHiddenFromPlayerTieredFlea(tieredFlea, offer, tieredFleaLimitTypes, pmcData.Info.Level)
) {
return false;
}
}
return true;
});
}
@ -136,6 +194,9 @@ export class RagfairOfferHelper {
const offersMap = new Map<string, IRagfairOffer[]>();
const offers: IRagfairOffer[] = [];
const playerIsFleaBanned = this.profileHelper.playerIsFleaBanned(pmcData);
const tieredFlea = this.ragfairConfig.tieredFlea;
const tieredFleaLimitTypes = Object.keys(tieredFlea.unlocks);
for (const offer of this.ragfairOfferService.getOffers()) {
if (!this.passesSearchFilterCriteria(searchRequest, offer, pmcData)) {
continue;
@ -160,6 +221,19 @@ export class RagfairOfferHelper {
continue;
}
if (tieredFlea.enabled && offer.user.memberType !== MemberCategory.TRADER) {
if (
this.offerIsHiddenFromPlayerTieredFlea(
tieredFlea,
offer,
tieredFleaLimitTypes,
pmcData.Info.Level,
)
) {
continue;
}
}
const key = offer.items[0]._tpl;
if (!offersMap.has(key)) {
offersMap.set(key, []);

View File

@ -12,6 +12,7 @@ export interface IRagfairConfig extends IBaseConfig {
/** Trader ids + should their assorts be listed on flea */
traders: Record<string, boolean>;
dynamic: Dynamic;
tieredFlea: ITieredFlea;
}
export interface Sell {
@ -170,3 +171,10 @@ export interface IArmorSettings {
/** What slots are to be removed when removeRemovablePlateChance is true */
plateSlotIdToRemovePool: string[];
}
export interface ITieredFlea {
enabled: boolean;
unlocks: Record<string, number>;
ammoTiersEnabled: boolean;
ammoTplUnlocks: Record<string, number>;
}