Пример #1
0
 /// <summary>
 /// Generates an SHA1 hash of a particular GilesObject
 /// </summary>
 /// <param name="obj"></param>
 /// <returns></returns>
 public static string GenerateObjecthash(GilesObject obj)
 {
     using (MD5 md5 = MD5.Create())
     {
         string objHashBase = String.Format("{0}{1}{2}{3}", obj.ActorSNO, obj.Position, obj.Type, GilesTrinity.CurrentWorldDynamicId);
         string objHash     = GetMd5Hash(md5, objHashBase);
         return(objHash);
     }
 }
Пример #2
0
        // For cloning the object (and not simply referencing it)
        public GilesObject Clone()
        {
            GilesObject newGilesObject = new GilesObject(Unit)
            {
                Position          = Position,
                Type              = Type,
                Weight            = Weight,
                CentreDistance    = CentreDistance,
                RadiusDistance    = RadiusDistance,
                InternalName      = InternalName,
                ACDGuid           = ACDGuid,
                RActorGuid        = RActorGuid,
                DynamicID         = DynamicID,
                BalanceID         = BalanceID,
                ActorSNO          = ActorSNO,
                ItemLevel         = ItemLevel,
                GoldAmount        = GoldAmount,
                OneHanded         = OneHanded,
                TwoHanded         = TwoHanded,
                ItemQuality       = ItemQuality,
                DBItemBaseType    = DBItemBaseType,
                DBItemType        = DBItemType,
                FollowerType      = FollowerType,
                GilesItemType     = GilesItemType,
                IsElite           = IsElite,
                IsRare            = IsRare,
                IsUnique          = IsUnique,
                IsMinion          = IsMinion,
                IsTreasureGoblin  = IsTreasureGoblin,
                IsEliteRareUnique = IsEliteRareUnique,
                IsBoss            = IsBoss,
                IsAttackable      = IsAttackable,
                HitPointsPct      = HitPointsPct,
                HitPoints         = HitPoints,
                Radius            = Radius,
                MonsterStyle      = MonsterStyle,
                ForceLeapAgainst  = ForceLeapAgainst,
                ObjectHash        = ObjectHash
            };

            return(newGilesObject);
        }
Пример #3
0
        private static void RecordTargetHistory()
        {
            string targetMd5Hash = HashGenerator.GenerateObjecthash(CurrentTarget);

            // clean up past targets
            if (!GenericCache.ContainsKey(targetMd5Hash))
            {
                CurrentTarget.HasBeenPrimaryTarget      = true;
                CurrentTarget.TimesBeenPrimaryTarget    = 1;
                CurrentTarget.FirstTargetAssignmentTime = DateTime.Now;
                GenericCache.AddToCache(new GenericCacheObject(targetMd5Hash, CurrentTarget, new TimeSpan(0, 10, 0)));
            }
            else if (GenericCache.ContainsKey(targetMd5Hash))
            {
                GilesObject cTarget = (GilesObject)GenericCache.GetObject(targetMd5Hash).Value;
                if (!cTarget.IsBoss && cTarget.TimesBeenPrimaryTarget > 15 && !(cTarget.Type == GObjectType.Item && cTarget.ItemQuality >= ItemQuality.Legendary))
                {
                    DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Blacklisting target {0} ActorSNO={1} RActorGUID={2} due to possible stuck/flipflop!",
                                 CurrentTarget.InternalName, CurrentTarget.ActorSNO, CurrentTarget.RActorGuid);

                    hashRGUIDBlacklist60.Add(CurrentTarget.RActorGuid);

                    // Add to generic blacklist for safety, as the RActorGUID on items and gold can change as we move away and get closer to the items (while walking around corners)
                    // So we can't use any ID's but rather have to use some data which never changes (actorSNO, position, type, worldID)
                    GenericBlacklist.AddToBlacklist(new GenericCacheObject()
                    {
                        Key     = CurrentTarget.ObjectHash,
                        Value   = null,
                        Expires = DateTime.Now.AddSeconds(60)
                    });
                }
                else
                {
                    cTarget.TimesBeenPrimaryTarget++;
                    GenericCache.UpdateObject(new GenericCacheObject(targetMd5Hash, cTarget, new TimeSpan(0, 10, 0)));
                }
            }
        }
