예제 #1
0
 public override async Task<bool> OnInviteRequest(Message sender, EventData e)
 {
     if (e.IsFollowerEvent)
     {
         Log.Info("My minion {0} is requesting a party invite!", sender.HeroName);
         await Party.InviteFollower(sender);
     }
     return true;
 }
예제 #2
0
        /// <summary>
        /// Object used to send information between bots.
        /// This is used in the communication thread and DB doesn't play nicely when multiple threads access D3 memory.
        /// Must be be created from non-memory accessing properties, which is why it's populated from the Player object.
        /// </summary>
        public static Message GetMessage()
        {
            try
            {
                Message m;

                if (!ZetaDia.Service.IsValid || !ZetaDia.Service.Platform.IsConnected)
                {
                    m = new Message
                    {
                        IsInGame = false,
                        Events = EventManager.Events.ToList()
                    };
                    return m;
                }

                if (ZetaDia.Me == null)
                {
                    m = new Message
                    {
                        Index = Player.Index,
                        IsInGame = false,
                        LastUpdated = DateTime.UtcNow,
                        IsInParty = Player.IsInParty,
                        OwnerId = Player.BattleTagHash,
                        NumPartymembers = Player.NumPlayersInParty,
                        Events = EventManager.Events.ToList(),
                        BNetPartyMembers = ZetaDia.Service.Party.NumPartyMembers,
                        IsServer = Service.ConnectionMode == ConnectionMode.Server,
                        IsClient = Service.ConnectionMode == ConnectionMode.Client,
                        IsRequestingLeader = AutoFollow.CurrentBehavior.Category == BehaviorCategory.Leader,
                        BehaviorType = AutoFollow.CurrentBehavior.Type,
                        IsQuickJoinEnabled = Player.IsQuickJoinEnabled,
                        BattleTagEncrypted = GetMyEncryptedBattleTag(),
                        HeroName = Player.HeroName,
                        HeroId = Player.HeroId,
                        ActorClass = Player.ActorClass,
                        IsLoadingWorld = Player.IsLoadingWorld,
                    };
                }
                else if (ZetaDia.IsInGame && !ZetaDia.IsLoadingWorld && ZetaDia.Me.IsValid)
                {
                    m = new Message
                    {
                        Index = Player.Index,
                        LastUpdated = DateTime.UtcNow,
                        IsInGame = Player.IsInGame,
                        OwnerId = Player.BattleTagHash,
                        IsInParty = Player.IsInParty,
                        NumPartymembers = Player.NumPlayersInParty,
                        IsLoadingWorld = Player.IsLoadingWorld,
                        ActorClass = Player.ActorClass,
                        ActorSNO = Player.ActorId,
                        GameId = Player.CurrentGameId,
                        HitpointsCurrent = Player.HitpointsCurrent,
                        HitpointsMaxTotal = Player.HitpointsMaxTotal,
                        LevelAreaId = Player.LevelAreaId,
                        IsInTown = Player.LevelAreaId != 55313 && Player.IsInTown, // A2 Caldeum Bazaar
                        Position = Player.Position,
                        ProfilePosition = Player.GetProfilePosition(),
                        ProfileActorSno = Player.ProfileActorSno,
                        ProfilePathPrecision = Player.ProfilePathPrecision,
                        ProfileTagName = Player.GetProfileTagname(),
                        IsInCombat = Player.IsInCombat,
                        WorldSnoId = Player.CurrentWorldSnoId,
                        IsVendoring = BrainBehavior.IsVendoring,
                        BattleTagEncrypted = GetMyEncryptedBattleTag(),
                        HeroName = Player.HeroName,
                        HeroId = Player.HeroId,
                        Events = EventManager.Events.Take(25).ToList(),
                        CurrentTarget = Player.Target,
                        IsInRift = Player.IsInRift,
                        IsInGreaterRift = Player.IsIsInGreaterRift,
                        IsParticipatingInGreaterRift = Player.IsParticipatingInGreaterRift,
                        FreeBackPackSlots = Player.FreeBackPackSlots,
                        JewelUpgradesleft = Player.JewelUpgradesleft,
                        IsDead = Player.IsDead,
                        BNetPartyMembers = ZetaDia.Service.Party.NumPartyMembers,
                        IsServer = Service.ConnectionMode == ConnectionMode.Server,
                        IsClient = Service.ConnectionMode == ConnectionMode.Client,
                        PreviousWorldSnoId = ChangeMonitor.LastWorldId,
                        LastPositionInPreviousWorld = ChangeMonitor.LastWorldPosition,
                        IsRequestingLeader = AutoFollow.CurrentBehavior.Category == BehaviorCategory.Leader,
                        IsQuickJoinEnabled = Player.IsQuickJoinEnabled,
                        LastPortalUsed = Player.LastPortalUsed,
                        BehaviorType = AutoFollow.CurrentBehavior.Type,
                        IsInBossEncounter = Player.IsInBossEncounter,
                    };
                }
                else if (ZetaDia.IsInGame && ZetaDia.IsLoadingWorld)
                {
                    m = new Message
                    {
                        Index = Player.Index,
                        IsInGame = true,
                        IsLoadingWorld = true,
                        GameId = Player.CurrentGameId,
                        OwnerId = Player.BattleTagHash,
                        HeroName = Player.HeroName,
                        HeroId = Player.HeroId,
                        IsInTown = false,
                        WorldSnoId = -1,
                        LevelAreaId = -1,
                        LastUpdated = DateTime.UtcNow,
                        IsInParty = Player.IsInParty,
                        NumPartymembers = Player.NumPlayersInParty,
                        Events = EventManager.Events.ToList(),
                        CurrentTarget = null,
                        BNetPartyMembers = ZetaDia.Service.Party.NumPartyMembers,
                        IsServer = Service.ConnectionMode == ConnectionMode.Server,
                        IsClient = Service.ConnectionMode == ConnectionMode.Client,
                        IsQuickJoinEnabled = Player.IsQuickJoinEnabled,
                        BehaviorType = AutoFollow.CurrentBehavior.Type,
                        BattleTagEncrypted = GetMyEncryptedBattleTag(),
                        IsInRift = RiftHelper.IsInRift
                    };
                }
                else
                {
                    m = new Message
                    {
                        Index = Player.Index,
                        IsInGame = false,
                        IsInTown = false,
                        OwnerId = Player.BattleTagHash,
                        WorldSnoId = -1,
                        LastUpdated = DateTime.UtcNow,
                        IsInParty = Player.IsInParty,
                        NumPartymembers = Player.NumPlayersInParty,
                        Events = EventManager.Events.ToList(),
                        CurrentTarget = null,
                        BNetPartyMembers = ZetaDia.Service.Party.NumPartyMembers,
                        IsServer = Service.ConnectionMode == ConnectionMode.Server,
                        IsClient = Service.ConnectionMode == ConnectionMode.Client,
                        IsQuickJoinEnabled = Player.IsQuickJoinEnabled,
                        BehaviorType = AutoFollow.CurrentBehavior.Type,
                        BattleTagEncrypted = GetMyEncryptedBattleTag(),
                        HeroName = Player.HeroName,
                        HeroId = Player.HeroId,
                        IsLoadingWorld = Player.IsLoadingWorld,
                    };
                }

                return m;
            }
            catch (Exception ex)
            {
                Log.Info("Exception in GetMessage() {0}", ex);
                return new Message();
            }
        }
