Merge branch '3.8.0' of https://dev.sp-tarkov.com/SPT-AKI/Server into 3.8.0
This commit is contained in:
commit
2839ce8c77
@ -592,24 +592,32 @@ export class HideoutController
|
|||||||
const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId);
|
const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId);
|
||||||
|
|
||||||
// Find the actual amount of items we need to remove because body can send weird data
|
// Find the actual amount of items we need to remove because body can send weird data
|
||||||
const recipeRequirementsClone = this.jsonUtil.clone(recipe.requirements.filter((i) => i.type === "Item"));
|
const recipeRequirementsClone = this.jsonUtil.clone(recipe.requirements.filter((i) => i.type === "Item" || i.type === "Tool"));
|
||||||
|
|
||||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||||
|
const itemsToDelete = body.items.concat(body.tools);
|
||||||
for (const itemToDelete of body.items)
|
for (const itemToDelete of itemsToDelete)
|
||||||
{
|
{
|
||||||
const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id);
|
const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id);
|
||||||
const requirement = recipeRequirementsClone.find((requirement) =>
|
const requirement = recipeRequirementsClone.find((requirement) =>
|
||||||
requirement.templateId === itemToCheck._tpl
|
requirement.templateId === itemToCheck._tpl
|
||||||
);
|
);
|
||||||
if (requirement.count <= 0)
|
|
||||||
|
// Handle tools not having a `count`, but always only requiring 1
|
||||||
|
const requiredCount = requirement.count ?? 1;
|
||||||
|
if (requiredCount <= 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inventoryHelper.removeItemByCount(pmcData, itemToDelete.id, requirement.count, sessionID, output);
|
this.inventoryHelper.removeItemByCount(pmcData, itemToDelete.id, requiredCount, sessionID, output);
|
||||||
|
|
||||||
|
// Tools don't have a count
|
||||||
|
if (requirement.type !== "Tool")
|
||||||
|
{
|
||||||
requirement.count -= itemToDelete.count;
|
requirement.count -= itemToDelete.count;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -793,6 +801,46 @@ export class HideoutController
|
|||||||
output: IItemEventRouterResponse,
|
output: IItemEventRouterResponse,
|
||||||
): void
|
): void
|
||||||
{
|
{
|
||||||
|
// Validate that we have a matching production
|
||||||
|
const productionDict = Object.entries(pmcData.Hideout.Production);
|
||||||
|
let prodId: string;
|
||||||
|
for (const [productionId, production] of productionDict)
|
||||||
|
{
|
||||||
|
// Skip null production objects
|
||||||
|
if (!production)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hideoutHelper.isProductionType(production))
|
||||||
|
{
|
||||||
|
// Production or ScavCase
|
||||||
|
if (production.RecipeId === request.recipeId)
|
||||||
|
{
|
||||||
|
prodId = productionId; // Set to objects key
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're unable to find the production, send an error to the client
|
||||||
|
if (prodId === undefined)
|
||||||
|
{
|
||||||
|
this.logger.error(
|
||||||
|
this.localisationService.getText(
|
||||||
|
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
||||||
|
request.recipeId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.httpResponse.appendErrorToOutput(output, this.localisationService.getText(
|
||||||
|
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
||||||
|
request.recipeId,
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Variables for managemnet of skill
|
// Variables for managemnet of skill
|
||||||
let craftingExpAmount = 0;
|
let craftingExpAmount = 0;
|
||||||
|
|
||||||
@ -865,40 +913,27 @@ export class HideoutController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loops over all current productions on profile - we want to find a matching production
|
// Build an array of the tools that need to be returned to the player
|
||||||
const productionDict = Object.entries(pmcData.Hideout.Production);
|
const toolsToSendToPlayer: Item[][] = [];
|
||||||
let prodId: string;
|
const production = pmcData.Hideout.Production[prodId];
|
||||||
for (const production of productionDict)
|
if (production.sptRequiredTools?.length > 0)
|
||||||
{
|
{
|
||||||
// Skip null production objects
|
for (const tool of production.sptRequiredTools)
|
||||||
if (!production[1])
|
|
||||||
{
|
{
|
||||||
continue;
|
const toolToAdd: Item = {
|
||||||
}
|
_id: this.hashUtil.generate(),
|
||||||
|
_tpl: tool,
|
||||||
|
};
|
||||||
|
|
||||||
if (this.hideoutHelper.isProductionType(production[1]))
|
if (this.itemHelper.isItemTplStackable(tool))
|
||||||
{
|
{
|
||||||
// Production or ScavCase
|
toolToAdd.upd = {
|
||||||
if ((production[1] as Production).RecipeId === request.recipeId)
|
StackObjectsCount: 1,
|
||||||
{
|
|
||||||
prodId = production[0]; // Set to objects key
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prodId === undefined)
|
toolsToSendToPlayer.push([toolToAdd]);
|
||||||
{
|
}
|
||||||
this.logger.error(
|
|
||||||
this.localisationService.getText(
|
|
||||||
"hideout-unable_to_find_production_in_profile_by_recipie_id",
|
|
||||||
request.recipeId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.httpResponse.appendErrorToOutput(output);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the recipe is the same as the last one - get bonus when crafting same thing multiple times
|
// Check if the recipe is the same as the last one - get bonus when crafting same thing multiple times
|
||||||
@ -920,15 +955,34 @@ export class HideoutController
|
|||||||
hoursCrafting -= this.hideoutConfig.hoursForSkillCrafting * multiplierCrafting;
|
hoursCrafting -= this.hideoutConfig.hoursForSkillCrafting * multiplierCrafting;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create request for what we want to add to stash
|
// Make sure we can fit both the craft result and tools in the stash
|
||||||
|
const totalResultItems = toolsToSendToPlayer.concat(itemAndChildrenToSendToPlayer);
|
||||||
|
if (!this.inventoryHelper.canPlaceItemsInInventory(sessionID, totalResultItems))
|
||||||
|
{
|
||||||
|
this.httpResponse.appendErrorToOutput(output, this.localisationService.getText("inventory-no_stash_space"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the used tools to the stash as non-FiR
|
||||||
|
const addToolsRequest: IAddItemsDirectRequest = {
|
||||||
|
itemsWithModsToAdd: toolsToSendToPlayer,
|
||||||
|
foundInRaid: false,
|
||||||
|
useSortingTable: false,
|
||||||
|
callback: null,
|
||||||
|
};
|
||||||
|
this.inventoryHelper.addItemsToStash(sessionID, addToolsRequest, pmcData, output);
|
||||||
|
if (output.warnings.length > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the crafting result to the stash, marked as FiR
|
||||||
const addItemsRequest: IAddItemsDirectRequest = {
|
const addItemsRequest: IAddItemsDirectRequest = {
|
||||||
itemsWithModsToAdd: itemAndChildrenToSendToPlayer,
|
itemsWithModsToAdd: itemAndChildrenToSendToPlayer,
|
||||||
foundInRaid: true,
|
foundInRaid: true,
|
||||||
useSortingTable: false,
|
useSortingTable: false,
|
||||||
callback: null,
|
callback: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add FiR crafted items(s) to player inventory
|
|
||||||
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);
|
this.inventoryHelper.addItemsToStash(sessionID, addItemsRequest, pmcData, output);
|
||||||
if (output.warnings.length > 0)
|
if (output.warnings.length > 0)
|
||||||
{
|
{
|
||||||
|
@ -2,12 +2,14 @@ import { inject, injectable } from "tsyringe";
|
|||||||
|
|
||||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||||
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
||||||
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class PresetController
|
export class PresetController
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(
|
||||||
|
@inject("WinstonLogger") protected logger: ILogger,
|
||||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||||
)
|
)
|
||||||
@ -15,11 +17,17 @@ export class PresetController
|
|||||||
|
|
||||||
public initialize(): void
|
public initialize(): void
|
||||||
{
|
{
|
||||||
const presets: IPreset[] = Object.values(this.databaseServer.getTables().globals.ItemPresets);
|
const presets: [string, IPreset][] = Object.entries(this.databaseServer.getTables().globals.ItemPresets);
|
||||||
const reverse: Record<string, string[]> = {};
|
const reverse: Record<string, string[]> = {};
|
||||||
|
|
||||||
for (const preset of presets)
|
for (const [id, preset] of presets)
|
||||||
{
|
{
|
||||||
|
if (id != preset._id)
|
||||||
|
{
|
||||||
|
this.logger.error(`Preset for template '${preset._items[0]._tpl}' has invalid id (${id} != ${preset._id}). Skipping`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const tpl = preset._items[0]._tpl;
|
const tpl = preset._items[0]._tpl;
|
||||||
|
|
||||||
if (!(tpl in reverse))
|
if (!(tpl in reverse))
|
||||||
|
@ -95,11 +95,20 @@ export class HideoutHelper
|
|||||||
modifiedProductionTime = 40;
|
modifiedProductionTime = 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmcData.Hideout.Production[body.recipeId] = this.initProduction(
|
const production = this.initProduction(
|
||||||
body.recipeId,
|
body.recipeId,
|
||||||
modifiedProductionTime,
|
modifiedProductionTime,
|
||||||
recipe.needFuelForAllProductionTime,
|
recipe.needFuelForAllProductionTime,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Store the tools used for this production, so we can return them later
|
||||||
|
const productionTools = recipe.requirements.filter(req => req.type === "Tool").map(req => req.templateId);
|
||||||
|
if (productionTools.length > 0)
|
||||||
|
{
|
||||||
|
production.sptRequiredTools = productionTools;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmcData.Hideout.Production[body.recipeId] = production;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -539,6 +548,7 @@ export class HideoutHelper
|
|||||||
recipeId: HideoutHelper.waterCollector,
|
recipeId: HideoutHelper.waterCollector,
|
||||||
Action: "HideoutSingleProductionStart",
|
Action: "HideoutSingleProductionStart",
|
||||||
items: [],
|
items: [],
|
||||||
|
tools: [],
|
||||||
timestamp: this.timeUtil.getTimestamp(),
|
timestamp: this.timeUtil.getTimestamp(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -393,6 +393,8 @@ export interface Productive
|
|||||||
sptIsComplete?: boolean;
|
sptIsComplete?: boolean;
|
||||||
/** Is the craft a Continuous, e.g bitcoins/water collector */
|
/** Is the craft a Continuous, e.g bitcoins/water collector */
|
||||||
sptIsContinuous?: boolean;
|
sptIsContinuous?: boolean;
|
||||||
|
/** Stores a list of tools used in this craft, to give back once the craft is done */
|
||||||
|
sptRequiredTools?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Production extends Productive
|
export interface Production extends Productive
|
||||||
|
@ -3,6 +3,7 @@ export interface IHideoutSingleProductionStartRequestData
|
|||||||
Action: "HideoutSingleProductionStart";
|
Action: "HideoutSingleProductionStart";
|
||||||
recipeId: string;
|
recipeId: string;
|
||||||
items: Item[];
|
items: Item[];
|
||||||
|
tools: Item[];
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user