using SptCommon.Annotations; using Core.Models.Eft.Common; using Core.Models.Eft.Common.Tables; using Core.Models.Eft.Hideout; using Core.Models.Eft.ItemEvent; using Core.Models.Enums; using Core.Models.Utils; using Core.Services; using Core.Utils; namespace Core.Helpers; [Injectable] public class HideoutHelper( ISptLogger _logger, TimeUtil _timeUtil, LocalisationService _localisationService ) { public const string BitcoinFarm = "5d5c205bd582a50d042a3c0e"; public const string CultistCircleCraftId = "66827062405f392b203a44cf"; public const string BitcoinProductionId = "5d5c205bd582a50d042a3c0e"; public const string WaterCollector = "5d5589c1f934db045e6c5492"; public const int MaxSkillPoint = 5000; /// /// Add production to profiles' Hideout.Production array /// /// Profile to add production to /// Production request /// Session id /// client response public void RegisterProduction( PmcData profileData, HideoutSingleProductionStartRequestData productionRequest, string sessionId) { throw new NotImplementedException(); } /// /// Add production to profiles' Hideout.Production array /// /// Profile to add production to /// Production request /// Session id /// client response public void RegisterProduction( PmcData profileData, HideoutContinuousProductionStartRequestData productionRequest, string sessionId) { throw new NotImplementedException(); } /// /// This convenience function initializes new Production Object /// with all the constants. /// public Production InitProduction( string recipeId, int productionTime, bool needFuelForAllProductionTime) { throw new NotImplementedException(); } /// /// Is the provided object a Production type /// /// /// public bool IsProductionType(Production Production) { throw new NotImplementedException(); } /// /// Apply bonus to player profile given after completing hideout upgrades /// /// Profile to add bonus to /// Bonus to add to profile public void ApplyPlayerUpgradesBonuses(PmcData profileData, Bonus bonus) { // Handle additional changes some bonuses need before being added var bonusToAdd = new Bonus(); switch (bonus.Type) { case BonusType.StashSize: { // Find stash item and adjust tpl to new tpl from bonus var stashItem = profileData.Inventory.Items.FirstOrDefault((x) => x.Id == profileData.Inventory.Stash); if (stashItem is null) { _logger.Warning(_localisationService.GetText("hideout-unable_to_apply_stashsize_bonus_no_stash_found", profileData.Inventory.Stash)); } stashItem.Template = bonus.TemplateId; break; } case BonusType.MaximumEnergyReserve: // Amend max energy in profile profileData.Health.Energy.Maximum += bonus.Value; break; case BonusType.TextBonus: // Delete values before they're added to profile bonus.IsPassive = null; bonus.IsProduction = null; bonus.IsVisible = null; break; } // Add bonus to player bonuses array in profile // EnergyRegeneration, HealthRegeneration, RagfairCommission, ScavCooldownTimer, SkillGroupLevelingBoost, ExperienceRate, QuestMoneyReward etc _logger.Debug($"Adding bonus: {bonus.Type} to profile, value: {bonus.Value}"); profileData.Bonuses.Add(bonus); } /// /// Process a players hideout, update areas that use resources + increment production timers /// /// Session id public void UpdatePlayerHideout(string sessionId) { throw new NotImplementedException(); } /// /// Get various properties that will be passed to hideout update-related functions /// /// Player profile /// Properties protected (int btcFarmCGs, bool isGeneratorOn, bool waterCollectorHasFilter) GetHideoutProperties(PmcData profileData) { throw new NotImplementedException(); } protected bool DoesWaterCollectorHaveFilter(BotHideoutArea waterCollector) { throw new NotImplementedException(); } /// /// Iterate over productions and update their progress timers /// /// Profile to check for productions and update /// Hideout properties protected void UpdateProductionTimers( PmcData profileData, (int btcFarmCGs, bool isGeneratorOn, bool waterCollectorHasFilter) hideoutProperties) { throw new NotImplementedException(); } /// /// Is a craft from a particular hideout area /// /// Craft to check /// Type to check craft against /// True if it is from that area protected bool IsCraftOfType(Production craft, HideoutAreas hideoutType) { throw new NotImplementedException(); } /// /// Has the craft completed /// Ignores bitcoin farm/cultist circle as they're continuous crafts /// /// Craft to check /// True when craft is complete protected bool IsCraftComplete(Production craft) { throw new NotImplementedException(); } /// /// Update progress timer for water collector /// /// profile to update /// id of water collection production to update /// Hideout properties protected void UpdateWaterCollectorProductionTimer( PmcData pmcData, string productionId, Dictionary hideoutProperties) { throw new NotImplementedException(); } /// /// Update a productions progress value based on the amount of time that has passed /// /// Player profile /// Production id being crafted /// Recipe data being crafted /// protected void UpdateProductionProgress( PmcData pmcData, string prodId, HideoutProduction recipe, Dictionary hideoutProperties) { throw new NotImplementedException(); } protected void UpdateCultistCircleCraftProgress(PmcData pmcData, string prodId) { throw new NotImplementedException(); } protected void FlagCultistCircleCraftAsComplete(Production Production) { throw new NotImplementedException(); } /// /// Check if a productions progress value matches its corresponding recipes production time value /// /// Player profile /// Production id /// Recipe being crafted /// progress matches productionTime from recipe protected bool DoesProgressMatchProductionTime(PmcData pmcData, string prodId) { throw new NotImplementedException(); } /// /// Update progress timer for scav case /// /// Profile to update /// Id of scav case production to update protected void UpdateScavCaseProductionTimer(PmcData pmcData, string productionId) { throw new NotImplementedException(); } /// /// Iterate over hideout areas that use resources (fuel/filters etc) and update associated values /// /// Session id /// Profile to update areas of /// hideout properties protected void UpdateAreasWithResources( string sessionID, PmcData pmcData, Dictionary hideoutProperties) { throw new NotImplementedException(); } /// /// Decrease fuel from generator slots based on amount of time since last time this occurred /// /// Hideout area /// Player profile /// Is the generator turned on since last update protected void UpdateFuel(BotHideoutArea generatorArea, PmcData pmcData, bool isGeneratorOn) { throw new NotImplementedException(); } protected void UpdateWaterCollector( string sessionId, PmcData pmcData, BotHideoutArea area, Dictionary hideoutProperties) { throw new NotImplementedException(); } /// /// Get craft time and make adjustments to account for dev profile + crafting skill level /// /// Player profile making craft /// Recipe being crafted /// Should the hideout management bonus be applied to the calculation /// Items craft time with bonuses subtracted public double GetAdjustedCraftTimeWithSkills( PmcData playerProfile, string recipeId, bool applyHideoutManagementBonus = false) { throw new NotImplementedException(); } /// /// Adjust water filter objects resourceValue or delete when they reach 0 resource /// /// Water filter area to update /// Production object /// Is generator enabled /// Player profile protected void UpdateWaterFilters( BotHideoutArea waterFilterArea, Production production, bool isGeneratorOn, PmcData playerProfile) { throw new NotImplementedException(); } /// /// Get an adjusted water filter drain rate based on time elapsed since last run, /// handle edge case when craft time has gone on longer than total production time /// /// Time passed /// Total time collecting water /// How far water collector has progressed /// Base drain rate /// Drain rate (adjusted) protected double GetTimeAdjustedWaterFilterDrainRate( double secondsSinceServerTick, double totalProductionTime, double productionProgress, double baseFilterDrainRate) { throw new NotImplementedException(); } /// /// Get the water filter drain rate based on hideout bonuses player has /// /// Player profile /// Drain rate protected double GetWaterFilterDrainRate(PmcData playerProfile) { throw new NotImplementedException(); } /// /// Get the production time in seconds for the desired production /// /// Id, e.g. Water collector id /// Seconds to produce item protected double GetTotalProductionTimeSeconds(string prodId) { throw new NotImplementedException(); } /// /// Create a upd object using passed in parameters /// /// /// /// /// Upd protected Upd GetAreaUpdObject( int stackCount, double resourceValue, int resourceUnitsConsumed, bool isFoundInRaid) { throw new NotImplementedException(); } protected void UpdateAirFilters(BotHideoutArea airFilterArea, PmcData playerProfile, bool isGeneratorOn) { throw new NotImplementedException(); } protected void UpdateBitcoinFarm( PmcData playerProfile, Production btcProduction, int btcFarmCGs, bool isGeneratorOn) { throw new NotImplementedException(); } /// /// Add bitcoin object to btc production products array and set progress time /// /// Bitcoin production object /// Time to craft a bitcoin protected void AddBtcToProduction(Production btcProd, double coinCraftTimeSeconds) { throw new NotImplementedException(); } /// /// Get number of ticks that have passed since hideout areas were last processed, reduced when generator is off /// /// Player profile /// Is the generator on for the duration of elapsed time /// Hideout production recipe being crafted we need the ticks for /// Amount of time elapsed in seconds protected double GetTimeElapsedSinceLastServerTick( PmcData playerProfile, bool isGeneratorOn, HideoutProduction recipe = null) { throw new NotImplementedException(); } /// /// Get a count of how many possible BTC can be gathered by the profile /// /// Profile to look up /// Coin slot count protected int GetBTCSlots(PmcData profileData) { throw new NotImplementedException(); } /// /// Get a count of how many additional bitcoins player hideout can hold with elite skill /// protected int GetEliteSkillAdditionalBitcoinSlotCount() { throw new NotImplementedException(); } /// /// HideoutManagement skill gives a consumption bonus the higher the level /// 0.5% per level per 1-51, (25.5% at max) /// /// Profile to get hideout consumption level from /// Consumption bonus protected double GetHideoutManagementConsumptionBonus(PmcData profileData) { throw new NotImplementedException(); } /// /// Get a multiplier based on player's skill level and value per level /// /// Player profile /// Player skill from profile /// Value from globals.config.SkillsSettings - `PerLevel` /// Multiplier from 0 to 1 protected double GetSkillBonusMultipliedBySkillLevel(PmcData profileData, SkillTypes skill, double valuePerLevel) { throw new NotImplementedException(); } /// /// /// Player profile /// Time to complete hideout craft in seconds /// Skill bonus to get reduction from /// Skill bonus amount to apply /// Seconds to reduce craft time by public double GetSkillProductionTimeReduction( PmcData profileData, double productionTime, SkillTypes skill, double amountPerLevel) { throw new NotImplementedException(); } public bool IsProduction(Production Production) { throw new NotImplementedException(); } /// /// Gather crafted BTC from hideout area and add to inventory /// Reset production start timestamp if hideout area at full coin capacity /// /// Player profile /// Take production request /// Session id /// Output object to update public void GetBTC( PmcData profileData, HideoutTakeProductionRequestData request, string sessionId, ItemEventRouterResponse output) { throw new NotImplementedException(); } /// /// Upgrade hideout wall from starting level to interactable level if necessary stations have been upgraded /// /// Profile to upgrade wall in public void UnlockHideoutWallInProfile(PmcData profileData) { var profileHideoutAreas = profileData.Hideout.Areas; var waterCollector = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.WATER_COLLECTOR); var medStation = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.MEDSTATION); var wall = profileHideoutAreas.FirstOrDefault((x) => x.Type == HideoutAreas.EMERGENCY_WALL); // No collector or med station, skip if ((waterCollector is null && medStation is null)) { return; } // If med-station > level 1 AND water collector > level 1 AND wall is level 0 if (waterCollector?.Level >= 1 && medStation?.Level >= 1 && wall?.Level <= 0) { wall.Level = 3; } } /// /// Hideout improvement is flagged as complete /// /// hideout improvement object /// true if complete protected bool HideoutImprovementIsComplete(HideoutImprovement improvement) { throw new NotImplementedException(); } /// /// Iterate over hideout improvements not completed and check if they need to be adjusted /// /// Profile to adjust public void SetHideoutImprovementsToCompleted(PmcData profileData) { foreach (var improvementId in profileData.Hideout.Improvements) { if (!profileData.Hideout.Improvements.TryGetValue(improvementId.Key, out var improvementDetails)) { continue; } if (improvementDetails.Completed == false && improvementDetails.ImproveCompleteTimestamp < _timeUtil.GetTimeStamp() ) { improvementDetails.Completed = true; } } } /// /// Add/remove bonus combat skill based on number of dogtags in place of fame hideout area /// /// Player profile public void ApplyPlaceOfFameDogtagBonus(PmcData profileData) { throw new NotImplementedException(); } /// /// Calculate the raw dogtag combat skill bonus for place of fame based on number of dogtags /// Reverse engineered from client code /// /// Player profile /// Active dogtags in place of fame dogtag slots /// Combat bonus protected double GetDogtagCombatSkillBonusPercent(PmcData profileData, List activeDogtags) { throw new NotImplementedException(); } /// /// The wall pollutes a profile with various temp buffs/debuffs, /// Remove them all /// /// Hideout area data /// Player profile public void RemoveHideoutWallBuffsAndDebuffs(HideoutArea wallAreaData, PmcData profileData) { throw new NotImplementedException(); } }