예제 #3
0
 public EventDispatcher(AsyncEvent<Message, EventData> e, EventData eventData, Message senderMessage)
 {
     AsyncEvent = e;
     EventData = eventData;
     SenderMessage = senderMessage;
 }
예제 #4
0
 public virtual async Task<bool> OnLeavingGame(Message sender, EventData e)
 {
     return false;
 }
예제 #5
0
 public virtual async Task<bool> OnUsedPortal(Message sender, EventData e)
 {
     return false;
 }
예제 #6
0
 public virtual async Task<bool> OnPlayerDied(Message sender, EventData e)
 {
     return false;
 }
예제 #7
0
 public virtual async Task<bool> OnEngagedElite(Message sender, EventData e)
 {            
     return false;
 }
예제 #8
0
 public override async Task<bool> OnGemUpgraded(Message sender, EventData e)
 {
     Log.Info("we are in the function of OnGemUpgraded");
     return false;
 }
예제 #9
0
 private static void Queue(AsyncEvent<Message, EventData> e, EventData data, Message m)
 {
     if (e != null)
         EventQueue.Enqueue(new EventDispatcher(e, data, m));
 }
예제 #10
0
 private static bool TryGetMessageForId(EventData e, out Message m)
 {
     if (e.OwnerId == Player.BattleTagHash)
     {
         m = Player.CurrentMessage;
     }
     else if (e.OwnerId == AutoFollow.CurrentLeader.OwnerId)
     {
         m = AutoFollow.CurrentLeader;
     }
     else
     {
         m = AutoFollow.CurrentParty.FirstOrDefault(message => message.OwnerId == e.OwnerId);                
     }            
     return m != null;
 }
