Improve buyItem() to also support putting fence purchases through addItemToStash()

This commit is contained in:
Dev 2024-01-14 22:30:05 +00:00
parent 2f07d6083f
commit 1d9ff8ace8
2 changed files with 113 additions and 58 deletions

View File

@ -79,7 +79,7 @@ export class InventoryHelper
{
const itemWithModsToAddClone = this.jsonUtil.clone(request.itemWithModsToAdd);
// get stash layouts ready for use
// Get stash layouts ready for use
const stashFS2D = this.getStashSlotMap(pmcData, sessionId);
const sortingTableFS2D = this.getSortingTableSlotMap(pmcData);
@ -122,11 +122,11 @@ export class InventoryHelper
return this.httpResponse.appendErrorToOutput(output, message);
}
// Add item + mods to output + profile inventory
// Add item + mods to output and profile inventory
output.profileChanges[sessionId].items.new.push(...itemWithModsToAddClone);
pmcData.Inventory.items.push(...itemWithModsToAddClone);
this.logger.debug(`Added item ${itemWithModsToAddClone[0]._tpl} with ${itemWithModsToAddClone.length - 1} mods to inventory`);
this.logger.debug(`Added ${itemWithModsToAddClone[0].upd?.StackObjectsCount} item: ${itemWithModsToAddClone[0]._tpl} with: ${itemWithModsToAddClone.length - 1} mods to inventory`);
return output;
}

View File

