Пример #1
0
        /// <summary>
        /// Assigns key items from the item user's inventory.
        /// </summary>
        /// <param name="self">The game client data for the item user.</param>
        public PeasantItemCommands(TkClient self)
        {
            _self = self;

            _ring         = _self.Inventory.KeyItems.Ring;
            _yellowScroll = _self.Inventory.KeyItems.YellowScroll;
        }
Пример #2
0
 /// <summary>
 /// Assigns Harden Armor, Sanctuary, and Valor spells from the Poet's spell inventory.
 /// </summary>
 /// <param name="self">The game client data for the Poet.</param>
 public CasterAsvCommands(PoetClient self)
 {
     _self             = self;
     _hardenArmorSpell = self.Spells.KeySpells.HardenArmor;
     _sanctuarySpell   = self.Spells.KeySpells.Sanctuary;
     _valorSpell       = self.Spells.KeySpells.Valor;
 }
Пример #3
0
        /// <summary>
        /// Assigns mana restoration spells from a Mage's spell inventory.
        /// </summary>
        /// <param name="self">The game client data for the Mage.</param>
        protected CasterManaCommands(MageClient self)
        {
            Self = self;

            InvokeSpell  = self.Spells.KeySpells.Invoke;
            InvokeStatus = self.Status.Invoke;
        }
        private Direction GetFollowDirection(TkClient target, uint distance)
        {
            if (target.Environment.Map.Name != _self.Environment.Map.Name)
            {
                return(Direction.None);
            }

            var x = (int)target.Environment.Map.Coordinates.X - (int)_self.Environment.Map.Coordinates.X;
            var y = (int)target.Environment.Map.Coordinates.Y - (int)_self.Environment.Map.Coordinates.Y;

            if (Math.Abs(x) >= Math.Abs(y) && Math.Abs(x) > distance)
            {
                return(x > 0
                    ? Direction.Right
                    : Direction.Left);
            }

            if (Math.Abs(y) > distance)
            {
                return(y > 0
                    ? Direction.Down
                    : Direction.Up);
            }

            return(Direction.None);
        }
Пример #5
0
        public static async Task <bool> CastStatus(TkClient caster, Npc target, NpcDebuffActivity activity, KeySpell statusEffectSpell)
        {
            if (activity.IsActive)
            {
                return(false);
            }

            if (statusEffectSpell != null && statusEffectSpell.IsOrbSpell) // TODO: Probably remove this delay once you figure out how to read the curse status of NPCs. It will then cast spells too rapidly, but the negative effects of doing so will have been eliminated.
            {
                // Fragile Orb of Scourge has aethers that are too short to appear in the status effects window and therefore require an additional manual delay.
                await caster.Activity.WaitForMeleeCooldown();

                caster.Activity.ResetCommandCooldown();
                await caster.Activity.WaitForMeleeCooldown();

                caster.Activity.ResetCommandCooldown();
                await caster.Activity.WaitForMovementCooldown();

                caster.Activity.ResetCommandCooldown();
            }

            if (!await CastStatus(caster, target.Uid, $"NPC {target.Uid}", statusEffectSpell))
            {
                if (statusEffectSpell != null) // Indicates that the target is off-screen without having to repeat the relatively inefficient IsTargetOffScreen() check
                {
                    caster.Npcs.Remove(target);
                }

                return(false);
            }

            activity.ResetTimer();
            return(true);
        }
Пример #6
0
        /// <summary>
        /// /// Assigns spells and items from the Peasant's spell and item inventories.
        /// </summary>
        /// <param name="self">The game client data for the Peasant.</param>
        public PeasantCommands(PeasantClient self)
        {
            Self          = self;
            _gatewaySpell = self.Spells.KeySpells.Gateway;

            Items    = new PeasantItemCommands(self);
            Movement = new PeasantMovementCommands(self);
        }
        public async Task <bool> Follow(TkClient target, uint distance)
        {
            await _self.Activity.WaitForMovementCooldown();

            var direction = GetFollowDirection(target, distance);

            return(await Move(direction));
        }