예제 #11
0
 private static void FireEventByType(EventData e, Message m)
 {
     // These events are async so we can't just fire them here.
     // They need to be awaited within a bot hook.
     switch (e.Type)
     {
         case EventType.GreaterRiftStarted:
             Queue(GreaterRiftStarted, e, m);
             break;
         case EventType.NormalRiftStarted:
             Queue(NormalRiftStarted, e, m);
             break;
         case EventType.InTrouble:
             Queue(InTrouble, e, m);
             break;
         case EventType.JoinedParty:
             Queue(JoinedParty, e, m);
             break;
         case EventType.LeftParty:
             Queue(LeftParty, e, m);
             break;
         case EventType.LeftGame:
             Queue(LeftGame, e, m);
             break;
         case EventType.JoinedGame:
             Queue(JoinedGame, e, m);
             break;
         case EventType.LevelAreaChanged:
             Queue(LevelAreaChanged, e, m);
             break;
         case EventType.WorldAreaChanged:
             Queue(WorldAreaChanged, e, m);
             break;
         case EventType.ObjectiveFound:
             Queue(ObjectiveFound, e, m);
             break;
         case EventType.EngagedElite:
             Queue(EngagedElite, e, m);
             break;
         case EventType.UsedPortal:
             Queue(UsedPortal, e, m);
             break;
         case EventType.Died:
             Queue(Died, e, m);
             break;
         case EventType.InviteRequest:
             Queue(InviteRequest, e, m);
             break;
         case EventType.LeavingGame:
             Queue(LeavingGame, e, m);
             break;
         case EventType.GoingToTown:
             Queue(GoingToTown, e, m);
             break;
         case EventType.StartingTownRun:
             Queue(StartingTownRun, e, m);
             break;
         case EventType.GemUpgraded:
             Queue(GemUpgraded, e, m);
             break;
     }
 }
예제 #12
0
        /// <summary>
        /// Move to another bot
        /// </summary>
        /// <param name="player">a player to move to</param>
        /// <param name="range">the closeness required</param>
        public static async Task<bool> MoveToPlayer(Message player, float range)
        {
            if (!ZetaDia.IsInGame || !player.IsInSameGame || !player.IsInSameWorld || player.IsInGreaterRift)
                return false;

            if (player.Distance > range)
            {
                Log.Verbose("Moving to Player {0} CurrentDistance={1} DistanceRequired={2} ",
                    player.HeroName, player.Distance, range);

                await MoveTo(() => AutoFollow.GetUpdatedMessage(player), player.HeroName, range, t => !player.IsInSameWorld || t.Distance > Settings.Coordination.TeleportDistance);
                return true;
            }

            Log.Debug("Player {0} is close enough CurrentDistance={1} DistanceRequired={2} ",
                player.HeroName, player.Distance, range);

            return true;
        }
예제 #13
0
 public override async Task<bool> OnInviteRequest(Message sender, EventData e)
 {
     if (e.IsFollowerEvent)
     {
         Log.Info("My minion {0} is requesting a party invite!", sender.HeroName);
         await Party.InviteFollower(sender);
         
         if(DateTime.UtcNow.Subtract(Coordination.StartAllowedTime).TotalSeconds <= 30)
             Coordination.StartAllowedTime = DateTime.UtcNow.Add(TimeSpan.FromSeconds(30));
     }
     return true;
 }
예제 #14
0
 public override async Task<bool> OnEngagedElite(Message sender, EventData e)
 {
     if (e.IsFollowerEvent)
     {
         Log.Info("My minion {0} is attacking a Unique! {1} at {2} DistanceFromMe={3}",
             sender.HeroName, sender.CurrentTarget.Name, sender.Position, ZetaDia.Me.Position.Distance(sender.CurrentTarget.Position));
     }
     return true;
 }
