From 4434b95621369112f38eb21de884b0c3dedf2bc2 Mon Sep 17 00:00:00 2001 From: chomp Date: Wed, 15 Mar 2023 19:06:03 +0000 Subject: [PATCH] Feature: reworked calculation of flea price to use the price an item can be sold to a trader for instead of the price a trader sells an item at (!71) Disable automatic adjustment of items that are below handbook price Co-authored-by: Dev Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/71 --- project/assets/configs/ragfair.json | 2 +- project/src/helpers/TraderHelper.ts | 67 ++++++++++++++++++++- project/src/services/RagfairPriceService.ts | 4 +- 3 files changed, 68 insertions(+), 5 deletions(-) diff --git a/project/assets/configs/ragfair.json b/project/assets/configs/ragfair.json index ad5d9201..32ffa038 100644 --- a/project/assets/configs/ragfair.json +++ b/project/assets/configs/ragfair.json @@ -48,7 +48,7 @@ ] }, "offerAdjustment":{ - "adjustPriceWhenBelowHandbookPrice": true, + "adjustPriceWhenBelowHandbookPrice": false, "maxPriceDifferenceBelowHandbookPercent": 64, "handbookPriceMultipier": 1.1, "priceThreshholdRub": 20000 diff --git a/project/src/helpers/TraderHelper.ts b/project/src/helpers/TraderHelper.ts index 160f6bce..d8b5a0f3 100644 --- a/project/src/helpers/TraderHelper.ts +++ b/project/src/helpers/TraderHelper.ts @@ -14,16 +14,20 @@ import { SaveServer } from "../servers/SaveServer"; import { FenceService } from "../services/FenceService"; import { LocalisationService } from "../services/LocalisationService"; import { PlayerService } from "../services/PlayerService"; +import { RandomUtil } from "../utils/RandomUtil"; import { TimeUtil } from "../utils/TimeUtil"; import { HandbookHelper } from "./HandbookHelper"; +import { ItemHelper } from "./ItemHelper"; import { ProfileHelper } from "./ProfileHelper"; @injectable() export class TraderHelper { protected traderConfig: ITraderConfig; - /** Dictionary of item tpl and the highest trader rouble price */ + /** Dictionary of item tpl and the highest trader sell rouble price */ protected highestTraderPriceItems: Record = null; + /** Dictionary of item tpl and the highest trader buy back rouble price */ + protected highestTraderBuyPriceItems: Record = null; constructor( @inject("WinstonLogger") protected logger: ILogger, @@ -31,10 +35,12 @@ export class TraderHelper @inject("SaveServer") protected saveServer: SaveServer, @inject("ProfileHelper") protected profileHelper: ProfileHelper, @inject("HandbookHelper") protected handbookHelper: HandbookHelper, + @inject("ItemHelper") protected itemHelper: ItemHelper, @inject("PlayerService") protected playerService: PlayerService, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("FenceService") protected fenceService: FenceService, @inject("TimeUtil") protected timeUtil: TimeUtil, + @inject("RandomUtil") protected randomUtil: RandomUtil, @inject("ConfigServer") protected configServer: ConfigServer ) { @@ -266,6 +272,7 @@ export class TraderHelper /** * Get the highest rouble price for an item from traders + * UNUSED * @param tpl Item to look up highest pride for * @returns highest rouble cost for item */ @@ -276,8 +283,12 @@ export class TraderHelper return this.highestTraderPriceItems[tpl]; } + if (!this.highestTraderPriceItems) + { + this.highestTraderPriceItems = {}; + } + // Init dict and fill - this.highestTraderPriceItems = {}; for (const traderName in Traders) { // Skip some traders @@ -314,4 +325,56 @@ export class TraderHelper return this.highestTraderPriceItems[tpl]; } + + /** + * Get the highest price item can be sold to trader for (roubles) + * @param tpl Item to look up best trader sell-to price + * @returns Rouble price + */ + public getHighestSellToTraderPrice(tpl: string): number + { + // Init dict if doesn't exist + if (!this.highestTraderBuyPriceItems) + { + this.highestTraderBuyPriceItems = {}; + } + + // Return result if it exists + if (this.highestTraderBuyPriceItems[tpl]) + { + return this.highestTraderBuyPriceItems[tpl]; + } + + + // Find highest trader price for item + for (const traderName in Traders) + { + // Get trader and check buy category allows tpl + const traderBase = this.databaseServer.getTables().traders[Traders[traderName]]?.base; + if (traderBase && this.itemHelper.isOfBaseclasses(tpl, traderBase.items_buy.category)) + { + // Get loyalty level details player has achieved with this trader + // Uses lowest loyalty level as this function is used before a player has logged into server - we have no idea what player loyalty is with traders + const relevantLoyaltyData = traderBase.loyaltyLevels[0]; + const traderBuyBackPricePercent = relevantLoyaltyData.buy_price_coef; + + const itemHandbookPrice = this.handbookHelper.getTemplatePrice(tpl); + const priceTraderBuysItemAt = Math.round(this.randomUtil.getPercentOfValue(traderBuyBackPricePercent, itemHandbookPrice)); + + // Set new item to 1 rouble as default + if (!this.highestTraderBuyPriceItems[tpl]) + { + this.highestTraderBuyPriceItems[tpl] = 1; + } + + // Existing price smaller in dict than current iteration, overwrite + if (this.highestTraderBuyPriceItems[tpl] < priceTraderBuysItemAt) + { + this.highestTraderBuyPriceItems[tpl] = priceTraderBuysItemAt; + } + } + } + + return this.highestTraderBuyPriceItems[tpl]; + } } \ No newline at end of file diff --git a/project/src/services/RagfairPriceService.ts b/project/src/services/RagfairPriceService.ts index 50dd7eec..667f970e 100644 --- a/project/src/services/RagfairPriceService.ts +++ b/project/src/services/RagfairPriceService.ts @@ -212,7 +212,7 @@ export class RagfairPriceService implements OnLoad if (this.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher) { // Get highest trader price for item, if greater than value found so far, use it - const traderPrice = this.traderHelper.getHighestTraderPriceRouble(item._tpl); + const traderPrice = this.traderHelper.getHighestSellToTraderPrice(item._tpl); if (traderPrice > itemPrice) { itemPrice = traderPrice; @@ -368,7 +368,7 @@ export class RagfairPriceService implements OnLoad protected getHighestHandbookOrTraderPriceAsRouble(itemTpl: string): number { let price = this.getStaticPriceForItem(itemTpl); - const traderPrice = this.traderHelper.getHighestTraderPriceRouble(itemTpl); + const traderPrice = this.traderHelper.getHighestSellToTraderPrice(itemTpl); if (traderPrice > price) { price = traderPrice;