Пример #8
0
 /// <summary>
 /// Casts the Poet's full array of debuff cures on a target. Each debuff cure will only be cast if the target
 /// is found to be affected by the debuff. The method will exit and return true as soon as a spell is cast on
 /// on the target. If no spells are cast, the method will return false. The spell priority is Atone, Remove Curse,
 /// Cure Paralysis, Purge, and then Remove Veil.
 /// </summary>
 /// <param name="target">The caster or a multibox member of the caster's group.</param>
 /// <returns>True if a spell was cast; false otherwise.</returns>
 public async Task <bool> Esuna(TkClient target)
 {
     return(await Atone(target) ||
            await RemoveCurse(target) ||
            await CureParalysis(target) ||
            await Purge(target) ||
            await RemoveVeil(target));
 }
Пример #9
0
        /// <summary>
        /// Casts a vita restoration spell on a target if the target has a vita percentage below
        /// than the specified threshold.
        /// </summary>
        /// <param name="target">The caster or a multibox member of the caster's group.</param>
        /// <param name="minimumVitaPercent">The vita percentage threshold below which a target
        /// becomes eligible for the spell.</param>
        /// <returns>True if the spell was cast; false otherwise.</returns>
        public async Task <bool> HealIfBelowVitaPercent(TkClient target, double minimumVitaPercent)
        {
            await _self.Activity.WaitForCommandCooldown();

            var targetVitaPercent = target.Self.Vita.Percent;

            return(await HealIfBelowVitaPercent(target.Self.Uid, target.Self.Name, targetVitaPercent, minimumVitaPercent));
        }
Пример #10
0
        /// <summary>
        /// /// Assigns spells and items from the Warrior's spell and item inventories.
        /// </summary>
        /// <param name="self">The game client data for the Warrior.</param>
        protected PeasantCommands(WarriorClient self)
        {
            Self          = self;
            _gatewaySpell = self.Spells.KeySpells.Gateway;

            Items    = new PeasantItemCommands(self);
            Movement = new PeasantMovementCommands(self);
        }
Пример #11
0
        /// <summary>
        /// Casts a vita restoration spell on a target if the target has a vita deficit greater
        /// than the restoration amount of the spell.
        /// </summary>
        /// <param name="target">The caster or a multibox member of the caster's group.</param>
        /// <returns>True if the spell was cast; false otherwise.</returns>
        public async Task <bool> HealIfEligible(TkClient target)
        {
            await _self.Activity.WaitForCommandCooldown();

            var targetVitaDeficit = target.Self.Vita.Deficit;

            return(await HealIfEligible(target.Self.Uid, target.Self.Name, targetVitaDeficit));
        }
Пример #12
0
        /// <summary>
        /// Assigns debuff and debuff cure spells from a Poet's spell inventory.
        /// </summary>
        /// <param name="self">The game client data for the Poet.</param>
        protected CasterDebuffCommands(PoetClient self)
        {
            _self = self;

            _cureParalysisSpell = self.Spells.KeySpells.CureParalysis;
            CurseSpell          = self.Spells.KeySpells.Curse;
            _purgeSpell         = self.Spells.KeySpells.Purge;
            _removeCurseSpell   = self.Spells.KeySpells.RemoveCurse;
        }
Пример #13
0
        /// <summary>
        /// Transfers mana from the caster to the target. Inspires will only be performed if the
        /// caster possesses the Invoke spell and the target has a lower current mana percentage
        /// than the specified ceiling.
        /// </summary>
        /// <param name="target">The caster or a multibox member of the caster's group.</param>
        /// <param name="manaPercentCeiling">The mana percentage threshold below which a target
        /// is eligible to be Inspired.</param>
        /// <returns>True if the spell was cast; false otherwise.</returns>
        public async Task <bool> Inspire(TkClient target, double manaPercentCeiling = DefaultInspireManaPercentCeiling)
        {
            if (target.Self.Mana.Percent > manaPercentCeiling)
            {
                return(false);
            }

            return(await Inspire(target.Self.Name, target.Self.Uid));
        }
Пример #14
0
 /// <summary>
 /// Initializes a Rogue's status data.
 /// </summary>
 /// <param name="self">All game client data for the Rogue.</param>
 public RogueStatus(TkClient self) : base(self.Activity)
 {
     DesperateAttack = new BuffStatus(Activity, Rogue.DesperateAttack);
     Invisible       = new InvisibleStatus(Activity, Rogue.Invisible);
     LethalStrike    = new BuffStatus(Activity, Rogue.LethalStrike);
     Fury            = new BuffStatus(Activity, Rogue.Fury);
     Rage            = new RageStatus(self, Rogue.Cunning);
     ShadowFigure    = new BuffStatus(Activity, Rogue.ShadowFigure);
 }