예제 #15
0
 public override async Task<bool> OnInTrouble(Message sender, EventData e)
 {
     if (e.IsFollowerEvent && !Data.Monsters.Any(m => m.Distance <= 80f) && sender.IsInSameWorld)
     {
         Log.Info("My minion needs help! Teleporting to {0}. Distance={1}", sender.HeroName, sender.Distance);
         await Coordination.TeleportToPlayer(sender);
     }
     return false;
 }
예제 #16
0
 public override async Task<bool> OnWorldAreaChanged(Message sender, EventData e)
 {
     if (e.IsLeaderEvent)
     {
         Log.Info("Leader ({0}) changed world from {1} to {2}", 
             sender.HeroName, e.OldValue, e.NewValue);
     }
     return false;
 }
예제 #17
0
        public override async Task<bool> OnLeavingGame(Message sender, EventData e)
        {
            if (e.IsLeaderEvent && Player.IsInGame)
            {
                Log.Info("Leader ({0}) is leaving game, lets leave too!",
                    sender.HeroName, e.OldValue, e.NewValue);

                await Party.LeaveGame();
                await Coroutine.Sleep(1000);
                return true;
            }
            return false;
        }
예제 #18
0
 public static void UpdateOutOfGame()
 {
     var hero = ZetaDia.Service.Hero;
     HeroId = hero.HeroId;
     HeroName = Common.CleanString(hero.Name);
     IsLoadingWorld = ZetaDia.IsLoadingWorld || ZetaDia.IsPlayingCutscene;
     ActorClass = ZetaDia.Service.Hero.Class;
     IsInGame = false;
     CurrentMessage = Message.GetMessage();            
 }
예제 #19
0
 public override async Task<bool> OnEngagedElite(Message sender, EventData e)
 {
     if (e.IsLeaderEvent)
     {
         Log.Info("Leader ({0}) is attacking a Unique! {1} at {2} DistanceFromMe={3}",
             Common.CleanString(sender.HeroName),
             Common.CleanString(sender.CurrentTarget.Name),
             sender.Position.ToString(),
             ZetaDia.Me.Position.Distance(sender.CurrentTarget.Position));
     }
     return false;
 }
예제 #20
0
        public static void Update()
        {
            if (DateTime.UtcNow.Subtract(LastUpdate).TotalMilliseconds < 25)
                return;

            var shouldUpdate = ZetaDia.IsInGame && !ZetaDia.IsLoadingWorld && ZetaDia.Me != null;

            if (ZetaDia.Me != null && (!ZetaDia.Me.IsValid || !ZetaDia.Me.CommonData.IsValid || ZetaDia.Me.CommonData.IsDisposed))
                shouldUpdate = false;

            if (!ZetaDia.IsInGame && (ZetaDia.PlayerData == null || !ZetaDia.PlayerData.IsValid))
                shouldUpdate = false;

            if (shouldUpdate)
            {
                try
                {
                    Index = ZetaDia.PlayerData.Index;
                    RActorId = ZetaDia.Me.RActorId;
                    LastUpdate = DateTime.UtcNow;
                    IsInGame = ZetaDia.IsInGame;
                    AcdId = ZetaDia.Me.ACDId;
                    HitpointsCurrent = ZetaDia.Me.HitpointsCurrent;
                    HitpointsMaxTotal = ZetaDia.Me.HitpointsMaxTotal;
                    HitpointsCurrentPct = HitpointsMaxTotal > 0 ? ZetaDia.Me.HitpointsCurrent / ZetaDia.Me.HitpointsMaxTotal : 0;
                    Position = ZetaDia.Me.Position;
                    CurrentLevelAreaId = LevelAreaId;
                    CurrentWorldSnoId = ZetaDia.CurrentWorldSnoId;
                    CurrentDynamicWorldId = ZetaDia.WorldId;
                    IsInTown = ZetaDia.IsInTown;
                    IsVendoring = BrainBehavior.IsVendoring;
                    ActorId = ZetaDia.Me.ActorSnoId;
                    ActorClass = ZetaDia.Service.Hero.Class;
                    HeroName = Common.CleanString(ZetaDia.Service.Hero.Name);
                    HeroId = ZetaDia.PlayerData.HeroId;
                    CurrentGameId = ZetaDia.Service.CurrentGameId;
                    IsInCombat = GetIsInCombat();
                    GameId = ZetaDia.Service.CurrentGameId;
                    IsLoadingWorld = ZetaDia.IsLoadingWorld || ZetaDia.IsPlayingCutscene;
                    IsQuickJoinEnabled = ZetaDia.SocialPreferences.QuickJoinEnabled;
                    IsInRift = RiftHelper.IsInRift;
                    IsIsInGreaterRift = RiftHelper.IsInGreaterRift;
                    IsParticipatingInGreaterRift = !ZetaDia.IsInTown && ZetaDia.Me.IsParticipatingInTieredLootRun;
                    IsTryingToCastPortalSpell = DateTime.UtcNow.Subtract(ChangeMonitor.LastCastPortalSpell).TotalSeconds < 10;
                    IsIdle = ChangeMonitor.IsIdle;
                    IsCasting = ZetaDia.Me.LoopingAnimationEndTime > 0;
                    IsCastingTownPortal = IsCasting && DateTime.UtcNow.Subtract(ChangeMonitor.LastCastTownPortal).TotalSeconds < 5;
                    Target = GetCurrentTarget();
                    ProfilePosition = GetProfilePosition();
                    ProfileActorSno = GetProfileActorSNO();
                    ProfilePathPrecision = GetProfilePathPrecision();
                    ProfileTagName = GetProfileTagname();
                    IsInBossEncounter = ZetaDia.Me.IsInBossEncounter;
                    JewelUpgradesleft = ZetaDia.Me.JewelUpgradesLeft;
                    FreeBackPackSlots = ZetaDia.Me.Inventory.NumFreeBackpackSlots;
                    IsDead = ZetaDia.Me.IsDead;
                    LastCastTownPortal = ChangeMonitor.LastCastTownPortal;
                }
                catch (Exception ex)
                {
                    Log.Verbose("Exception {0}", ex);
                }
            }

            CurrentMessage = Message.GetMessage();
        }