Пример #4
0
        private static void RefreshSetKiting(ref Vector3 vKitePointAvoid, bool NeedToKite, ref bool TryToKite)
        {
            using (new PerformanceLogger("RefreshDiaObjectCache.Kiting"))
            {
                TryToKite = false;

                var monsterList = from m in GilesObjectCache
                                  where m.Type == GObjectType.Unit &&
                                  m.Weight > 0 &&
                                  m.RadiusDistance <= PlayerKiteDistance &&
                                  (m.IsBossOrEliteRareUnique ||
                                   ((m.HitPointsPct >= .15 || m.MonsterStyle != MonsterSize.Swarm) && !m.IsBossOrEliteRareUnique)
                                  )
                                  select m;

                if (CurrentTarget != null && CurrentTarget.Type == GObjectType.Unit && PlayerKiteDistance > 0 && CurrentTarget.RadiusDistance <= PlayerKiteDistance)
                {
                    TryToKite       = true;
                    vKitePointAvoid = PlayerStatus.CurrentPosition;
                }

                if (monsterList.Count() > 0 && (PlayerStatus.ActorClass != ActorClass.Wizard || IsWizardShouldKite()))
                {
                    TryToKite       = true;
                    vKitePointAvoid = PlayerStatus.CurrentPosition;
                }

                // Note that if treasure goblin level is set to kamikaze, even avoidance moves are disabled to reach the goblin!
                bool shouldKamikazeTreasureGoblins = (!AnyTreasureGoblinsPresent || Settings.Combat.Misc.GoblinPriority <= GoblinPriority.Prioritize);

                double msCancelledEmergency = DateTime.Now.Subtract(timeCancelledEmergencyMove).TotalMilliseconds;
                bool   shouldEmergencyMove  = msCancelledEmergency >= cancelledEmergencyMoveForMilliseconds && NeedToKite;

                double msCancelledKite = DateTime.Now.Subtract(timeCancelledKiteMove).TotalMilliseconds;
                bool   shouldKite      = msCancelledKite >= cancelledKiteMoveForMilliseconds && TryToKite;

                if (shouldKamikazeTreasureGoblins && (shouldEmergencyMove || shouldKite))
                {
                    Vector3 vAnySafePoint = NavHelper.FindSafeZone(false, 1, vKitePointAvoid, true, monsterList);

                    if (LastKitePosition == null)
                    {
                        LastKitePosition = new KitePosition()
                        {
                            PositionFoundTime = DateTime.Now,
                            Position          = vAnySafePoint,
                            Distance          = vAnySafePoint.Distance(PlayerStatus.CurrentPosition)
                        };
                    }

                    if (vAnySafePoint != Vector3.Zero && vAnySafePoint.Distance(PlayerStatus.CurrentPosition) >= 1)
                    {
                        if ((DateTime.Now.Subtract(LastKitePosition.PositionFoundTime).TotalMilliseconds > 3000 && LastKitePosition.Position == vAnySafePoint) ||
                            (CurrentTarget != null && DateTime.Now.Subtract(lastGlobalCooldownUse).TotalMilliseconds > 1500 && TryToKite))
                        {
                            timeCancelledKiteMove            = DateTime.Now;
                            cancelledKiteMoveForMilliseconds = 1500;
                            DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Kite movement failed, cancelling for {0:0}ms", cancelledKiteMoveForMilliseconds);
                            return;
                        }
                        else
                        {
                            LastKitePosition = new KitePosition()
                            {
                                PositionFoundTime = DateTime.Now,
                                Position          = vAnySafePoint,
                                Distance          = vAnySafePoint.Distance(PlayerStatus.CurrentPosition)
                            };
                        }

                        if (Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement))
                        {
                            DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Kiting to: {0} Distance: {1:0} Direction: {2:0}, Health%={3:0.00}, KiteDistance: {4:0}, Nearby Monsters: {5:0} NeedToKite: {6} TryToKite: {7}",
                                         vAnySafePoint, vAnySafePoint.Distance(PlayerStatus.CurrentPosition), MathUtil.GetHeading(MathUtil.FindDirectionDegree(Me.Position, vAnySafePoint)),
                                         PlayerStatus.CurrentHealthPct, PlayerKiteDistance, monsterList.Count(),
                                         NeedToKite, TryToKite);
                        }
                        CurrentTarget = new GilesObject()
                        {
                            Position       = vAnySafePoint,
                            Type           = GObjectType.Avoidance,
                            Weight         = 90000,
                            CentreDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vAnySafePoint),
                            RadiusDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vAnySafePoint),
                            InternalName   = "KitePoint"
                        };

                        //timeCancelledKiteMove = DateTime.Now;
                        //cancelledKiteMoveForMilliseconds = 100;

                        // Try forcing a target update with each kiting
                        //bForceTargetUpdate = true;
                    }
                    //else
                    //{
                    //    // Didn't find any kiting we could reach, so don't look for any more kite spots for at least 1.5 seconds
                    //    timeCancelledKiteMove = DateTime.Now;
                    //    cancelledKiteMoveForMilliseconds = 500;
                    //}
                }
                else if (!shouldEmergencyMove && NeedToKite)
                {
                    DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Emergency movement cancelled for {0:0}ms", DateTime.Now.Subtract(timeCancelledEmergencyMove).TotalMilliseconds - cancelledKiteMoveForMilliseconds);
                }
                else if (!shouldKite && TryToKite)
                {
                    DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Kite movement cancelled for {0:0}ms", DateTime.Now.Subtract(timeCancelledKiteMove).TotalMilliseconds - cancelledKiteMoveForMilliseconds);
                }
            }
        }