Пример #15
0
        public static async Task <bool> CastStatus(TkClient caster, GroupMember target, GroupMemberBuffActivity activity, KeySpell statusEffectSpell)
        {
            if (activity.IsActive || !await CastStatus(caster, target.Uid, target.Name, statusEffectSpell))
            {
                return(false);
            }

            activity.ResetTimer();
            return(true);
        }
Пример #16
0
        public static async Task <bool> CastStatus(TkClient caster, TkClient target, BuffStatus status, KeySpell statusEffectSpell)
        {
            if (status.IsActive || !await CastStatus(caster, target.Self.Uid, target.Self.Name, statusEffectSpell))
            {
                return(false);
            }

            status.ResetStatusCooldown();
            return(true);
        }
Пример #17
0
        // ReSharper disable once UnusedMember.Local
        private static async Task RestoreManaIfBelowPercent(TkClient itemUser, double minimumManaPercent, Restoration manaRestorationItem)
        {
            await itemUser.Activity.WaitForCommandCooldown();

            var currentManaPercent = itemUser.Self.Mana.Percent;

            if (currentManaPercent < minimumManaPercent)
            {
                await UseManaRestorationItem(itemUser, manaRestorationItem);
            }
        }
Пример #18
0
        private static async Task RestoreManaForSpell(TkClient itemUser, KeySpell spell, Restoration manaRestorationItem)
        {
            await itemUser.Activity.WaitForCommandCooldown();

            var currentMana = (int)itemUser.Self.Mana.Current;

            if (currentMana < spell.Cost)
            {
                await UseManaRestorationItem(itemUser, manaRestorationItem, spell.Cost - currentMana);
            }
        }
Пример #19
0
        private static async Task UseManaRestorationItem(TkClient itemUser, Restoration manaRestorationItem, int minimumRestoration = 1)
        {
            var requiredUsages = (int)Math.Ceiling((float)minimumRestoration / manaRestorationItem.RestoreAmount);

            itemUser.IncrementManaRestorationItemUsageCount(requiredUsages);

            if (!await UseItem(itemUser, manaRestorationItem, requiredUsages))
            {
                Log.Error($"{itemUser.Self.Name} does not have any mana restoration items.");
            }
        }
Пример #20
0
        /// <summary>
        /// Terminates the bot with experience and mana restoration item usage reports.
        /// </summary>
        /// <param name="client">The TkClient controlled by the bot.</param>
        public static void Terminate(TkClient client)
        {
            Log.Information(client.GetExpReport());
            Log.Information(client.GetManaRestorationItemUsageReport());

            Console.WriteLine();
            Console.WriteLine(@"Press ""Esc"" to exit...");
            while (Console.ReadKey(true).Key != ConsoleKey.Escape)
            {
            }
            Environment.Exit(0);
        }
Пример #21
0
        /// <summary>
        /// Initializes the key spell properties used to track the status of Rage/Cunning.
        /// </summary>
        /// <param name="self">All game client data for the Rogue or Warrior.</param>
        /// <param name="rageLevels">A list of each key spell for each level of Rage/Cunning.</param>
        public RageStatus(TkClient self, BuffKeySpell[] rageLevels) : base(self.Activity, rageLevels)
        {
            _self             = self;
            _rageLevels       = rageLevels;
            _maxRageLevel     = GetMaxRageLevel();
            _currentRageLevel = GetCurrentRageLevel();

            Log.Debug($"{self.Self.Name}'s starting rage level is {_currentRageLevel}.");

            _latestDurationInactivity = DateTime.Now.AddMilliseconds(-self.Activity.DefaultCommandCooldown);
            _durationInactiveCount    = RequiredDurationInactiveCount;
        }
Пример #22
0
        /// <summary>
        /// Assigns mana restoration spells from a Poet's spell inventory.
        /// </summary>
        /// <param name="self">The game client data for the Poet.</param>
        protected CasterManaCommands(PoetClient self)
        {
            Self = self;

            InvokeSpell  = self.Spells.KeySpells.Invoke;
            InvokeStatus = self.Status.Invoke;

            if (InvokeSpell == null)
            {
                Log.Warning($"{self.Self.Name} does not have an Invoke spell. Mana restoration item consumption will be very high.");
            }
        }
