public static bool ContainsItem(CacheItem item) { UpdateItemList(); if (item.BalanceData == null) { if (item.ItemDropType.HasValue) { var pluginBase = ItemFunc.DetermineBaseItemType(item.ItemDropType.Value); return NewItemList.Any(i => i.BaseItemType == pluginBase); } } else { return NewItemList.Any(i => i.ThisBalanceID == item.BalanceData.BalanceID); } return NewItemList.Any(i => i.SNO == item.SNOID); }
internal static bool PickupItemValidation(CacheItem item) { //if (FunkyTownRunPlugin.ItemRulesEval != null) //{ // Interpreter.InterpreterAction action = FunkyTownRunPlugin.ItemRulesEval.checkPickUpItem(item.DynamicID.Value, item.BalanceData.thisItemType, item.ref_DiaItem.Name, item.InternalName, item.Itemquality.Value, item.BalanceData.iThisItemLevel, item.BalanceData.bThisOneHand, item.BalanceData.bThisTwoHand, item.BalanceID.Value, ItemEvaluationType.PickUp); // if (action== Interpreter.InterpreterAction.PICKUP) // { // return true; // } //} // Calculate giles item types and base types etc. PluginItemTypes thisPluginItemType = PluginItemTypes.Unknown; PluginBaseItemTypes thisGilesBaseType = PluginBaseItemTypes.Unknown; if (item.BalanceID.HasValue && item.BalanceData != null) { thisPluginItemType = item.BalanceData.PluginType; thisGilesBaseType = item.BalanceData.PluginBase; } else { thisPluginItemType = ItemFunc.DetermineItemType(item.InternalName, ItemType.Unknown, FollowerType.None, item.SNOID); thisGilesBaseType = ItemFunc.DetermineBaseType(thisPluginItemType); } if (thisPluginItemType == PluginItemTypes.MiscBook) return FunkyBaseExtension.Settings.Loot.ExpBooks; if (thisPluginItemType == PluginItemTypes.RamaladnisGift) return true; // Error logging for DemonBuddy item mis-reading ItemType gilesDBItemType = ItemFunc.PluginItemTypeToDBItemType(thisPluginItemType); if (item.BalanceID.HasValue && item.BalanceData != null && gilesDBItemType != item.BalanceData.Type) { Logger.DBLog.InfoFormat("GSError: Item type mis-match detected: Item Internal=" + item.InternalName + ". DemonBuddy ItemType thinks item type is=" + item.BalanceData.Type + ". Giles thinks item type is=" + gilesDBItemType + ". [pickup]", true); } switch (thisGilesBaseType) { case PluginBaseItemTypes.WeaponTwoHand: case PluginBaseItemTypes.WeaponOneHand: case PluginBaseItemTypes.WeaponRange: case PluginBaseItemTypes.Armor: case PluginBaseItemTypes.Offhand: case PluginBaseItemTypes.Jewelry: case PluginBaseItemTypes.FollowerItem: if (FunkyBaseExtension.Settings.Loot.PickupWhiteItems == 1 && FunkyBaseExtension.Settings.Loot.PickupMagicItems == 1 && FunkyBaseExtension.Settings.Loot.PickupRareItems == 1 && FunkyBaseExtension.Settings.Loot.PickupLegendaryItems == 1) { return true; } if (item.Itemquality.HasValue && item.BalanceID.HasValue && item.BalanceData != null) { switch (item.Itemquality.Value) { case ItemQuality.Inferior: case ItemQuality.Normal: case ItemQuality.Superior: return FunkyBaseExtension.Settings.Loot.PickupWhiteItems > 0 && (item.BalanceData.ItemLevel >= FunkyBaseExtension.Settings.Loot.PickupWhiteItems); case ItemQuality.Magic1: case ItemQuality.Magic2: case ItemQuality.Magic3: return FunkyBaseExtension.Settings.Loot.PickupMagicItems > 0 && (item.BalanceData.ItemLevel >= FunkyBaseExtension.Settings.Loot.PickupMagicItems); case ItemQuality.Rare4: case ItemQuality.Rare5: case ItemQuality.Rare6: return FunkyBaseExtension.Settings.Loot.PickupRareItems > 0 && (item.BalanceData.ItemLevel >= FunkyBaseExtension.Settings.Loot.PickupRareItems); case ItemQuality.Legendary: return FunkyBaseExtension.Settings.Loot.PickupLegendaryItems > 0 && (item.BalanceData.ItemLevel >= FunkyBaseExtension.Settings.Loot.PickupLegendaryItems); } } return false; case PluginBaseItemTypes.Gem: if (thisPluginItemType == PluginItemTypes.LegendaryGem) return true; GemQualityTypes qualityType = ItemFunc.ReturnGemQualityType(item.SNOID, item.BalanceData!=null?item.BalanceData.ItemLevel:-1); int qualityLevel = (int)qualityType; if (qualityLevel < FunkyBaseExtension.Settings.Loot.MinimumGemItemLevel || (thisPluginItemType == PluginItemTypes.Ruby && !FunkyBaseExtension.Settings.Loot.PickupGems[0]) || (thisPluginItemType == PluginItemTypes.Emerald && !FunkyBaseExtension.Settings.Loot.PickupGems[1]) || (thisPluginItemType == PluginItemTypes.Amethyst && !FunkyBaseExtension.Settings.Loot.PickupGems[2]) || (thisPluginItemType == PluginItemTypes.Topaz && !FunkyBaseExtension.Settings.Loot.PickupGems[3]) || (thisPluginItemType == PluginItemTypes.Diamond && !FunkyBaseExtension.Settings.Loot.PickupGemDiamond)) { return false; } break; case PluginBaseItemTypes.Misc: // Note; Infernal keys are misc, so should be picked up here - we aren't filtering them out, so should default to true at the end of this function if (thisPluginItemType == PluginItemTypes.CraftingMaterial) { return FunkyBaseExtension.Settings.Loot.PickupCraftMaterials; } if (thisPluginItemType == PluginItemTypes.LegendaryCraftingMaterial) return true; if (thisPluginItemType == PluginItemTypes.CraftingPlan) { if (!FunkyBaseExtension.Settings.Loot.PickupCraftPlans) return false; if (item.BalanceID.HasValue && item.BalanceData != null) { if (item.BalanceData.IsBlacksmithPlanSixProperties && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanSix) return false; if (item.BalanceData.IsBlacksmithPlanFiveProperties && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanFive) return false; if (item.BalanceData.IsBlacksmithPlanFourProperties && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanFour) return false; if (item.BalanceData.IsBlacksmithPlanArchonSpaulders && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanArchonSpaulders) return false; if (item.BalanceData.IsBlacksmithPlanArchonGauntlets && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanArchonGauntlets) return false; if (item.BalanceData.IsBlacksmithPlanRazorspikes && !FunkyBaseExtension.Settings.Loot.PickupBlacksmithPlanRazorspikes) return false; if (item.BalanceData.IsJewelcraftDesignAmulet && !FunkyBaseExtension.Settings.Loot.PickupJewelerDesignAmulet) return false; if (item.BalanceData.IsJewelcraftDesignFlawlessStarGem && !FunkyBaseExtension.Settings.Loot.PickupJewelerDesignFlawlessStar) return false; if (item.BalanceData.IsJewelcraftDesignMarquiseGem && !FunkyBaseExtension.Settings.Loot.PickupJewelerDesignMarquise) return false; if (item.BalanceData.IsJewelcraftDesignPerfectStarGem && !FunkyBaseExtension.Settings.Loot.PickupJewelerDesignPerfectStar) return false; if (item.BalanceData.IsJewelcraftDesignRadiantStarGem && !FunkyBaseExtension.Settings.Loot.PickupJewelerDesignRadiantStar) return false; } } if (thisPluginItemType == PluginItemTypes.InfernalKey) { return FunkyBaseExtension.Settings.Loot.PickupInfernalKeys; } if (thisPluginItemType == PluginItemTypes.KeyStone) { return FunkyBaseExtension.Settings.Loot.PickupKeystoneFragments; } if (thisPluginItemType == PluginItemTypes.BloodShard) { return Backpack.GetBloodShardCount() < 500; } // Potion filtering if (thisPluginItemType == PluginItemTypes.HealthPotion || thisPluginItemType == PluginItemTypes.LegendaryHealthPotion) { PotionTypes potionType = ItemFunc.ReturnPotionType(item.SNOID); if (potionType== PotionTypes.Regular) { if (FunkyBaseExtension.Settings.Loot.MaximumHealthPotions <= 0) return false; var BestPotionToUse = Backpack.ReturnBestPotionToUse(); if (BestPotionToUse == null) return true; var Potions = Backpack.ReturnRegularPotions(); if (Potions.Sum(potions => potions.ThisItemStackQuantity) >= FunkyBaseExtension.Settings.Loot.MaximumHealthPotions) return false; } } break; case PluginBaseItemTypes.HealthGlobe: return false; case PluginBaseItemTypes.Unknown: return false; default: return false; } // Switch giles base item type // Didn't cancel it, so default to true! return true; }
// ///<summary> ///Adds/Updates CacheObjects inside collection by Iteration of RactorList ///This is the method that caches all live data about an object! ///</summary> internal static bool UpdateCacheObjectCollection() { //Update Character (just incase it wasnt called before..) FunkyGame.Hero.Update(false, true); Obstacles.AttemptToClearEntries(); HashSet<int> hashDoneThisRactor = new HashSet<int>(); using (ZetaDia.Memory.AcquireFrame(true)) { if (!ZetaDia.IsInGame || ZetaDia.IsLoadingWorld || !ZetaDia.Me.IsValid) return false; foreach (Actor thisActor in ZetaDia.Actors.RActorList) { int tmp_raGUID; DiaObject thisObj; if (!thisActor.IsValid) continue; //Convert to DiaObject thisObj = (DiaObject)thisActor; tmp_raGUID = thisObj.RActorGuid; // See if we've already checked this ractor, this loop if (hashDoneThisRactor.Contains(tmp_raGUID)) continue; hashDoneThisRactor.Add(tmp_raGUID); //Update RactorGUID and check blacklisting.. if (BlacklistCache.IsRAGUIDBlacklisted(tmp_raGUID)) continue; CacheObject tmp_CachedObj; if (!Objects.TryGetValue(tmp_raGUID, out tmp_CachedObj)) { ActorType Actortype; Vector3 tmp_position; int tmp_acdguid; int tmp_SNOID; #region SNO //Lookup SNO try { tmp_SNOID = thisObj.ActorSNO; } catch (Exception ex) { Logger.Write(LogLevel.Cache, "Safely handled getting SNO for {0}", tmp_raGUID); //Logger.DBLog.InfoFormat("Failure to get SNO from object! RaGUID: {0}", tmp_raGUID); continue; } #endregion //check our SNO blacklist (exclude pets?) if (BlacklistCache.IsSNOIDBlacklisted(tmp_SNOID)) continue; #region Position try { tmp_position = thisObj.Position; } catch (Exception ex) { Logger.Write(LogLevel.Cache, "Safely handled getting Position for {0}", tmp_SNOID); continue; } #endregion #region AcdGUID try { tmp_acdguid = thisObj.ACDGuid; } catch (Exception ex) { Logger.Write(LogLevel.Cache, "Safely handled getting ACDGuid for {0}", tmp_SNOID); continue; } #endregion tmp_CachedObj = new CacheObject(tmp_SNOID, tmp_raGUID, tmp_acdguid, tmp_position); } else //Reset unseen var tmp_CachedObj.LoopsUnseen = 0; ////Validate (ignore special object SNO Ids) //if (!CacheIDLookup.hashSNOSkipCommonDataCheck.Contains(tmp_CachedObj.SNOID)) //{ // try // { // if (thisObj.CommonData == null) // { // Logger.Write(LogLevel.Cache, "CommonData is no longer valid! {0}", tmp_CachedObj.DebugStringSimple); // //BlacklistCache.AddObjectToBlacklist(tmp_CachedObj.RAGUID, BlacklistType.Temporary); // continue; // } // if (thisObj.CommonData.ACDGuid != thisObj.ACDGuid) // { // Logger.Write(LogLevel.Cache, "ACDGuid Mismatched! {0}", tmp_CachedObj.DebugStringSimple); // //BlacklistCache.AddObjectToBlacklist(tmp_CachedObj.RAGUID, BlacklistType.Temporary); // continue; // } // } // catch (Exception ex) // { // //Logger.Write(LogLevel.Cache, "Object is no longer valid! (Exception) SNOID {0}", tmp_CachedObj.DebugStringSimple); // //BlacklistCache.AddObjectToBlacklist(tmp_CachedObj.RAGUID, BlacklistType.Temporary); // continue; // } //} //Update any SNO Data. #region SNO_Cache_Update if (tmp_CachedObj.ref_DiaObject == null || tmp_CachedObj.ContainsNullValues()) { if (!tmp_CachedObj.UpdateData(thisObj, tmp_CachedObj.RAGUID)) { continue; } } else if (!tmp_CachedObj.IsFinalized) {//Finalize this data by recreating it and updating the Sno cache with a new finalized entry, this also clears our all Sno cache dictionaries since we no longer need them! cacheSnoCollection.FinalizeEntry(tmp_CachedObj.SNOID); } #endregion //Check if this object is a summoned unit by a player... #region SummonedUnits if (tmp_CachedObj.IsSummonedPet && CacheIDLookup.hashSNOSkipCommonDataCheck.Contains(tmp_CachedObj.SNOID)) { PetTypes PetType = (PetTypes)TheCache.ObjectIDCache.UnitPetEntries[tmp_CachedObj.SNOID].ObjectType; if (PetType== PetTypes.WIZARD_ArcaneOrbs) { FunkyGame.Targeting.Cache.Environment.HeroPets.WizardArcaneOrbs++; tmp_CachedObj.NeedsRemoved = true; continue; } } #endregion //Special Cache for Interactable Server Objects if (CheckFlag(tmp_CachedObj.targetType.Value, TargetType.ServerInteractable)) { if (!InteractableObjectCache.ContainsKey(tmp_CachedObj.RAGUID)) { InteractableObjectCache.Add(tmp_CachedObj.RAGUID, tmp_CachedObj); //Adventure Mode -- Rifting we add Exit to LOS movement! //if (FunkyGame.AdventureMode && FunkyGame.Bounty.IsInRiftWorld && FunkyBaseExtension.Settings.AdventureMode.EnableAdventuringMode) //{ // if (tmp_CachedObj.InternalName.Contains("Exit")) // { // int index = FunkyGame.Bounty.CurrentBountyMapMarkers.Count; // FunkyGame.Bounty.CurrentBountyMapMarkers.Add(index, new BountyCache.BountyMapMarker(tmp_CachedObj.Position, FunkyGame.Hero.CurrentWorldDynamicID, index)); // } //} } //Whymsdal Portal! if (tmp_CachedObj.SNOID == 405590) { GoblinBehavior.Portal = tmp_CachedObj; } else if (tmp_CachedObj.SNOID == 393030) { GoblinBehavior.Portal = tmp_CachedObj; } //Do not add to main cache! continue; } //Objects with static positions already cached don't need to be updated here. if (!tmp_CachedObj.NeedsUpdate) continue; //Obstacles -- (Not an actual object we add to targeting.) if (CheckFlag(tmp_CachedObj.targetType.Value, TargetType.Avoidance) || tmp_CachedObj.IsObstacle || tmp_CachedObj.HandleAsAvoidanceObject) { #region Obstacles CacheObstacle thisObstacle; //Do we have this cached? if (!Obstacles.TryGetValue(tmp_CachedObj.RAGUID, out thisObstacle)) { AvoidanceType AvoidanceType = AvoidanceType.None; if (tmp_CachedObj.IsAvoidance) { AvoidanceType = AvoidanceCache.FindAvoidanceUsingSNOID(tmp_CachedObj.SNOID); if (AvoidanceType == AvoidanceType.None) { AvoidanceType = AvoidanceCache.FindAvoidanceUsingName(tmp_CachedObj.InternalName); if (AvoidanceType == AvoidanceType.None) continue; } } if (tmp_CachedObj.IsAvoidance && tmp_CachedObj.IsProjectileAvoidance) {//Ranged Projectiles require more than simple bounding points.. so we create it as avoidance zone to cache it with properties. //Check for intersection.. try { ActorMovement thisMovement = thisObj.Movement; Vector2 Direction = thisMovement.DirectionVector; Ray R = new Ray(tmp_CachedObj.Position, Direction.ToVector3()); double Speed; //Lookup Cached Speed, or add new entry. if (!dictProjectileSpeed.TryGetValue(tmp_CachedObj.SNOID, out Speed)) { Speed = thisMovement.DesiredSpeed; dictProjectileSpeed.Add(tmp_CachedObj.SNOID, Speed); } thisObstacle = new CacheAvoidance(tmp_CachedObj, AvoidanceType, R, Speed); Obstacles.Add(thisObstacle); } catch { Logger.Write(LogLevel.Cache, "Failed to create projectile avoidance with rotation and speed. {0}", tmp_CachedObj.InternalName); } } else if (tmp_CachedObj.IsAvoidance) { //Poison Gas Can Be Friendly... if (AvoidanceType == AvoidanceType.PoisonGas) { int TeamID = 0; try { TeamID = thisObj.CommonData.GetAttribute<int>(ActorAttributeType.TeamID); } catch { Logger.Write(LogLevel.Cache, "Failed to retrieve TeamID attribute for object {0}", tmp_CachedObj.InternalName); } //ID of 1 means its non-hostile! (-1?) 2?? //if (TeamID==1||TeamID==-1) if (TeamID != 10) { //Logger.Write(LogLevel.None, "Ignoring Avoidance {0} due to Friendly TeamID match!", tmp_CachedObj.InternalName); BlacklistCache.AddObjectToBlacklist(tmp_CachedObj.RAGUID, BlacklistType.Permanent); continue; } } thisObstacle = new CacheAvoidance(tmp_CachedObj, AvoidanceType); Obstacles.Add(thisObstacle); } else { //Obstacles. thisObstacle = new CacheServerObject(tmp_CachedObj); Obstacles.Add(thisObstacle); } } continue; #endregion } if (tmp_CachedObj.ObjectShouldBeRecreated) {//This is where we create the real object after its done with SNO Update. //Specific updates if (tmp_CachedObj.Actortype.Value == ActorType.Item) { tmp_CachedObj = new CacheItem(tmp_CachedObj); } else if (tmp_CachedObj.Actortype.Value == ActorType.Monster) { if (!tmp_CachedObj.IsSummonedPet) tmp_CachedObj = new CacheUnit(tmp_CachedObj); else { PetTypes PetType = (PetTypes)TheCache.ObjectIDCache.UnitPetEntries[tmp_CachedObj.SNOID].ObjectType; #region Summoner ID Check // Get the summoned-by info, cached if possible if (!tmp_CachedObj.SummonerID.HasValue) { try { tmp_CachedObj.SummonerID = thisObj.CommonData.GetAttribute<int>(ActorAttributeType.SummonedByACDID); } catch (Exception ex) { //Logger.DBLog.InfoFormat("[Funky] Safely handled exception getting summoned-by info [" + tmp_CachedObj.SNOID.ToString(CultureInfo.InvariantCulture) + "]"); //Logger.DBLog.DebugFormat(ex.ToString()); continue; } } if (FunkyGame.Hero.iMyDynamicID != tmp_CachedObj.SummonerID.Value) { BlacklistCache.IgnoreThisObject(tmp_CachedObj, false, false); tmp_CachedObj.NeedsRemoved = true; continue; } #endregion tmp_CachedObj = new CachePet(tmp_CachedObj, PetType); } } else if (tmp_CachedObj.Actortype.Value == ActorType.Gizmo) { if (CheckFlag(tmp_CachedObj.targetType.Value, TargetType.Interactables)) tmp_CachedObj = new CacheInteractable(tmp_CachedObj); else tmp_CachedObj = new CacheDestructable(tmp_CachedObj); } //Update Properties (currently only for units) try { tmp_CachedObj.UpdateProperties(); } catch { Logger.Write(LogLevel.Cache,"Failed to update properties for {0}", tmp_CachedObj.DebugStringSimple); } } if (!tmp_CachedObj.UpdateData()) { //Logger.Write(LogLevel.Cache, "Update Failed for {0}", tmp_CachedObj.DebugStringSimple); if (!tmp_CachedObj.IsStillValid()) tmp_CachedObj.NeedsRemoved = true; continue; } //Obstacle cache if (tmp_CachedObj.Obstacletype.Value != ObstacleType.None && (CheckFlag(tmp_CachedObj.targetType.Value, TargetType.ServerObjects))) { CacheObstacle thisObstacleObj; if (!Obstacles.TryGetValue(tmp_CachedObj.RAGUID, out thisObstacleObj)) { CacheServerObject newobj = new CacheServerObject(tmp_CachedObj); Obstacles.Add(tmp_CachedObj.RAGUID, newobj); //Add nearby objects to our collection (used in navblock/obstaclecheck methods to reduce queries) if (CacheIDLookup.hashSNONavigationObstacles.Contains(newobj.SNOID)) Navigation.Navigation.MGP.AddCellWeightingObstacle(newobj.SNOID, newobj.Radius); } else { if (thisObstacleObj.targetType.Value == TargetType.Unit) { //Since units position requires updating, we update using the CacheObject thisObstacleObj.Position = tmp_CachedObj.Position; Obstacles[tmp_CachedObj.RAGUID] = thisObstacleObj; } } } //cache it if (Objects.ContainsKey(tmp_CachedObj.RAGUID)) Objects[tmp_CachedObj.RAGUID] = tmp_CachedObj; else Objects.Add(tmp_CachedObj.RAGUID, tmp_CachedObj); } //End of Loop }// End of Framelock //Tally up unseen objects. var UnseenObjects = Objects.Keys.Where(O => !hashDoneThisRactor.Contains(O)).ToList(); if (UnseenObjects.Any()) { for (int i = 0; i < UnseenObjects.Count(); i++) { Objects[UnseenObjects[i]].LoopsUnseen++; } } //Trim our collection every 5th refresh. UpdateLoopCounter++; if (UpdateLoopCounter > 4) { UpdateLoopCounter = 0; //Now flag any objects not seen for 5 loops. Gold/Globe only 1 loop. foreach (var item in Objects.Values.Where(CO => (CO.LoopsUnseen >= 5 || //5 loops max.. (CO.targetType.HasValue && (CheckFlag(CO.targetType.Value, TargetType.Gold | TargetType.Globe)) && CO.LoopsUnseen > 0)))) //gold/globe only 1 loop! { item.NeedsRemoved = true; } } CheckForCacheRemoval(); _lastUpdatedCacheCollection=DateTime.Now; return true; }
internal static void ItemPickupEval(CacheItem item) { if (OnItemPickupEvaluation == null) {//If no event hooked then use default evaluation if (!item.ShouldPickup.HasValue) { //Use Giles Scoring or DB Weighting.. item.ShouldPickup = PickupItemValidation(item); } } else { OnItemPickupEvaluation(item); } }
public CacheBalance(CacheItem item) { try { BalanceID = item.ref_DiaItem.CommonData.GameBalanceId; _itemLevel = item.ref_DiaItem.CommonData.Level; _type = item.ref_DiaItem.CommonData.ItemType; _base = item.ref_DiaItem.CommonData.ItemBaseType; _followerType = item.ref_DiaItem.CommonData.FollowerSpecialType; _pluginType = ItemFunc.DetermineItemType(item.InternalName, _type, _followerType, item.SNOID); if (item.ItemDropType.HasValue) _pluginBase = ItemFunc.DetermineBaseItemType(item.ItemDropType.Value); else _pluginBase = ItemFunc.DetermineBaseItemType(item.InternalName, item.SNOID); _isStackable = ItemFunc.DetermineIsStackable(_pluginType, item.SNOID); if (!_isStackable) _isTwoSlot = ItemFunc.DetermineIsTwoSlot(_pluginType); } catch (Exception ex) { Logger.Write(LogLevel.Items, String.Format("Failed to create balance data for item {0}", item.DebugStringSimple)); } }