예제 #21
0
 public virtual async Task<bool> OnWorldAreaChanged(Message sender, EventData e)
 {
     return false;
 }
예제 #22
0
        /// <summary>
        /// Invites another bot to the current party.
        /// </summary>
        /// <param name="follower">the player to be invited</param>
        public static async Task<bool> InviteFollower(Message follower)
        {
            if (DateTime.UtcNow.Subtract(_lastInviteAttempt).TotalSeconds < 1)
                return false;

            if (ZetaDia.Service.Party.CurrentPartyLockReasonFlags != PartyLockReasonFlag.None)
            {
                Log.Info("Party is locked, can't invite right now");
                return false;
            }

            if (AutoFollow.NumberOfConnectedBots == 0)
                return false;

            if (!GameUI.FriendsListContent.IsVisible)
            {
                Log.Info("Opening Social Panel");
                GameUI.SocialFlyoutButton.Click();
                await Coroutine.Sleep(250);
            }

            var stackPanel = GameUI.SocialFriendsListStackPanel;
            var stackPanelItems = stackPanel.GetStackPanelItems();
            if (!stackPanelItems.Any())
            {
                Log.Info("No friends or local players were found!");
                return false;
            }

            foreach (var item in stackPanelItems)
            {
                var name = Common.CleanString(item.TextElement.Text);
                var isBattleTag = Message.IsBattleTag(name, follower.BattleTagEncrypted);

                if (isBattleTag)
                {
                    Log.Info("Found follower on friends list!");
                    var inviteButton = item.TextElement.GetSiblingByName("PartyInviteButton");
                    inviteButton.Click();
                    _lastInviteAttempt = DateTime.UtcNow;

                    await Coroutine.Sleep(250);

                    if (GameUI.FriendsListContent.IsVisible)
                    {
                        Log.Info("Closing Social Panel");
                        GameUI.SocialFlyoutButton.Click();
                        await Coroutine.Sleep(250);
                    }

                    return true;
                }
            }

            Log.Info("Unable to find invitation requester on friends list!");
            _lastInviteAttempt = DateTime.UtcNow;
            return false;
        }
예제 #23
0
 public virtual async Task<bool> OnInTrouble(Message sender, EventData e)
 {
     return false;
 }
