Refactor functions (!90)
(cherry picked from commit f6fc6e41c0
)
Co-authored-by: Dev <dev@noreply.dev.sp-tarkov.com>
Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/90
This commit is contained in:
parent
2bc582d65c
commit
7974e4531b
@ -26,7 +26,7 @@ export class DialogueController
|
||||
const profiles = this.saveServer.getProfiles();
|
||||
for (const sessionID in profiles)
|
||||
{
|
||||
this.removeExpiredItems(sessionID);
|
||||
this.removeExpiredItemsFromMessages(sessionID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,20 +220,40 @@ export class DialogueController
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete expired items. triggers when updating traders.
|
||||
* @param sessionID Session id
|
||||
* Delete expired items from all messages in player profile. triggers when updating traders.
|
||||
* @param sessionId Session id
|
||||
*/
|
||||
protected removeExpiredItems(sessionID: string): void
|
||||
protected removeExpiredItemsFromMessages(sessionId: string): void
|
||||
{
|
||||
for (const dialogueId in this.saveServer.getProfile(sessionID).dialogues)
|
||||
for (const dialogueId in this.saveServer.getProfile(sessionId).dialogues)
|
||||
{
|
||||
for (const message of this.saveServer.getProfile(sessionID).dialogues[dialogueId].messages)
|
||||
this.removeExpiredItemsFromMessage(sessionId, dialogueId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes expired items from a message in player profile
|
||||
* @param sessionId Session id
|
||||
* @param dialogueId Dialog id
|
||||
*/
|
||||
protected removeExpiredItemsFromMessage(sessionId: string, dialogueId: string): void
|
||||
{
|
||||
for (const message of this.saveServer.getProfile(sessionId).dialogues[dialogueId].messages)
|
||||
{
|
||||
if (this.messageHasExpired(message))
|
||||
{
|
||||
if ((this.timeUtil.getTimestamp()) > (message.dt + message.maxStorageTime))
|
||||
{
|
||||
message.items = {};
|
||||
}
|
||||
message.items = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has a dialog message expired
|
||||
* @param message Message to check expiry of
|
||||
* @returns true or false
|
||||
*/
|
||||
protected messageHasExpired(message: Message): boolean
|
||||
{
|
||||
return (this.timeUtil.getTimestamp()) > (message.dt + message.maxStorageTime);
|
||||
}
|
||||
}
|
@ -327,67 +327,38 @@ export class RagfairController
|
||||
}
|
||||
}
|
||||
|
||||
public addPlayerOffer(pmcData: IPmcData, info: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse
|
||||
/**
|
||||
* List item(s) on flea for sale
|
||||
* @param pmcData Player profile
|
||||
* @param offerRequest Flea list creatio offer
|
||||
* @param sessionID Session id
|
||||
* @returns IItemEventRouterResponse
|
||||
*/
|
||||
public addPlayerOffer(pmcData: IPmcData, offerRequest: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse
|
||||
{
|
||||
let output = this.eventOutputHolder.getOutput(sessionID);
|
||||
let requirementsPriceInRub = 0;
|
||||
const invItems: Item[] = [];
|
||||
|
||||
if (!info?.items || info.items.length === 0)
|
||||
const validationMessage = "";
|
||||
if (!this.isValidPlayerOfferRequest(offerRequest, validationMessage))
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("ragfair-invalid_player_offer_request"));
|
||||
|
||||
return this.httpResponse.appendErrorToOutput(output);
|
||||
return this.httpResponse.appendErrorToOutput(output, validationMessage);
|
||||
}
|
||||
|
||||
if (!info.requirements)
|
||||
// Get an array of items from player inventory to list on flea
|
||||
const getItemsFromInventoryErrorMessage = "";
|
||||
const itemsInInventoryToList = this.getItemsToListOnFleaFromInventory(pmcData, offerRequest.items, getItemsFromInventoryErrorMessage);
|
||||
if (!itemsInInventoryToList)
|
||||
{
|
||||
return this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("ragfair-unable_to_place_offer_with_no_requirements"));
|
||||
}
|
||||
|
||||
for (const item of info.requirements)
|
||||
{
|
||||
const requestedItemTpl = item._tpl;
|
||||
|
||||
if (this.paymentHelper.isMoneyTpl(requestedItemTpl))
|
||||
{
|
||||
requirementsPriceInRub += this.handbookHelper.inRUB(item.count, requestedItemTpl);
|
||||
}
|
||||
else
|
||||
{
|
||||
requirementsPriceInRub += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count;
|
||||
}
|
||||
}
|
||||
|
||||
// Count how many items are being sold and multiply the requested amount accordingly
|
||||
for (const itemId of info.items)
|
||||
{
|
||||
let item = pmcData.Inventory.items.find(i => i._id === itemId);
|
||||
|
||||
if (item === undefined)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", {id: itemId}));
|
||||
|
||||
return this.httpResponse.appendErrorToOutput(output);
|
||||
}
|
||||
|
||||
item = this.itemHelper.fixItemStackCount(item);
|
||||
invItems.push(...this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, itemId));
|
||||
}
|
||||
|
||||
if (!invItems?.length)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory"));
|
||||
|
||||
return this.httpResponse.appendErrorToOutput(output);
|
||||
this.httpResponse.appendErrorToOutput(output, getItemsFromInventoryErrorMessage);
|
||||
}
|
||||
|
||||
// Preparations are done, create the offer
|
||||
const offer = this.createPlayerOffer(this.saveServer.getProfile(sessionID), info.requirements, this.ragfairHelper.mergeStackable(invItems), info.sellInOnePiece, requirementsPriceInRub);
|
||||
const requirementsPriceInRub = this.calculateRequirementsPriceInRub(offerRequest.requirements);
|
||||
const offer = this.createPlayerOffer(this.saveServer.getProfile(sessionID), offerRequest.requirements, this.ragfairHelper.mergeStackable(itemsInInventoryToList), offerRequest.sellInOnePiece, requirementsPriceInRub);
|
||||
const rootItem = offer.items[0];
|
||||
const qualityMultiplier = this.itemHelper.getItemQualityModifier(rootItem);
|
||||
const averageOfferPrice = this.ragfairPriceService.getFleaPriceForItem(rootItem._tpl) * rootItem.upd.StackObjectsCount * qualityMultiplier;
|
||||
const itemStackCount = (!info.sellInOnePiece) ? offer.items[0].upd.StackObjectsCount : 1;
|
||||
const itemStackCount = (!offerRequest.sellInOnePiece) ? offer.items[0].upd.StackObjectsCount : 1;
|
||||
const singleOfferValue = averageOfferPrice / itemStackCount;
|
||||
let sellChance = this.ragfairConfig.sell.chance.base * qualityMultiplier;
|
||||
|
||||
@ -397,7 +368,7 @@ export class RagfairController
|
||||
// Subtract flea market fee from stash
|
||||
if (this.ragfairConfig.sell.fees)
|
||||
{
|
||||
const tax = this.ragfairTaxHelper.calculateTax(rootItem, pmcData, requirementsPriceInRub, itemStackCount, info.sellInOnePiece);
|
||||
const tax = this.ragfairTaxHelper.calculateTax(rootItem, pmcData, requirementsPriceInRub, itemStackCount, offerRequest.sellInOnePiece);
|
||||
|
||||
const request: IProcessBuyTradeRequestData = {
|
||||
tid: "ragfair",
|
||||
@ -428,7 +399,7 @@ export class RagfairController
|
||||
output.profileChanges[sessionID].ragFairOffers.push(offer);
|
||||
|
||||
// Remove items from inventory after creating offer
|
||||
for (const itemToRemove of info.items)
|
||||
for (const itemToRemove of offerRequest.items)
|
||||
{
|
||||
this.inventoryHelper.removeItem(pmcData, itemToRemove, sessionID, output);
|
||||
}
|
||||
@ -436,6 +407,95 @@ export class RagfairController
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the item to be listed on the flea valid
|
||||
* @param offerRequest Client offer request
|
||||
* @param errorMessage message to show to player when offer is invalid
|
||||
* @returns Is offer valid
|
||||
*/
|
||||
protected isValidPlayerOfferRequest(offerRequest: IAddOfferRequestData, errorMessage: string): boolean
|
||||
{
|
||||
if (!offerRequest?.items || offerRequest.items.length === 0)
|
||||
{
|
||||
errorMessage = this.localisationService.getText("ragfair-invalid_player_offer_request");
|
||||
this.logger.error(errorMessage);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!offerRequest.requirements)
|
||||
{
|
||||
errorMessage = this.localisationService.getText("ragfair-unable_to_place_offer_with_no_requirements");
|
||||
this.logger.error(errorMessage);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handbook price in roubles for the items being listed
|
||||
* @param requirements
|
||||
* @returns Rouble price
|
||||
*/
|
||||
protected calculateRequirementsPriceInRub(requirements: Requirement[]): number
|
||||
{
|
||||
let requirementsPriceInRub = 0;
|
||||
for (const item of requirements)
|
||||
{
|
||||
const requestedItemTpl = item._tpl;
|
||||
|
||||
if (this.paymentHelper.isMoneyTpl(requestedItemTpl))
|
||||
{
|
||||
requirementsPriceInRub += this.handbookHelper.inRUB(item.count, requestedItemTpl);
|
||||
}
|
||||
else
|
||||
{
|
||||
requirementsPriceInRub += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl) * item.count;
|
||||
}
|
||||
}
|
||||
|
||||
return requirementsPriceInRub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Using item ids from flea offer request, find corrispnding items from player inventory and return as array
|
||||
* @param pmcData Player profile
|
||||
* @param itemIdsFromFleaOfferRequest Ids from request
|
||||
* @param errorMessage if item is not found, add error message to this parameter
|
||||
* @returns Array of items from player inventory
|
||||
*/
|
||||
protected getItemsToListOnFleaFromInventory(pmcData: IPmcData, itemIdsFromFleaOfferRequest: string[], errorMessage: string): Item[]
|
||||
{
|
||||
const itemsToReturn = [];
|
||||
// Count how many items are being sold and multiply the requested amount accordingly
|
||||
for (const itemId of itemIdsFromFleaOfferRequest)
|
||||
{
|
||||
let item = pmcData.Inventory.items.find(i => i._id === itemId);
|
||||
if (!item)
|
||||
{
|
||||
errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", {id: itemId});
|
||||
this.logger.error(errorMessage);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
item = this.itemHelper.fixItemStackCount(item);
|
||||
itemsToReturn.push(...this.itemHelper.findAndReturnChildrenAsItems(pmcData.Inventory.items, itemId));
|
||||
}
|
||||
|
||||
if (!itemsToReturn?.length)
|
||||
{
|
||||
errorMessage = this.localisationService.getText("ragfair-unable_to_find_requested_items_in_inventory");
|
||||
this.logger.error(errorMessage);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return itemsToReturn;
|
||||
}
|
||||
|
||||
public createPlayerOffer(profile: IAkiProfile, requirements: Requirement[], items: Item[], sellInOnePiece: boolean, amountToSend: number): IRagfairOffer
|
||||
{
|
||||
const loyalLevel = 1;
|
||||
|
@ -13,6 +13,11 @@ import { LocalisationService } from "../services/LocalisationService";
|
||||
import { HashUtil } from "../utils/HashUtil";
|
||||
import { RandomUtil } from "../utils/RandomUtil";
|
||||
|
||||
type ItemLimit = {
|
||||
current: number,
|
||||
max: number
|
||||
};
|
||||
|
||||
@injectable()
|
||||
export class LootGenerator
|
||||
{
|
||||
@ -71,19 +76,18 @@ export class LootGenerator
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct item limit record to hold max and current item count
|
||||
* Construct item limit record to hold max and current item count for each item type
|
||||
* @param limits limits as defined in config
|
||||
* @returns record, key: item tplId, value: current/max item count allowed
|
||||
*/
|
||||
protected initItemLimitCounter(limits: Record<string, number>): Record<string, {current: number, max: number}>
|
||||
protected initItemLimitCounter(limits: Record<string, number>): Record<string, ItemLimit>
|
||||
{
|
||||
const itemTypeCounts: Record<string, {current: number, max: number}> = {};
|
||||
|
||||
for (const x in limits)
|
||||
const itemTypeCounts: Record<string, ItemLimit> = {};
|
||||
for (const itemTypeId in limits)
|
||||
{
|
||||
itemTypeCounts[x] = {
|
||||
itemTypeCounts[itemTypeId] = {
|
||||
current: 0,
|
||||
max: limits[x]
|
||||
max: limits[itemTypeId]
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ export class RagfairServerHelper
|
||||
}
|
||||
|
||||
// generated offer
|
||||
// recurse if name is longer than max characters allowed (15 characters)
|
||||
// recurivse if name is longer than max characters allowed (15 characters)
|
||||
const type = (this.randomUtil.getInt(0, 1) === 0) ? "usec" : "bear";
|
||||
const name = this.randomUtil.getStringArrayValue(this.databaseServer.getTables().bots.types[type].firstName);
|
||||
return (name.length > 15) ? this.getNickname(userID) : name;
|
||||
|
@ -126,17 +126,26 @@ export class TraderHelper
|
||||
const traderInfo = pmcData.TradersInfo[traderId];
|
||||
|
||||
// Add standing to trader
|
||||
traderInfo.standing += standingToAdd;
|
||||
|
||||
// dont allow standing to fall below 0
|
||||
if (traderInfo.standing < 0)
|
||||
{
|
||||
traderInfo.standing = 0;
|
||||
}
|
||||
traderInfo.standing = this.addStandingValuesTogether(traderInfo.standing, standingToAdd);
|
||||
|
||||
this.lvlUp(traderId, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add standing to current standing and clamp value if it goes too low
|
||||
* @param currentStanding current trader standing
|
||||
* @param standingToAdd stansding to add to trader standing
|
||||
* @returns current standing + added standing (clamped if needed)
|
||||
*/
|
||||
protected addStandingValuesTogether(currentStanding: number, standingToAdd: number): number
|
||||
{
|
||||
const newStanding = currentStanding + standingToAdd;
|
||||
|
||||
return newStanding < 0
|
||||
? 0
|
||||
: newStanding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate traders level based on exp amount and increments level if over threshold
|
||||
* @param traderID trader to process
|
||||
|
Loading…
Reference in New Issue
Block a user