diff --git a/project/src/helpers/HideoutHelper.ts b/project/src/helpers/HideoutHelper.ts index ce99e96e..41aa3a1c 100644 --- a/project/src/helpers/HideoutHelper.ts +++ b/project/src/helpers/HideoutHelper.ts @@ -73,7 +73,9 @@ export class HideoutHelper sessionID: string, ): IItemEventRouterResponse { - const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId); + const recipe = this.databaseServer.getTables().hideout.production.find((production) => + production._id === body.recipeId + ); if (!recipe) { this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", body.recipeId)); @@ -81,9 +83,6 @@ export class HideoutHelper return this.httpResponse.appendErrorToOutput(this.eventOutputHolder.getOutput(sessionID)); } - let modifiedProductionTime = recipe.productionTime - - this.getCraftingSkillProductionTimeReduction(pmcData, recipe.productionTime); - // @Important: Here we need to be very exact: // - normal recipe: Production time value is stored in attribute "productionType" with small "p" // - scav case recipe: Production time value is stored in attribute "ProductionType" with capital "P" @@ -92,10 +91,7 @@ export class HideoutHelper pmcData.Hideout.Production = {}; } - if (modifiedProductionTime > 0 && this.profileHelper.isDeveloperAccount(sessionID)) - { - modifiedProductionTime = 40; - } + const modifiedProductionTime = this.getAdjustedCraftTimeWithSkills(pmcData, body.recipeId); const production = this.initProduction( body.recipeId, @@ -253,25 +249,6 @@ export class HideoutHelper return false; } - /** - * Update progress timer for water collector - * @param pmcData profile to update - * @param productionId id of water collection production to update - * @param hideoutProperties Hideout properties - */ - protected updateWaterCollectorProductionTimer( - pmcData: IPmcData, - productionId: string, - hideoutProperties: { btcFarmCGs?: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean; }, - ): void - { - const timeElapsed = this.getTimeElapsedSinceLastServerTick(pmcData, hideoutProperties.isGeneratorOn); - if (hideoutProperties.waterCollectorHasFilter) - { - pmcData.Hideout.Production[productionId].Progress += timeElapsed; - } - } - /** * Iterate over productions and update their progress timers * @param pmcData Profile to check for productions and update @@ -345,6 +322,25 @@ export class HideoutHelper } } + /** + * Update progress timer for water collector + * @param pmcData profile to update + * @param productionId id of water collection production to update + * @param hideoutProperties Hideout properties + */ + protected updateWaterCollectorProductionTimer( + pmcData: IPmcData, + productionId: string, + hideoutProperties: { btcFarmCGs?: number; isGeneratorOn: boolean; waterCollectorHasFilter: boolean; }, + ): void + { + const timeElapsed = this.getTimeElapsedSinceLastServerTick(pmcData, hideoutProperties.isGeneratorOn); + if (hideoutProperties.waterCollectorHasFilter) + { + pmcData.Hideout.Production[productionId].Progress += timeElapsed; + } + } + /** * Update a productions progress value based on the amount of time that has passed * @param pmcData Player profile @@ -558,6 +554,9 @@ export class HideoutHelper const prod = pmcData.Hideout.Production[HideoutHelper.waterCollector]; if (prod && this.isProduction(prod)) { + // Update craft time to account for increases in players craft time skill + prod.ProductionTime = this.getAdjustedCraftTimeWithSkills(pmcData, prod.RecipeId); + this.updateWaterFilters(area, prod, isGeneratorOn, pmcData); } else @@ -576,6 +575,35 @@ export class HideoutHelper } } + /** + * Get craft time and make adjustments to account for dev profile + crafting skill level + * @param pmcData Player profile making craft + * @param recipeId Recipe being crafted + * @returns + */ + protected getAdjustedCraftTimeWithSkills(pmcData: IPmcData, recipeId: string): number + { + const recipe = this.databaseServer.getTables().hideout.production.find((production) => + production._id === recipeId + ); + if (!recipe) + { + this.logger.error(this.localisationService.getText("hideout-missing_recipe_in_db", recipeId)); + + return undefined; + } + + let modifiedProductionTime = recipe.productionTime + - this.getCraftingSkillProductionTimeReduction(pmcData, recipe.productionTime); + + if (modifiedProductionTime > 0 && this.profileHelper.isDeveloperAccount(pmcData._id)) + { + modifiedProductionTime = 40; + } + + return modifiedProductionTime; + } + /** * Adjust water filter objects resourceValue or delete when they reach 0 resource * @param waterFilterArea water filter area to update @@ -594,7 +622,7 @@ export class HideoutHelper const productionTime = this.getTotalProductionTimeSeconds(HideoutHelper.waterCollector); const secondsSinceServerTick = this.getTimeElapsedSinceLastServerTick(pmcData, isGeneratorOn); - filterDrainRate = this.adjustWaterFilterDrainRate( + filterDrainRate = this.getAdjustWaterFilterDrainRate( secondsSinceServerTick, productionTime, production.Progress, @@ -605,56 +633,57 @@ export class HideoutHelper let pointsConsumed = 0; if (production.Progress < productionTime) { - // Check all slots that take water filters - // Must loop to find first water filter and use that + // Check all slots that take water filters until we find one with filter in it for (let i = 0; i < waterFilterArea.slots.length; i++) { - // Has a water filter installed into slot - if (waterFilterArea.slots[i].item) + // No water filter, skip + if (!waterFilterArea.slots[i].item) { - // How many units of filter are left - let resourceValue = (waterFilterArea.slots[i].item[0].upd?.Resource) - ? waterFilterArea.slots[i].item[0].upd.Resource.Value - : null; - if (!resourceValue) - { - // None left - resourceValue = 100 - filterDrainRate; - pointsConsumed = filterDrainRate; - } - else - { - pointsConsumed = (waterFilterArea.slots[i].item[0].upd.Resource.UnitsConsumed || 0) - + filterDrainRate; - resourceValue -= filterDrainRate; - } - - // Round to get values to 3dp - resourceValue = Math.round(resourceValue * 10000) / 10000; - pointsConsumed = Math.round(pointsConsumed * 10000) / 10000; - - // Check amount of units consumed for possible increment of hideout mgmt skill point - if (pmcData && Math.floor(pointsConsumed / 10) >= 1) - { - this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, 1); - pointsConsumed -= 10; - } - - // Filter has some juice left in it after we adjusted it - if (resourceValue > 0) - { - // Set filter consumed amount - waterFilterArea.slots[i].item[0].upd = this.getAreaUpdObject(1, resourceValue, pointsConsumed); - this.logger.debug(`Water filter has: ${resourceValue} units left in slot ${i + 1}`); - - break; // Break here to avoid updating all filters - } - - // Filter ran out / used up - delete waterFilterArea.slots[i].item; - // Update remaining resources to be subtracted - filterDrainRate = Math.abs(resourceValue); + continue; } + + // How many units of filter are left + let resourceValue = (waterFilterArea.slots[i].item[0].upd?.Resource) + ? waterFilterArea.slots[i].item[0].upd.Resource.Value + : null; + if (!resourceValue) + { + // Missing, is new filter, add default and subtract usage + resourceValue = 100 - filterDrainRate; + pointsConsumed = filterDrainRate; + } + else + { + pointsConsumed = (waterFilterArea.slots[i].item[0].upd.Resource.UnitsConsumed || 0) + + filterDrainRate; + resourceValue -= filterDrainRate; + } + + // Round to get values to 3dp + resourceValue = Math.round(resourceValue * 1000) / 1000; + pointsConsumed = Math.round(pointsConsumed * 1000) / 1000; + + // Check units consumed for possible increment of hideout mgmt skill point + if (pmcData && Math.floor(pointsConsumed / 10) >= 1) + { + this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.HIDEOUT_MANAGEMENT, 1); + pointsConsumed -= 10; + } + + // Filter has some fuel left in it after our adjustment + if (resourceValue > 0) + { + // Set filters consumed amount + waterFilterArea.slots[i].item[0].upd = this.getAreaUpdObject(1, resourceValue, pointsConsumed); + this.logger.debug(`Water filter has: ${resourceValue} units left in slot ${i + 1}`); + + break; // Break here to avoid iterating other filters now w're done + } + + // Filter ran out / used up + delete waterFilterArea.slots[i].item; + // Update remaining resources to be subtracted + filterDrainRate = Math.abs(resourceValue); } } } @@ -666,23 +695,21 @@ export class HideoutHelper * @param totalProductionTime Total time collecting water * @param productionProgress how far water collector has progressed * @param baseFilterDrainRate Base drain rate - * @returns + * @returns drain rate (adjusted) */ - protected adjustWaterFilterDrainRate( + protected getAdjustWaterFilterDrainRate( secondsSinceServerTick: number, totalProductionTime: number, productionProgress: number, baseFilterDrainRate: number, ): number { - const drainRateMultiplier = secondsSinceServerTick > totalProductionTime + const drainTimeSeconds = secondsSinceServerTick > totalProductionTime ? (totalProductionTime - productionProgress) // more time passed than prod time, get total minus the current progress : secondsSinceServerTick; // Multiply drain rate by calculated multiplier - baseFilterDrainRate *= drainRateMultiplier; - - return baseFilterDrainRate; + return baseFilterDrainRate * drainTimeSeconds; } /** @@ -952,7 +979,7 @@ export class HideoutHelper protected getHideoutManagementConsumptionBonus(pmcData: IPmcData): number { const hideoutManagementSkill = this.profileHelper.getSkillFromProfile(pmcData, SkillTypes.HIDEOUT_MANAGEMENT); - if (!hideoutManagementSkill) + if (!hideoutManagementSkill || hideoutManagementSkill.Progress === 0) { return 0; } @@ -976,7 +1003,7 @@ export class HideoutHelper */ protected getCraftingSkillProductionTimeReduction(pmcData: IPmcData, productionTime: number): number { - const craftingSkill = pmcData.Skills.Common.find((x) => x.Id === SkillTypes.CRAFTING); + const craftingSkill = pmcData.Skills.Common.find((skill) => skill.Id === SkillTypes.CRAFTING); if (!craftingSkill) { return productionTime;