Пример #1
0
 /// <summary>
 /// Gets the largest cordial available to use.
 /// </summary>
 /// <param name="cordialType"></param>
 /// <returns></returns>
 public InventoryItem GetLargestCordial(CordialType cordialType)
 {
     return(this.cordialStock
            .Where(k =>
                   cordialType != CordialType.None &&
                   (cordialType == CordialType.Auto || k.Key.Id == (uint)cordialType) &&
                   k.Value.Quantity > 0 &&
                   k.Value.CanUse(ExProfileBehavior.Me))
            .OrderByDescending(k => CordialDataMap[k.Key].Gp)
            .Select(k => k.Value)
            .FirstOrDefault());
 }
Пример #2
0
        /// <summary>
        /// Gets the most appropriate cordial available that gives the player enough GP.
        /// </summary>
        /// <param name="gpNeeded">Amount of GP needed to gather.</param>
        /// <returns></returns>
        public InventoryItem GetFulfillingCordial(int gpNeeded, CordialType cordialType)
        {
            var best = this.cordialStock
                       .Where(k =>
                              cordialType != CordialType.None &&
                              (cordialType == CordialType.Auto || k.Key.Id == (uint)cordialType) &&
                              k.Value.Quantity > 0 &&
                              k.Value.CanUse(ExProfileBehavior.Me) &&
                              CordialDataMap[k.Key].Gp >= gpNeeded)
                       .OrderBy(k => CordialDataMap[k.Key].Gp)
                       .Select(k => k.Value)
                       .FirstOrDefault();

            return(best);
        }
Пример #3
0
        /// <summary>
        /// Gets the most appropriate cordial available that gives the player GP without going over the missing GP.
        /// </summary>
        /// <param name="gpMissing"></param>
        /// <param name="cordialType"></param>
        /// <returns></returns>
        public InventoryItem GetBestCordial(int gpMissing, CordialType cordialType)
        {
            var best = this.cordialStock
                .Where(k =>
                    cordialType != CordialType.None
                    && (cordialType == CordialType.Auto || k.Key.Id == (uint)cordialType)
                    && k.Value.Quantity > 0
                    && k.Value.CanUse(ExProfileBehavior.Me)
                    && CordialDataMap[k.Key].Gp <= gpMissing)
                .OrderByDescending(k => CordialDataMap[k.Key].Gp)
                .Select(k => k.Value)
                .FirstOrDefault();

            return best;
        }
Пример #4
0
        private async Task <bool> UseCordial(CordialType cordialType, int maxTimeoutSeconds = 5)
        {
            if (!(CordialSpellData.Cooldown.TotalSeconds < maxTimeoutSeconds))
            {
                return(false);
            }

            BagSlot cordial = InventoryManager.FilledSlots.FirstOrDefault(slot => slot.RawItemId == (uint)cordialType);

            if (cordial != null)
            {
                StatusText = Localization.ExFish_UseCordialWhenAvailable;

                Logger.Info(
                    Localization.ExFish_UseCordial,
                    (int)CordialSpellData.Cooldown.TotalSeconds,
                    ExProfileBehavior.Me.CurrentGP);

                if (!await Coroutine.Wait(
                        TimeSpan.FromSeconds(maxTimeoutSeconds),
                        () =>
                {
                    if (!ExProfileBehavior.Me.IsMounted || !(CordialSpellData.Cooldown.TotalSeconds < 2))
                    {
                        return(cordial.CanUse(ExProfileBehavior.Me));
                    }

                    ActionManager.Dismount();
                    return(false);
                }))
                {
                    return(false);
                }

                await Coroutine.Sleep(500);

                Logger.Info("Using " + cordialType);
                cordial.UseItem(ExProfileBehavior.Me);
                await Coroutine.Sleep(1500);

                return(true);
            }
            Logger.Warn(Localization.ExFish_NoCordial + cordialType);

            return(false);
        }
        /// <summary>
        /// Executes the strategy logic in charge of regenerating GP after the gather.
        /// </summary>
        /// <returns></returns>
        public async Task <GpRegenStrategyResult> RegenerateGp(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType)
        {
            var rtn = new GpRegenStrategyResult()
            {
                StrategyState        = GpRegenStrategyResult.GpRegenStrategyResultState.OK,
                EffectiveCordialType = cordialType,
                OriginalCordialType  = cordialType,
            };

            var useCordial = cordialTime.HasFlag(CordialTime.AfterGather) &&
                             this.cordialStock.HasStock() &&
                             this.cordialStock.GetCordialCooldown() == TimeSpan.Zero;

            var currentGp = ExProfileBehavior.Me.CurrentGP;
            var maxGp     = ExProfileBehavior.Me.MaxGP;
            var missingGp = maxGp - currentGp;
            var cordial   = this.cordialStock.GetBestCordial(missingGp, cordialType);

            // Return OK if there is no cordial to use
            if (cordial == null)
            {
                rtn.UseState = InventoryItem.UseResult.OK;
                return(rtn);
            }

            // Use the cordial
            rtn.UseState = await cordial.Use(
                ExProfileBehavior.Me
                );

            // Log the result
            this.LogCordialResult(
                rtn.UseState ?? InventoryItem.UseResult.CantUse,
                cordial,
                currentGp
                );

            return(rtn);
        }