Пример #5
0
 private static void RefreshDoBackTrack()
 {
     // See if we should wait for [playersetting] milliseconds for possible loot drops before continuing run
     if (DateTime.Now.Subtract(lastHadUnitInSights).TotalMilliseconds <= Settings.Combat.Misc.DelayAfterKill || DateTime.Now.Subtract(lastHadEliteUnitInSights).TotalMilliseconds <= Settings.Combat.Misc.DelayAfterKill)
     {
         CurrentTarget = new GilesObject()
         {
             Position       = PlayerStatus.CurrentPosition,
             Type           = GObjectType.Avoidance,
             Weight         = 20000,
             CentreDistance = 2f,
             RadiusDistance = 2f,
             InternalName   = "GilesWaitForLootDrops"
         };
         DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Behavior, "Waiting for loot to drop, delay: {0}ms", Settings.Combat.Misc.DelayAfterKill);
     }
     // Now see if we need to do any backtracking
     if (CurrentTarget == null && iTotalBacktracks >= 2 && Settings.Combat.Misc.AllowBacktracking && !PlayerStatus.IsInTown)
     // Never bother with the 1st backtrack position nor if we are in town
     {
         // See if we're already within 18 feet of our start position first
         if (Vector3.Distance(PlayerStatus.CurrentPosition, vBacktrackList[1]) <= 18f)
         {
             vBacktrackList   = new SortedList <int, Vector3>();
             iTotalBacktracks = 0;
         }
         // See if we can raytrace to the final location and it's within 25 feet
         if (iTotalBacktracks >= 2 && Vector3.Distance(PlayerStatus.CurrentPosition, vBacktrackList[1]) <= 25f &&
             NavHelper.CanRayCast(PlayerStatus.CurrentPosition, vBacktrackList[1]))
         {
             vBacktrackList   = new SortedList <int, Vector3>();
             iTotalBacktracks = 0;
         }
         if (iTotalBacktracks >= 2)
         {
             // See if we can skip to the next backtracker location first
             if (iTotalBacktracks >= 3)
             {
                 if (Vector3.Distance(PlayerStatus.CurrentPosition, vBacktrackList[iTotalBacktracks - 1]) <= 10f)
                 {
                     vBacktrackList.Remove(iTotalBacktracks);
                     iTotalBacktracks--;
                 }
             }
             CurrentTarget = new GilesObject()
             {
                 Position       = vBacktrackList[iTotalBacktracks],
                 Type           = GObjectType.Backtrack,
                 Weight         = 20000,
                 CentreDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vBacktrackList[iTotalBacktracks]),
                 RadiusDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vBacktrackList[iTotalBacktracks]),
                 InternalName   = "GilesBacktrack"
             };
         }
     }
     else
     {
         vBacktrackList   = new SortedList <int, Vector3>();
         iTotalBacktracks = 0;
     }
     // End of backtracking check
     //TODO : If this code is obselete remove it (Check that)
     // Finally, a special check for waiting for wrath of the berserker cooldown before engaging Azmodan
     if (CurrentTarget == null && Hotbar.Contains(SNOPower.Barbarian_WrathOfTheBerserker) && Settings.Combat.Barbarian.WaitWOTB && !GilesUseTimer(SNOPower.Barbarian_WrathOfTheBerserker) &&
         ZetaDia.CurrentWorldId == 121214 &&
         (Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f))
     {
         bDontSpamOutofCombat = true;
         Logging.Write("[Trinity] Waiting for Wrath Of The Berserker cooldown before continuing to Azmodan.");
         CurrentTarget = new GilesObject()
         {
             Position       = PlayerStatus.CurrentPosition,
             Type           = GObjectType.Avoidance,
             Weight         = 20000,
             CentreDistance = 2f,
             RadiusDistance = 2f,
             InternalName   = "GilesWaitForWrath"
         };
     }
     // And a special check for wizard archon
     if (CurrentTarget == null && Hotbar.Contains(SNOPower.Wizard_Archon) && !GilesUseTimer(SNOPower.Wizard_Archon) && Settings.Combat.Wizard.WaitArchon && ZetaDia.CurrentWorldId == 121214 &&
         (Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f))
     {
         DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Waiting for Wizard Archon cooldown before continuing to Azmodan.");
         CurrentTarget = new GilesObject()
         {
             Position       = PlayerStatus.CurrentPosition,
             Type           = GObjectType.Avoidance,
             Weight         = 20000,
             CentreDistance = 2f,
             RadiusDistance = 2f,
             InternalName   = "GilesWaitForArchon"
         };
     }
     // And a very sexy special check for WD BigBadVoodoo
     if (CurrentTarget == null && Hotbar.Contains(SNOPower.Witchdoctor_BigBadVoodoo) && !PowerManager.CanCast(SNOPower.Witchdoctor_BigBadVoodoo) && ZetaDia.CurrentWorldId == 121214 &&
         (Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(711.25f, 716.25f, 80.13903f)) <= 40f || Vector3.Distance(PlayerStatus.CurrentPosition, new Vector3(546.8467f, 551.7733f, 1.576313f)) <= 40f))
     {
         DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Waiting for WD BigBadVoodoo cooldown before continuing to Azmodan.");
         CurrentTarget = new GilesObject()
         {
             Position       = PlayerStatus.CurrentPosition,
             Type           = GObjectType.Avoidance,
             Weight         = 20000,
             CentreDistance = 2f,
             RadiusDistance = 2f,
             InternalName   = "GilesWaitForVoodooo"
         };
     }
 }
