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; }
/// <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(); } }
public EventDispatcher(AsyncEvent<Message, EventData> e, EventData eventData, Message senderMessage) { AsyncEvent = e; EventData = eventData; SenderMessage = senderMessage; }
public virtual async Task<bool> OnLeavingGame(Message sender, EventData e) { return false; }
public virtual async Task<bool> OnUsedPortal(Message sender, EventData e) { return false; }
public virtual async Task<bool> OnPlayerDied(Message sender, EventData e) { return false; }
public virtual async Task<bool> OnEngagedElite(Message sender, EventData e) { return false; }
public override async Task<bool> OnGemUpgraded(Message sender, EventData e) { Log.Info("we are in the function of OnGemUpgraded"); return false; }
private static void Queue(AsyncEvent<Message, EventData> e, EventData data, Message m) { if (e != null) EventQueue.Enqueue(new EventDispatcher(e, data, m)); }
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; }
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; } }
/// <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; }
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; }
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; }
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; }
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; }
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; }
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(); }
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; }
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(); }
public virtual async Task<bool> OnWorldAreaChanged(Message sender, EventData e) { return false; }
/// <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; }
public virtual async Task<bool> OnInTrouble(Message sender, EventData e) { return false; }
public static Message GetUpdatedMessage(Message message) { return CurrentParty.FirstOrDefault(p => p.HeroId == message.HeroId); }
public virtual async Task<bool> OnInviteRequest(Message sender, EventData e) { return false; }
public static Vector3 GetUpdatedPosition(Message message) { var partyMember = GetUpdatedMessage(message); return partyMember != null ? partyMember.Position : Vector3.Zero; }
public virtual async Task<bool> OnGemUpgraded(Message sender, EventData e) { return false; }
/// <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; } }
//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; }
public static DiaPlayer GetPlayerActor(Message player) { var acdId = GetAcdIdByHeroId(player.HeroId); return acdId > 0 ? Players.FirstOrDefault(p => p.ACDId == acdId) : null; }