Пример #6
0
        /// <summary>
        /// Executes the strategy logic in charge of regenerating GP before the gather.
        /// </summary>
        /// <returns></returns>
        public async Task <GpRegenStrategyResult> RegenerateGp(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType)
        {
            var rtn = new GpRegenStrategyResult()
            {
                EffectiveCordialType = this.effectiveCordialType,
                OriginalCordialType  = this.requestedCordialType,
            };

            // Return OK immediately if there is no node
            if (node == null)
            {
                this.logger.GatheringNodeIsGone();

                rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NodeGone;
                return(rtn);
            }

            // Configure the strategy and report to the log
            this.Configure(node, gatherRotation, gatherStrategy, cordialTime, cordialType);
            this.logger.LogReport(this);

            // Return not enough time if player has less than 3 seconds to gather
            if (this.EffectiveTimeTillGather.TotalSeconds < 3)
            {
                this.logger.GatheringNotEnoughTime();

                rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughTime;
                return(rtn);
            }

            if (this.gatherStrategy == GatherStrategy.GatherOrCollect)
            {
                // Return not enough GP if we cannot meet the target breakpoint for the rotation
                if (this.BreakpointGp > this.TargetGp)
                {
                    this.logger.RegeneratingNotEnoughGp();

                    rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughGp;
                    return(rtn);
                }
            }

            // Use the cordial if one was selected
            if (this.Cordial != null)
            {
                rtn.UseState = await this.Cordial.Use(
                    ExProfileBehavior.Me,
                    maxTimeout : this.EffectiveTimeTillGather,
                    dismount : true
                    );

                this.LogCordialResult(rtn.UseState.Value);

                // Recalculate player's ability to gather after cordial use failure
                if (rtn.UseState != InventoryItem.UseResult.OK)
                {
                    this.effectiveCordialType = CordialType.None;
                    this.CalculateTargetAndCordialSelection();

                    this.logger.LogReport(this);

                    // Return not enough GP if we cannot meet the target breakpoint for the rotation
                    if (this.BreakpointGp > this.TargetGp)
                    {
                        this.logger.RegeneratingNotEnoughGp();

                        rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.NotEnoughGp;
                        return(rtn);
                    }
                }
            }

            // Handle TouchAndGo overrides
            if (this.gatherStrategy == GatherStrategy.TouchAndGo)
            {
                // Do nothing if this is not ephemeral
                if (!node.IsEphemeral())
                {
                    this.logger.GatheringNodeSkippedNotEphemeral();

                    rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK;
                    return(rtn);
                }

                if (this.EffectiveTimeToRegenerate.TotalSeconds > MAX_TOUCHANDGO_WAIT)
                {
                    this.logger.RegeneratingSkippedExceedsEphemeralMaxWait(
                        this.EffectiveTimeToRegenerate.TotalSeconds,
                        MAX_TOUCHANDGO_WAIT
                        );

                    rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK;
                    return(rtn);
                }
            }

            // Return OK immediately if the rotation forcefully gathers the item
            if (gatherRotation.ShouldForceGather(node))
            {
                rtn.StrategyState = GpRegenStrategyResult.GpRegenStrategyResultState.OK;
                return(rtn);
            }

            // Execute wait logic
            rtn.StrategyState = await this.WaitForGpRegeneration();

            return(rtn);
        }