예제 #24
0
 public static Message GetUpdatedMessage(Message message)
 {
     return CurrentParty.FirstOrDefault(p => p.HeroId == message.HeroId);
 }
예제 #25
0
 public virtual async Task<bool> OnInviteRequest(Message sender, EventData e)
 {
     return false;
 }
예제 #26
0
 public static Vector3 GetUpdatedPosition(Message message)
 {
     var partyMember = GetUpdatedMessage(message);
     return partyMember != null ? partyMember.Position : Vector3.Zero;
 }
예제 #27
0
 public virtual async Task<bool> OnGemUpgraded(Message sender, EventData e)
 {
     return false;
 }
예제 #28
0
 /// <summary>
 /// Turn combat (Trinity) on and off while the follower is far away from the leader.   
 /// </summary>
 public void StayCloseToPlayer(Message player)
 {
     if (player.Distance > Math.Max(Settings.Coordination.FollowDistance + 15f, 40f) && !Player.IsInTown && 
         !Navigation.IsBlocked && !Navigator.StuckHandler.IsStuck && Player.HitpointsCurrentPct > 0.7 && !Targetting.RoutineWantsToAttackGoblin())
     {
         Targetting.State = CombatState.Pulsing;
     }
     else
     {
         Targetting.State = CombatState.Enabled;
     }
 }
예제 #29
0
        //public async Task<bool> AttackWithPlayer(Message player)
        //{
        //    if (player.IsInCombat && player.CurrentTarget != null && player.Distance < 150f && 
        //        player.CurrentTarget.Distance < 150f && ZetaDia.Me.IsInCombat && Data.Monsters.Count(m => m.Distance <= 30f) < 10)
        //    {
        //        Log.Info("Moving to attack {0}'s target - {1} Distance={2}", 
        //            player.HeroName, player.CurrentTarget.Name, player.CurrentTarget.Distance);

        //        if(await Movement.MoveTo(() => AutoFollow.GetUpdatedMessage(player).CurrentTarget, player.CurrentTarget.Name, 10f, () => ZetaDia.Me.IsInCombat || !ZetaDia.Me.Movement.IsMoving))
        //            return true;                
        //    }
        //    return false;
        //}

        public override async Task<bool> OnUsedPortal(Message sender, EventData e)
        {
            if (Player.IsIsInGreaterRift)
            {
                return false;
            }
            if (e.IsLeaderEvent)
            {
                var portal = e.NewValue as Interactable;
                if (portal == null)
                {
                    Log.Debug("The portal details weren't provided in event. :(");
                    return false;
                }

                if (portal.WorldSnoId != Player.CurrentWorldSnoId)
                {
                    Log.Debug("Portal is in a different world.");
                    return false;
                }

                Log.Info("Leader ({0}) used a portal ({1})", sender.HeroName, portal.InternalName);
                await Coroutine.Sleep(2000);

                if (AutoFollow.CurrentLeader.IsInSameWorld)
                {
                    Log.Debug("Leader is in same world.");
                    return false;
                }
                
                var positionMatch = Data.Portals.FirstOrDefault(p => (int)p.Position.X == (int)portal.ActorPosition.X && (int)p.Position.Y == (int)portal.ActorPosition.Y);
                if (positionMatch != null)
                {
                    Log.Info("Portal found by position, lets use it!");
                    await Movement.MoveToAndInteract(positionMatch);
                    return true;
                }

                var nameMatch = Data.Portals.FirstOrDefault(p => p.CommonData.Name.Contains(portal.BaseInternalName));
                if (nameMatch != null)
                {
                    Log.Info("Portal found by name, lets use it!");
                    await Movement.MoveToAndInteract(nameMatch);
                    return true;
                }

                var closestPortal = Data.Portals.OrderBy(p => p.Position.Distance(Player.Position)).FirstOrDefault();
                if (closestPortal != null)
                {
                    Log.Info("Trying our luck with this nearby portal...");
                    await Movement.MoveToAndInteract(closestPortal);
                    return true;
                }

                Log.Info("Unable to find the portal we need to clicky :(");
            }
            return false;
        }
예제 #30
0
 public static DiaPlayer GetPlayerActor(Message player)
 {
     var acdId = GetAcdIdByHeroId(player.HeroId);
     return acdId > 0 ? Players.FirstOrDefault(p => p.ACDId == acdId) : null;
 }