Пример #23
0
        // ReSharper disable once UnusedMember.Local
        private static async Task RestoreManaIfEligible(TkClient itemUser, Restoration manaRestorationItem)
        {
            await itemUser.Activity.WaitForCommandCooldown();

            var currentManaDeficit = itemUser.Self.Mana.Deficit;

            if (currentManaDeficit > manaRestorationItem.RestoreAmount)
            {
                var usages = (int)(currentManaDeficit / manaRestorationItem.RestoreAmount);
                await UseManaRestorationItem(itemUser, manaRestorationItem, usages);
            }
        }
Пример #24
0
 /// <summary>
 /// Initializes a Warrior's status data.
 /// </summary>
 /// <param name="self">All game client data for the Warrior.</param>
 public WarriorStatus(TkClient self) : base(self.Activity)
 {
     Backstab  = new BuffStatus(Activity, Warrior.Backstab);
     Berserk   = new BuffStatus(Activity, Warrior.Berserk);
     Blessing  = new BuffStatus(Activity, Warrior.Blessing);
     Flank     = new BuffStatus(Activity, Warrior.Flank);
     Fury      = new BuffStatus(Activity, Warrior.Fury);
     Potence   = new BuffStatus(Activity, Warrior.Potence);
     Rage      = new RageStatus(self, Warrior.Rage);
     SpotTraps = new BuffStatus(Activity, Warrior.SpotTraps);
     Whirlwind = new BuffStatus(Activity, Warrior.Whirlwind);
 }
Пример #25
0
        // ReSharper disable once UnusedMember.Local
        private static async Task <bool> RestoreManaIfEligible(TkClient itemUser, Restoration manaRestorationItem)
        {
            await itemUser.Activity.WaitForCommandCooldown();

            var currentManaDeficit = itemUser.Self.Mana.Deficit;

            if (currentManaDeficit > manaRestorationItem.RestoreAmount)
            {
                return(await UseManaRestorationItem(itemUser, manaRestorationItem));
            }

            return(false);
        }
Пример #26
0
        public static async Task <bool> CastInvisibleSpell(
            TkClient caster,
            KeySpell spell,
            InvisibleStatus status)
        {
            var didCastSpell = await CastSpell(caster, spell, true);

            if (didCastSpell)
            {
                status.ResetStatusCooldown();
            }

            return(didCastSpell);
        }
Пример #27
0
        public static async Task <bool> CastTargetableSpell(
            TkClient caster,
            KeySpell spell,
            uint targetUid,
            string targetName,
            bool isLowCostSpell = false)
        {
            if (spell == null || await caster.IsTargetOffScreen(targetUid, spell))
            {
                return(false);
            }

            return(await CastSpell(caster, spell, isLowCostSpell, targetName));
        }
Пример #28
0
        public static async Task <bool> CastDebuffCure(TkClient caster, TkClient target, DebuffStatus status, KeySpell debuffCureSpell)
        {
            if (!status.IsActive)
            {
                return(false);
            }

            if (!await CastStatus(caster, target.Self.Uid, target.Self.Name, debuffCureSpell)) // Do not combine with the IsActive condition
            {
                return(false);
            }

            status.ResetStatusCooldown();
            return(true);
        }
Пример #29
0
        /// <summary>
        /// Initializes a Rogue's status data.
        /// </summary>
        /// <param name="self">All game client data for the Rogue.</param>
        public RogueStatus(TkClient self) : base(self.Activity)
        {
            var mightBuffs = new List <BuffKeySpell>();

            mightBuffs.AddRange(Caster.Valor);
            mightBuffs.AddRange(Rogue.Might);

            DesperateAttack = new BuffStatus(Activity, Rogue.DesperateAttack);
            Invisible       = new InvisibleStatus(Activity, Rogue.Invisible);
            LethalStrike    = new BuffStatus(Activity, Rogue.LethalStrike);
            Fury            = new BuffStatus(Activity, Rogue.Fury);
            Might           = new BuffStatus(Activity, mightBuffs);
            Rage            = new RageStatus(self, Rogue.Cunning);
            ShadowFigure    = new BuffStatus(Activity, Rogue.ShadowFigure);
        }
Пример #30
0
        public static async Task <bool> CastDebuffCure(TkClient caster, GroupMember target, GroupMemberDebuffActivity activity, KeySpell debuffCureSpell)
        {
            if (!activity.IsActive)
            {
                return(false);
            }

            if (!await CastStatus(caster, target.Uid, target.Name, debuffCureSpell)) // Do not combine with the IsActive condition
            {
                return(false);
            }

            activity.IsActive = false;
            return(true);
        }