Пример #7
0
        /// <summary>
        /// Configures the strategy for use
        /// </summary>
        protected void Configure(GatheringPointObject node, IGatheringRotation gatherRotation, GatherStrategy gatherStrategy, CordialTime cordialTime, CordialType cordialType)
        {
            if (gatherRotation == null)
            {
                throw new ArgumentNullException("gatherRotation");
            }

            // Set gathering parameters
            this.gatherRotation = gatherRotation;
            this.gatherStrategy = gatherStrategy;

            // Set cordial parameters
            this.cordialTime          = cordialTime;
            this.requestedCordialType = this.effectiveCordialType = cordialType;

            // Override cordial type
            if (this.requestedCordialType > CordialType.None)
            {
                // Turn off cordial when there is no stock
                if (!this.cordialStockManager.HasStock())
                {
                    this.effectiveCordialType = CordialType.None;

                    this.logger.RegeneratingCordialUseDisabledNoStock();
                }

                // Turn off cordial when node is not ephemeral in TnG strategies
                if (this.gatherStrategy == GatherStrategy.TouchAndGo && !node.IsEphemeral())
                {
                    this.effectiveCordialType = CordialType.None;
                }
            }
            else
            {
                this.effectiveCordialType = this.requestedCordialType;
            }

            // Set node lifespan parameters
            this.NodeLifespan = new EffectiveNodeLifespan(NodeHelper.GetNodeLifespan(node), this.gatherRotation.Attributes.RequiredTimeInSeconds);
            if (this.gatherStrategy == GatherStrategy.TouchAndGo)
            {
                this.NodeLifespan.Clamp(TimeSpan.Zero, TimeSpan.FromSeconds(MAX_TOUCHANDGO_WAIT));
            }
            this.EffectiveTimeTillGather = this.NodeLifespan.DeSpawn;

            // Set GP parameters
            this.StartingGp  = this.CurrentGp;
            this.MaxGp       = ExProfileBehavior.Me.MaxGP;
            this.EffectiveGp = CharacterResource.GetEffectiveGp(this.NodeLifespan.DeSpawnTicks);

            // Set breakpoint and cordial parameters
            this.CalculateTargetAndCordialSelection();

            // Calculate regeneration parameters
            this.RegeneratedGp = (ushort)(this.TargetGp - this.CordialGp - this.StartingGp);
            if (this.RegeneratedGp < 0)
            {
                this.RegeneratedGp = 0;
            }
            this.EffectiveTimeToRegenerate = CharacterResource.EstimateExpectedRegenerationTime(this.RegeneratedGp);
        }
Пример #8
0
		private async Task<bool> UseCordial(CordialType cordialType, int maxTimeoutSeconds = 5)
		{
			if (CordialSpellData.Cooldown.TotalSeconds < maxTimeoutSeconds)
			{
				var cordial = InventoryManager.FilledSlots.FirstOrDefault(slot => slot.RawItemId == (uint)cordialType);

				if (cordial != null)
				{
					StatusText = "Using cordial when it becomes available";

					Logger.Info(
						"Using Cordial -> Waiting (sec): {0}, CurrentGP: {1}",
						(int)CordialSpellData.Cooldown.TotalSeconds,
						Me.CurrentGP);

					if (await Coroutine.Wait(
						TimeSpan.FromSeconds(maxTimeoutSeconds),
						() =>
							{
								if (Me.IsMounted && CordialSpellData.Cooldown.TotalSeconds < 2)
								{
									Actionmanager.Dismount();
									return false;
								}

								return cordial.CanUse(Me);
							}))
					{
						await Coroutine.Sleep(500);
						Logger.Info("Using " + cordialType);
						cordial.UseItem(Me);
						await Coroutine.Sleep(1500);
						return true;
					}
				}
				else
				{
					Logger.Warn("No Cordial avilable, buy more " + cordialType);
				}
			}

			return false;
		}