@ -18,6 +18,7 @@ import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
import { RagfairServer } from "@spt-aki/servers/RagfairServer";
import { FenceService } from "@spt-aki/services/FenceService";
import { LocalisationService } from "@spt-aki/services/LocalisationService";
import { PaymentService } from "@spt-aki/services/PaymentService";
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
@ -36,6 +37,7 @@ export class TradeHelper
@inject("ItemHelper") protected itemHelper: ItemHelper,
@inject("PaymentService") protected paymentService: PaymentService,
@inject("FenceService") protected fenceService: FenceService,
@inject("LocalisationService") protected localisationService: LocalisationService,
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
@inject("InventoryHelper") protected inventoryHelper: InventoryHelper,
@inject("RagfairServer") protected ragfairServer: RagfairServer,
@ -77,20 +79,9 @@ export class TradeHelper
const callback = () =>
{
// Update assort/flea item values
let itemPurchased: Item;
const isRagfair = buyRequestData.tid.toLocaleLowerCase() === "ragfair";
if (isRagfair)
{
const allOffers = this.ragfairServer.getOffers();
// We store ragfair offerid in buyRequestData.item_id
const offerWithItem = allOffers.find((x) => x._id === buyRequestData.item_id);
itemPurchased = offerWithItem.items[0];
}
else
{
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items;
itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id);
}
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items;
const itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id);
// Ensure purchase does not exceed trader item limit
const hasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased);
@ -100,10 +91,7 @@ export class TradeHelper
}
// Decrement trader item count
if (!isRagfair)
{
itemPurchased.upd.StackObjectsCount -= buyRequestData.count;
}
itemPurchased.upd.StackObjectsCount -= buyRequestData.count;
if (this.traderConfig.persistPurchaseDataInProfile && hasBuyRestrictions)
{
@ -117,61 +105,128 @@ export class TradeHelper
throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`);
}
if (buyRequestData.tid === Traders.FENCE)
{
// Bought fence offer, remove from listing
this.fenceService.removeFenceOffer(buyRequestData.item_id);
}
else if (hasBuyRestrictions)
if (hasBuyRestrictions)
{
// Increment non-fence trader item buy count
this.incrementAssortBuyCount(itemPurchased, buyRequestData.count);
}
};
// Handle normal traders old way...for now
if (buyRequestData.tid.toLocaleLowerCase() !== "ragfair" && buyRequestData.tid.toLocaleLowerCase() !== Traders.FENCE)
{
return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, foundInRaid, upd);
}
let offerItems: Item[] = [];
let buyCallback;
if (buyRequestData.tid.toLocaleLowerCase() === "ragfair")
{
buyCallback = () =>
{
const allOffers = this.ragfairServer.getOffers();
// We store ragfair offerid in buyRequestData.item_id
const offerWithItem = allOffers.find((x) => x._id === buyRequestData.item_id);
const itemPurchased = offerWithItem.items[0];
// Ensure purchase does not exceed trader item limit
const hasBuyRestrictions = this.itemHelper.hasBuyRestrictions(itemPurchased);
if (hasBuyRestrictions)
{
this.checkPurchaseIsWithinTraderItemLimit(itemPurchased, buyRequestData.item_id, buyRequestData.count);
}
// Decrement trader item count
if (this.traderConfig.persistPurchaseDataInProfile && hasBuyRestrictions)
{
this.traderHelper.addTraderPurchasesToPlayerProfile(sessionID, newReq);
}
/// Pay for item
output = this.paymentService.payMoney(pmcData, buyRequestData, sessionID, output);
if (output.warnings.length > 0)
{
throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`);
}
if (hasBuyRestrictions)
{
// Increment non-fence trader item buy count
this.incrementAssortBuyCount(itemPurchased, buyRequestData.count);
}
};
// Get raw offer from ragfair, clone to prevent altering offer itself
const allOffers = this.ragfairServer.getOffers();
const offerWithItemCloned = this.jsonUtil.clone(allOffers.find((x) => x._id === buyRequestData.item_id));
const offerItems = offerWithItemCloned.items;
// Get item details from db
const itemDbDetails = this.itemHelper.getItem(offerItems[0]._tpl)[1];
const itemMaxStackSize = itemDbDetails._props.StackMaxSize;
const itemsToSendTotalCount = buyRequestData.count;
let itemsToSendRemaining = itemsToSendTotalCount;
while (itemsToSendRemaining > 0)
offerItems = offerWithItemCloned.items;
}
else if (buyRequestData.tid === Traders.FENCE)
{
buyCallback = () =>
{
// Handle edge case when remaining items to send < max stack size
const itemCountToSend = Math.min(itemMaxStackSize, itemsToSendRemaining);
offerItems[0].upd.StackObjectsCount = itemCountToSend;
// Update assort/flea item values
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(buyRequestData.tid).items;
const itemPurchased = traderAssorts.find((x) => x._id === buyRequestData.item_id);
// Decrement trader item count
itemPurchased.upd.StackObjectsCount -= buyRequestData.count;
/// Pay for item
output = this.paymentService.payMoney(pmcData, buyRequestData, sessionID, output);
if (output.warnings.length > 0)
{
throw new Error(`Transaction failed: ${output.warnings[0].errmsg}`);
}
this.fenceService.removeFenceOffer(buyRequestData.item_id);
};
// Prevent any collisions
this.itemHelper.remapRootItemId(offerItems);
// Construct request
const request: IAddItemDirectRequest = {
itemWithModsToAdd: this.itemHelper.reparentItemAndChildren(offerItems[0], offerItems),
foundInRaid: this.inventoryConfig.newItemsMarkedFound,
callback: callback,
useSortingTable: true
};
this.inventoryHelper.addItemToStash(sessionID, request, pmcData, output);
// Remove amount of items added to player stash
itemsToSendRemaining -= itemCountToSend;
const fenceItems = this.fenceService.getRawFenceAssorts().items;
const rootItemIndex = fenceItems.findIndex((item) => item._id === buyRequestData.item_id);
if (rootItemIndex === -1)
{
this.logger.debug(`Tried to buy item ${buyRequestData.item_id} from fence that no longer exists`);
const message = this.localisationService.getText("ragfair-offer_no_longer_exists");
return this.httpResponse.appendErrorToOutput(output, message);
}
return output;
offerItems = this.itemHelper.findAndReturnChildrenAsItems(fenceItems, buyRequestData.item_id);
}
// TODO - handle traders
// TODO - handle fence
// Get item details from db
const itemDbDetails = this.itemHelper.getItem(offerItems[0]._tpl)[1];
const itemMaxStackSize = itemDbDetails._props.StackMaxSize;
const itemsToSendTotalCount = buyRequestData.count;
let itemsToSendRemaining = itemsToSendTotalCount;
while (itemsToSendRemaining > 0)
{
// Handle edge case when remaining items to send < max stack size
const itemCountToSend = Math.min(itemMaxStackSize, itemsToSendRemaining);
offerItems[0].upd.StackObjectsCount = itemCountToSend;
return this.inventoryHelper.addItem(pmcData, newReq, output, sessionID, callback, foundInRaid, upd);
// Prevent any collisions
this.itemHelper.remapRootItemId(offerItems);
// Construct request
const request: IAddItemDirectRequest = {
itemWithModsToAdd: this.itemHelper.reparentItemAndChildren(offerItems[0], offerItems),
foundInRaid: this.inventoryConfig.newItemsMarkedFound,
callback: buyCallback,
useSortingTable: true
};
// Add item + children to stash
this.inventoryHelper.addItemToStash(sessionID, request, pmcData, output);
// Remove amount of items added to player stash
itemsToSendRemaining -= itemCountToSend;
}
// TODO - handle traders
return output;
}
/**