Пример #6
0
        /// <summary>
        /// This method will add and update necessary information about all available actors. Determines GilesObjectType, sets ranges, updates blacklists, determines avoidance, kiting, target weighting
        /// and the result is we will have a new target for the Target Handler. Returns true if the cache was refreshed.
        /// </summary>
        /// <returns>True if the cache was updated</returns>
        public static bool RefreshDiaObjectCache(bool forceUpdate = false)
        {
            using (new PerformanceLogger("RefreshDiaObjectCache"))
            {
                if (DateTime.Now.Subtract(LastRefreshedCache).TotalMilliseconds < Settings.Advanced.CacheRefreshRate && !forceUpdate)
                {
                    if (!UpdateCurrentTarget())
                    {
                        return(false);
                    }
                }
                LastRefreshedCache = DateTime.Now;

                using (new PerformanceLogger("RefreshDiaObjectCache.UpdateBlock"))
                {
                    GenericCache.MaintainCache();
                    GenericBlacklist.MaintainBlacklist();

                    using (ZetaDia.Memory.AcquireFrame())
                    {
                        // Update player-data cache, including buffs
                        GilesPlayerCache.UpdateCachedPlayerData();

                        if (PlayerStatus.CurrentHealthPct <= 0)
                        {
                            return(false);
                        }

                        if (Settings.Combat.Misc.UseNavMeshTargeting && !gp.CanStandAt(gp.WorldToGrid(PlayerStatus.CurrentPosition.ToVector2())))
                        {
                            NavHelper.UpdateSearchGridProvider();
                        }


                        RefreshCacheInit();

                        // Now pull up all the data and store anything we want to handle in the super special cache list
                        // Also use many cache dictionaries to minimize DB<->D3 memory hits, and speed everything up a lot
                        RefreshCacheMainLoop();
                    }
                }

                // Reduce ignore-for-loops counter
                if (IgnoreTargetForLoops > 0)
                {
                    IgnoreTargetForLoops--;
                }
                // If we have an avoidance under our feet, then create a new object which contains a safety point to move to
                // But only if we aren't force-cancelling avoidance for XX time
                bool bFoundSafeSpot = false;

                using (new PerformanceLogger("RefreshDiaObjectCache.AvoidanceCheck"))
                {
                    // Note that if treasure goblin level is set to kamikaze, even avoidance moves are disabled to reach the goblin!
                    if (StandingInAvoidance && (!AnyTreasureGoblinsPresent || Settings.Combat.Misc.GoblinPriority <= GoblinPriority.Prioritize) &&
                        DateTime.Now.Subtract(timeCancelledEmergencyMove).TotalMilliseconds >= cancelledEmergencyMoveForMilliseconds)
                    {
                        Vector3 vAnySafePoint = NavHelper.FindSafeZone(false, 1, PlayerStatus.CurrentPosition, true);
                        // Ignore avoidance stuff if we're incapacitated or didn't find a safe spot we could reach
                        if (vAnySafePoint != vNullLocation)
                        {
                            if (Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement))
                            {
                                DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Kiting Avoidance: {0} Distance: {1:0} Direction: {2:0}, Health%={3:0.00}, KiteDistance: {4:0}",
                                             vAnySafePoint, vAnySafePoint.Distance(Me.Position), MathUtil.GetHeading(MathUtil.FindDirectionDegree(Me.Position, vAnySafePoint)),
                                             PlayerStatus.CurrentHealthPct, PlayerKiteDistance);
                            }

                            bFoundSafeSpot = true;
                            CurrentTarget  = new GilesObject()
                            {
                                Position       = vAnySafePoint,
                                Type           = GObjectType.Avoidance,
                                Weight         = 20000,
                                CentreDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vAnySafePoint),
                                RadiusDistance = Vector3.Distance(PlayerStatus.CurrentPosition, vAnySafePoint),
                                InternalName   = "GilesSafePoint"
                            };;
                        }
                        //else
                        //{
                        //    // Didn't find any safe spot we could reach, so don't look for any more safe spots for at least 2.8 seconds
                        //    cancelledEmergencyMoveForMilliseconds = 2800;
                        //    timeCancelledEmergencyMove = DateTime.Now;
                        //    DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "Unable to find kite location, canceling emergency movement for {0}ms", cancelledEmergencyMoveForMilliseconds);
                        //}
                    }
                }

                /*
                 * Give weights to objects
                 */
                // Special flag for special whirlwind circumstances
                bAnyNonWWIgnoreMobsInRange = false;
                // Now give each object a weight *IF* we aren't skipping direcly to a safe-spot
                if (!bFoundSafeSpot)
                {
                    RefreshDiaGetWeights();
                    RefreshSetKiting(ref vKitePointAvoid, NeedToKite, ref TryToKite);
                }
                // Not heading straight for a safe-spot?
                // No valid targets but we were told to stay put?
                if (CurrentTarget == null && ShouldStayPutDuringAvoidance && !StandingInAvoidance)
                {
                    CurrentTarget = new GilesObject()
                    {
                        Position       = PlayerStatus.CurrentPosition,
                        Type           = GObjectType.Avoidance,
                        Weight         = 20000,
                        CentreDistance = 2f,
                        RadiusDistance = 2f,
                        InternalName   = "GilesStayPutPoint"
                    };
                    DbHelper.Log(TrinityLogLevel.Debug, LogCategory.CacheManagement, "Staying Put During Avoidance");
                }
                using (new PerformanceLogger("RefreshDiaObjectCache.FinalChecks"))
                {
                    // force to stay put if we want to town run and there's no target
                    if (CurrentTarget == null && ForceVendorRunASAP)
                    {
                        bDontMoveMeIAmDoingShit = true;
                    }

                    // Still no target, let's see if we should backtrack or wait for wrath to come off cooldown...
                    if (CurrentTarget == null)
                    {
                        RefreshDoBackTrack();
                    }
                    // Still no target, let's end it all!
                    if (CurrentTarget == null)
                    {
                        return(true);
                    }
                    // Ok record the time we last saw any unit at all
                    if (CurrentTarget.Type == GObjectType.Unit)
                    {
                        lastHadUnitInSights = DateTime.Now;
                        // And record when we last saw any form of elite
                        if (CurrentTarget.IsBoss || CurrentTarget.IsEliteRareUnique || CurrentTarget.IsTreasureGoblin)
                        {
                            lastHadEliteUnitInSights = DateTime.Now;
                        }
                    }
                    // Record the last time our target changed
                    if (CurrentTargetRactorGUID != CurrentTarget.RActorGuid)
                    {
                        RecordTargetHistory();
                        DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Weight, "Found New Target - {0} CurrentTargetRactorGUID: {1} CurrentTarget.RActorGuid: {2}",
                                     DateTime.Now, CurrentTargetRactorGUID, CurrentTarget.RActorGuid);
                        dateSincePickedTarget = DateTime.Now;
                        iTargetLastHealth     = 0f;
                    }
                    else
                    {
                        // We're sticking to the same target, so update the target's health cache to check for stucks
                        if (CurrentTarget.Type == GObjectType.Unit)
                        {
                            // Check if the health has changed, if so update the target-pick time before we blacklist them again
                            if (CurrentTarget.HitPointsPct != iTargetLastHealth)
                            {
                                DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Weight, "Keeping Target {0} - CurrentTarget.iHitPoints: {1:0.00}  iTargetLastHealth: {2:0.00} ",
                                             CurrentTarget.RActorGuid, CurrentTarget.HitPointsPct, iTargetLastHealth);
                                dateSincePickedTarget = DateTime.Now;
                            }
                            // Now store the target's last-known health
                            iTargetLastHealth = CurrentTarget.HitPointsPct;
                        }
                    }
                }
                // We have a target and the cached was refreshed
                return(true);
            }
        }