Пример #9
0
		public int? GetAdjustedWaitForGp(int gpBeforeGather, int secondsToStartGathering, CordialType cordialType)
		{
			if (CordialTime.HasFlag(CordialTime.BeforeGather) && cordialType > CordialType.None
				&& CordialSpellData.Cooldown.TotalSeconds + 2 <= secondsToStartGathering)
			{
				switch (cordialType)
				{
					case CordialType.Cordial:
						gpBeforeGather += 300;
						break;
					case CordialType.HiCordial:
						gpBeforeGather += 400;
						break;
					case CordialType.Auto:
						if (DataManager.GetItem((uint)CordialType.HiCordial).ItemCount() > 0)
						{
							gpBeforeGather += 400;
						}
						else
						{
							gpBeforeGather += 300;
						}
						break;
				}
			}

			foreach (var gp in gatherRotation.Attributes.RequiredGpBreakpoints)
			{
				if (gp <= gpBeforeGather)
				{
					return Math.Min(Me.MaxGP - (Me.MaxGP % 50), gp);
				}
			}

			return null;
		}
Пример #10
0
		private async Task<bool> UseCordial(CordialType cordialType, int maxTimeoutSeconds = 5)
		{
			if (CordialSpellData.Cooldown.TotalSeconds < maxTimeoutSeconds)
			{
				var cordial = InventoryManager.FilledSlots.FirstOrDefault(slot => slot.RawItemId == (uint) cordialType);

				if (cordial != null)
				{
					StatusText = Localization.Localization.ExFish_UseCordialWhenAvailable;

					Logger.Info(
                        Localization.Localization.ExFish_UseCordial,
						(int) CordialSpellData.Cooldown.TotalSeconds,
						ExProfileBehavior.Me.CurrentGP);

					if (await Coroutine.Wait(
						TimeSpan.FromSeconds(maxTimeoutSeconds),
						() =>
						{
							if (ExProfileBehavior.Me.IsMounted && CordialSpellData.Cooldown.TotalSeconds < 2)
							{
								Actionmanager.Dismount();
								return false;
							}

							return cordial.CanUse(ExProfileBehavior.Me);
						}))
					{
						await Coroutine.Sleep(500);
						Logger.Info("Using " + cordialType);
						cordial.UseItem(ExProfileBehavior.Me);
						await Coroutine.Sleep(1500);
						return true;
					}
				}
				else
				{
					Logger.Warn(Localization.Localization.ExFish_NoCordial + cordialType);
				}
			}

			return false;
		}
Пример #11
0
		private async Task<bool> UseCordial(CordialType cordialType, int maxTimeoutSeconds = 5)
		{
			maxTimeoutSeconds -= 2;

			if (GatherStrategy == GatherStrategy.TouchAndGo)
			{
				Logger.Verbose(Localization.Localization.ExGather_TnGOverride);
				maxTimeoutSeconds = maxTimeoutSeconds.Clamp(2, 16);
			}
			else
			{
				maxTimeoutSeconds = maxTimeoutSeconds.Clamp(2, 180);
			}

			if (CordialSpellData.Cooldown.TotalSeconds < maxTimeoutSeconds)
			{
				var cordial = InventoryManager.FilledSlots.FirstOrDefault(slot => slot.RawItemId == (uint) cordialType);

				if (cordial != null)
				{
					StatusText = Localization.Localization.ExGather_Cordial;

					Logger.Info(
                        Localization.Localization.ExGather_CordialUse,
						(int) CordialSpellData.Cooldown.TotalSeconds,
						ExProfileBehavior.Me.CurrentGP);

					if (await Coroutine.Wait(
						TimeSpan.FromSeconds(maxTimeoutSeconds),
						() =>
						{
							if (ExProfileBehavior.Me.IsMounted && CordialSpellData.Cooldown.TotalSeconds < 2)
							{
								Actionmanager.Dismount();
								return false;
							}

							return cordial.CanUse(ExProfileBehavior.Me) || Core.Player.IsDead;
						}))
					{
						await Coroutine.Sleep(500);
						Logger.Info(Localization.Localization.ExGather_CordialUsing + cordialType);
						cordial.UseItem(ExProfileBehavior.Me);
						await Coroutine.Sleep(1500);
						return true;
					}
				}
				else
				{
					Logger.Warn(Localization.Localization.ExGather_CordialNotAvailable + cordialType);
				}
			}

			return false;
		}