private void TimerCallback(object sender, EventArgs e) { // Make sure everything is loaded first. if (!LokiPoe.IsBotFullyLoaded) { return; } if (!IsEnabledFunc()) { return; } LokiPoe.BeginDispatchIfNecessary(Dispatcher, () => { var data = GetDataFunc(); if (data.IsValid) { foreach (var renderGroup in _renderGroups) { renderGroup.Render(data); } data.IsValid = false; } _renderNavGrid.Enabled = ShowNavGrid.IsChecked == true; _renderLocalPlayer.Enabled = ShowLocalPlayer.IsChecked == true; _renderLocalPlayer.LockCamera = LockCameraToPlayer.IsChecked == true; _renderMesh.Enabled = ShowNavMesh.IsChecked == true; }); }
private void CreateNavMeshOverlay() { var vertices = new List <Point3D>(); var indices = new List <int>(); NavMesh navMesh = ExilePather.PolyPathfinder.NavMesh; int tcount = navMesh.GetMaxTiles(); for (int i = 0; i < tcount; i++) { MeshTile tile = navMesh.GetTile(i); if (tile.Header == null) { continue; } AddMeshTile(tile, vertices, indices); } var b = new MeshBuilder(); for (int i = 0; i < indices.Count - 3; i += 3) { b.AddTriangle(vertices[indices[i + 2]], vertices[indices[i + 1]], vertices[indices[i]]); } _initialSeed = _curData.Seed; LokiPoe.BeginDispatchIfNecessary(View.Dispatcher, () => (Visual as MeshVisual3D).Content = new GeometryModel3D(b.ToMesh(true), MaterialHelper.CreateMaterial(Colors.DeepSkyBlue, 0.35))); }
private void LokiPoeOnOnGuiTick(object sender, GuiTickEventArgs guiTickEventArgs) { if (!BotManager.IsRunning) { using (LokiPoe.AcquireFrame()) { _data.Update(); } } }
private void TreeViewObjects_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e) { using (LokiPoe.AcquireFrame()) { using (LokiPoe.Memory.TemporaryCacheState(false)) { TextBoxInfoRaw.Text = ""; var item = TreeViewObjects.SelectedItem as TreeViewItem; if (item == null || item.Tag == null) { return; } var obj = item.Tag as NetworkObject; if (obj != null) { if (obj.IsValid && LokiPoe.ObjectManager.GetObjectByAddress(obj.BaseAddress) != null) { ShowObjectInformation(obj); } return; } var skill = item.Tag as Skill; if (skill != null) { ShowSkillInformation(skill); return; } var itm = item.Tag as Item; if (itm != null) { ShowItemInformation(itm); return; } var area = item.Tag as DatWorldAreaWrapper; if (area != null) { ShowAreaInformation(area); return; } var quest = item.Tag as DatQuestWrapper; if (quest != null) { ShowQuestInformation(quest); return; } } } }
private void ReloadExilePatherButton_OnClick(object sender, RoutedEventArgs e) { Dispatcher.BeginInvoke(new Action(() => { using (LokiPoe.AcquireFrame()) { ExilePather.Reload(true); } GetDataFunc().ForceReload = true; Log.InfoFormat("[ReloadExilePatherButton_OnClick] Done!"); })); }
private void SetCharNameButton_Click(object sender, RoutedEventArgs e) { using (LokiPoe.AcquireFrame()) { if (LokiPoe.IsInGame) { var charName = LokiPoe.Me.Name; Settings.Instance.Character = string.IsNullOrEmpty(charName) ? "error" : charName; } else { MessageBoxes.Error("You must be in the game."); } } }
/// <summary> /// This function will add a location that we can reference later. An example of a location /// would be area transitions or NPCs which can despawn. /// </summary> public void AddLocation(Vector2i position, int id, string name) { var location = new Location { Position = position, Id = id, Name = name }; _locations.Add(location); Log.DebugFormat("Adding location [\"{0}\"][{1}] = {2} for area [0x{3:X}]", location.Name, location.Id, location.Position, Hash); LokiPoe.InvokeEvent(OnLocationAdded, null, new OnLocationAddedEventArgs(location)); }
/// <summary> The plugin tick callback. Do any update logic here. </summary> public void Tick() { // Don't update while we are not in the game. if (!LokiPoe.IsInGame) { return; } // Update the current skillgems once per major event. if (!_ranOnce) { // This can trigger gui code from a non-gui thread, so we need to run it on a gui thread. LokiPoe.BeginDispatchIfNecessary(new Action(() => GemLevelerSettings.Instance.RefreshSkillGemsList())); _ranOnce = true; return; } }
internal void ExecutePythonButton_Click(object sender, RoutedEventArgs e) { PythonExampleSettings.Instance.Code = PyInputTextBox.Text; Dispatcher.BeginInvoke(new Action(() => { lock (_pythonExample) { _pythonExample.InitializeScriptManager(); using (LokiPoe.AcquireFrame()) { // For total control, GetStatement logic is this: var scope = _pythonExample.ScriptManager.Scope; var scriptSource = _pythonExample.ScriptManager.Engine.CreateScriptSourceFromString(PythonExampleSettings.Instance.Code); scope.SetVariable("ioproxy", _pythonExample.ScriptManager.IoProxy); scriptSource.Execute(scope); scope.GetVariable <Action>("Execute")(); } } })); }
private void CreateVisual() { _initialSeed = _curData.Seed; if (_curData.IsInGame) { var builder = new MeshBuilder(true, false); List <Tripper.Tools.Math.Vector3> verts; List <int> indices; if (!RDPathfinder.UseNewGetTris) { RDPathfinder.GetTris(_curData.CachedTerrainData, 2, out verts, out indices); // 2 is the walkable value used for pathfinding } else { RDPathfinder.GetTris2(_curData.CachedTerrainData, 2, out verts, out indices, out var rects); // 2 is the walkaloe value used for pathfinding } for (int i = 0; i < indices.Count - 3; i += 3) { var p0 = verts[indices[i + 2]]; var p1 = verts[indices[i + 1]]; var p2 = verts[indices[i + 0]]; // We need to swap Y/Z for display purposes. builder.AddTriangle(new Point3D(p0.X, p0.Z, p0.Y), new Point3D(p1.X, p1.Z, p1.Y), new Point3D(p2.X, p2.Z, p2.Y)); } LokiPoe.BeginDispatchIfNecessary(View.Dispatcher, () => (Visual as MeshVisual3D).Content = new GeometryModel3D(builder.ToMesh(true), Materials.White)); } else { LokiPoe.BeginDispatchIfNecessary(View.Dispatcher, () => (Visual as MeshVisual3D).Content = null); } }
private void LoadCharactersButton_OnClick(object sender, RoutedEventArgs e) { CharactersComboBox.Items.Clear(); var chars = new List<string>(); using (LokiPoe.AcquireFrame()) { if (LokiPoe.StateManager.IsSelectCharacterStateActive && !LokiPoe.StateManager.IsCreateCharacterStateActive) { if (LokiPoe.SelectCharacterState.IsCharacterListLoaded) { foreach (var ch in LokiPoe.SelectCharacterState.Characters.OrderBy(ce => ce.Name)) { chars.Add(ch.Name); } } } } foreach (var @char in chars) { CharactersComboBox.Items.Add(@char); } if (!string.IsNullOrEmpty(AutoLoginSettings.Instance.Character)) { var name = AutoLoginSettings.Instance.Character; for (int i = 0; i < CharactersComboBox.Items.Count; i++) { if (((string) (CharactersComboBox.Items[i])).Equals(name)) { CharactersComboBox.SelectedIndex = i; break; } } } }
private void OnTick() { //if (Explorer != null) //{ // Explorer.Tick(); //} var update = false; if (!_itemThrottle.IsRunning) { _itemThrottle.Start(); update = true; } else { if (_itemThrottle.ElapsedMilliseconds >= ItemThrottleMs) { update = true; } } //using (new PerformanceTimer("Tick::WorldItem", 1)) { if (update) { var myPos = LokiPoe.MyPosition; var added = 0; foreach (var worldItem in LokiPoe.ObjectManager.GetObjectsByType <WorldItem>()) { var doAdd = false; Vector2i pos; if (!_ignoreItems.TryGetValue(worldItem.Id, out pos)) { doAdd = true; } else { if (pos != worldItem.Position) { Log.InfoFormat("[AreaStateCache] An item collision has been detected! Item id {0}.", worldItem.Id); _ignoreItems.Remove(worldItem.Id); doAdd = true; } } if (doAdd) { if (added > 10) { break; } ++added; var item = worldItem.Item; if (worldItem.IsAllocatedToOther) { if (DateTime.Now < worldItem.PublicTime) { //Log.InfoFormat("[AreaStateCache] The item {0} is not being marked for pickup because it is allocated to another player.", item.FullName); //_ignoreItems.Add(worldItem.Id, worldItem.Position); continue; } } var visibleOverride = false; if (LootVisibleItemsOverride) { // We can only consider items when they are visible, otherwise we ignore stuff we might want. if (!LokiPoe.ConfigManager.IsAlwaysHighlightEnabled) { continue; } if (LokiPoe.Input.GetClickableHighlightLabelPosition(worldItem) != Vector2.Zero) { visibleOverride = true; } } IItemFilter filter = null; if (visibleOverride || ItemEvaluator.Match(item, EvaluationType.PickUp, out filter)) { var location = new ItemLocation { Id = worldItem.Id, Name = worldItem.Name, Position = worldItem.Position, Rarity = worldItem.Item.Rarity, Metadata = worldItem.Item.Metadata }; if (_itemLocations.ContainsKey(location.Id)) { _itemLocations[location.Id] = location; } else { _itemLocations.Add(location.Id, location); } Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being added from filter [{3}].{2}", location.Id, location.Name, worldItem.HasAllocation ? " [Allocation " + worldItem.PublicTime + "]" : "", filter != null ? filter.Name : "(null)"); } _ignoreItems.Add(worldItem.Id, worldItem.Position); } } var toRemove = new List <int>(); foreach (var kvp in _itemLocations) { if (Blacklist.Contains(kvp.Key)) { Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being removed because the id has been Blacklisted.", kvp.Value.Id, kvp.Value.Name); toRemove.Add(kvp.Value.Id); } else if (myPos.Distance(kvp.Value.Position) < 30) { if (LokiPoe.ObjectManager.GetObjectById <WorldItem>(kvp.Value.Id) == null) { Log.InfoFormat("[AreaStateCache] The location {0} [{1}] is being removed because the WorldItem does not exist.", kvp.Value.Id, kvp.Value.Name); toRemove.Add(kvp.Value.Id); } } } foreach (var id in toRemove) { _itemLocations.Remove(id); } _itemThrottle.Restart(); } } if (!_chestThrottle.IsRunning) { _chestThrottle.Start(); } else { if (_chestThrottle.ElapsedMilliseconds >= ChestThrottleMs) { //using (new PerformanceTimer("Tick::Chest", 1)) { var addedChests = new List <ChestLocation>(); foreach (var chest in LokiPoe.ObjectManager.GetObjectsByType <Chest>().ToList()) { ChestLocation location; if (!_chestLocations.TryGetValue(chest.Id, out location)) { location = new ChestLocation { Id = chest.Id, Name = chest.Name, IsTargetable = chest.IsTargetable, IsOpened = chest.IsOpened, IsStrongBox = chest.IsStrongBox, IsVaalVessel = chest.IsVaalVessel, OpensOnDamage = chest.OpensOnDamage, Position = chest.Position, Stats = chest.Stats.ToList(), IsIdentified = chest.IsIdentified, IsBreakable = chest.OpensOnDamage, Rarity = chest.Rarity, Metadata = chest.Type }; _chestLocations.Add(location.Id, location); addedChests.Add(location); } if (!location.IsOpened) { location.IsOpened = chest.IsOpened; location.IsLocked = chest.IsLocked; location.IsTargetable = chest.IsTargetable; // Support for chests that change locked state, without the lock state updating. var tc = chest.Components.TransitionableComponent; if (tc != null) { if ((tc.Flag1 & 2) != 0) { location.IsLocked = false; } } if (chest.IsVaalVessel) { location.IsLocked = false; } if (!location.IsCorrupted && chest.IsCorrupted) { location.IsCorrupted = chest.IsCorrupted; location.Stats = chest.Stats.ToList(); } if (!location.IsIdentified && chest.IsIdentified) { location.IsIdentified = chest.IsIdentified; location.Stats = chest.Stats.ToList(); } } if (addedChests.Count > 10) { break; } } foreach (var location in addedChests) { if (!location.IsBreakable) { location.Position = ExilePather.FastWalkablePositionFor(location.Position); } LokiPoe.InvokeEvent(OnChestLocationAdded, null, new OnChestLocationAddedEventArgs(location)); } addedChests.Clear(); _chestThrottle.Restart(); } } } if (!_questThrottle.IsRunning) { _questThrottle.Start(); } else { if (_questThrottle.ElapsedMilliseconds >= QuestThrottleMs) { if (LokiPoe.CurrentWorldArea.IsMissionArea) { if (!HasKaruiSpiritLocation) { var obj = LokiPoe.ObjectManager.GetObjectByName("Karui Spirit"); if (obj != null) { AddLocation(ExilePather.FastWalkablePositionFor(obj), obj.Id, obj.Name); HasKaruiSpiritLocation = true; } } } _questThrottle.Restart(); } } if (!_throttle.IsRunning) { _throttle.Start(); } else { if (_throttle.ElapsedMilliseconds >= ThrottleMs) { if (!_timeInInstance.IsRunning) { _timeInInstance.Start(); } if (!_timeInArea.IsRunning) { _timeInArea.Start(); } // Do we need to update wp state flags. if (_updateCheckForWaypoint) { // If the current area doesn't have a wp, we do not want to do any more logic processing. if (!LokiPoe.CurrentWorldArea.HasWaypoint) { _updateCheckForWaypoint = false; ShouldCheckForWaypoint = false; HasWaypointLocation = false; HasWaypointEntry = false; } else { ShouldCheckForWaypoint = true; } } // Do we need to update at state flags. if (_updateAreaTransition) { ShouldCheckForAreaTransition = true; } if (ShouldCheckForStash) { //using (new PerformanceTimer("ShouldCheckForStash", 1)) { if (!HasStashLocation) { var stash = LokiPoe.ObjectManager.Stash; if (stash != null) { // Save the location so we know where it is when the entity isn't in view. AddLocation(ExilePather.FastWalkablePositionFor(stash), stash.Id, "Stash"); // We now have the waypoint location. HasStashLocation = true; } } else { ShouldCheckForStash = false; } } } // If we need to handle wps. if (ShouldCheckForWaypoint) { //using (new PerformanceTimer("ShouldCheckForWaypoint", 1)) { // If we don't have the wp location yet, check to see if we see one. if (!HasWaypointLocation) { var wp = LokiPoe.ObjectManager.Waypoint; if (wp != null) { // Save the location so we know where it is when the entity isn't in view. AddLocation(ExilePather.FastWalkablePositionFor(wp), wp.Id, "Waypoint"); // We now have the waypoint location. HasWaypointLocation = true; } } // If we don't have the wp entry yet, poll for us having it now. // But only if we've seen the waypoint, since otherwise there's no way we have it. if (HasWaypointLocation && !HasWaypointEntry) { var areaId = WorldArea.Id; HasWaypointEntry = LokiPoe.InstanceInfo.AvailableWaypoints.ContainsKey(areaId); } // Once we have both the location and the entry, we do not need to execute wp logic anymore. if (HasWaypointLocation && HasWaypointEntry) { _updateCheckForWaypoint = false; ShouldCheckForWaypoint = false; } } } // If we need to handle ats. if (ShouldCheckForAreaTransition) { //using (new PerformanceTimer("ShouldCheckForAreaTransition", 1)) { // If there are any area transitions on screen, add them if we don't already know of them. foreach (var transition in LokiPoe.ObjectManager.Objects.OfType <AreaTransition>().ToList()) { var name = transition.Name; // We have to check all this in order to handle the areas that have transitions with the same name, but different // entity ids. if (HasLocation(name, transition.Id)) { continue; } AddLocation(ExilePather.FastWalkablePositionFor(transition), transition.Id, name); if (!SeenAreaTransitions.Contains(name)) { SeenAreaTransitions.Add(name); } } } } // Check to see if we need a new anchor point to kite back towards. if (!_hasAnchorPoint || LokiPoe.LocalData.AreaHash != _anchorPointSeed) { ResetAnchorPoint(); ResetCurrentAnchorPoint(); } _throttle.Restart(); } } }
/// <summary> /// Goes to the specified area using waypoint. /// </summary> /// <param name="name">Name of the area eg "Highgate"</param> /// <param name="difficulty"></param> /// <param name="newInstance">Do you want to open new instance?</param> /// <returns></returns> public static async Task <LokiPoe.InGameState.TakeWaypointResult> TakeWaypoint(string name, Difficulty difficulty = Difficulty.Unknown, bool newInstance = false) { //We are already there if (LokiPoe.LocalData.WorldArea.Name == name && LokiPoe.LocalData.WorldArea.Difficulty == difficulty && !newInstance) { return(LokiPoe.InGameState.TakeWaypointResult.None); } //await Coroutines.CloseBlockingWindows(); // First try of fastgotohideout instead of LokiPoe.InGameState.WorldUi.GoToHideout() if (name.Equals("Hideout", StringComparison.OrdinalIgnoreCase) && (LokiPoe.Me.IsInHideout || LokiPoe.Me.IsInTown)) { await Coroutines.CloseBlockingWindows(); var res = await FastGoToHideout(); switch (res) { case Results.FastGoToHideoutResult.None: return(LokiPoe.InGameState.TakeWaypointResult.None); case Results.FastGoToHideoutResult.NoHideout: return(LokiPoe.InGameState.TakeWaypointResult.AreaNotFound); case Results.FastGoToHideoutResult.NotInGame: return(LokiPoe.InGameState.TakeWaypointResult.UiNotOpen); //if we timed out then try to use default method like below } } if (!LokiPoe.InGameState.WorldUi.IsOpened) { var opened = await LibCoroutines.OpenWaypoint(); if (opened != Results.OpenWaypointError.None) { CommunityLib.Log.ErrorFormat("[TakeWaypoint] Fail to open waypoint. Error: \"{0}\".", opened); return(LokiPoe.InGameState.TakeWaypointResult.WaypointControlNotVisible); } } if (difficulty == Difficulty.Unknown) { difficulty = LokiPoe.CurrentWorldArea.Difficulty; } //var areaId = name == "Hideout" ? "" : GetZoneId(difficulty.ToString(), name); CommunityLib.Log.InfoFormat($"[TakeWaypoint] Going to {name} at {difficulty}."); var areaHash = LokiPoe.LocalData.AreaHash; var taken = name.Equals("Hideout", StringComparison.OrdinalIgnoreCase) ? LokiPoe.InGameState.WorldUi.GoToHideout() : LokiPoe.InGameState.WorldUi.TakeWaypoint(LokiPoe.GetZoneId(difficulty.ToString(), name), newInstance, Int32.MaxValue); if (taken != LokiPoe.InGameState.TakeWaypointResult.None) { CommunityLib.Log.ErrorFormat("[TakeWaypoint] Failed to take waypoint to \"{0}\". Error: \"{1}\".", name, taken); return(taken); } var awaited = await Areas.WaitForAreaChange(areaHash); return(awaited ? LokiPoe.InGameState.TakeWaypointResult.None : LokiPoe.InGameState.TakeWaypointResult.CouldNotJoinNewInstance); }
private void ButtonRefresh_OnClick(object sender, RoutedEventArgs e) { TreeViewObjects.Items.Clear(); using (LokiPoe.AcquireFrame()) { using (LokiPoe.Memory.TemporaryCacheState(false)) { if (!LokiPoe.IsInGame) { return; } var objs = LokiPoe.ObjectManager.Objects.OrderBy(o => o.Distance).ToList(); var used = new Dictionary <int, bool>(); var serverEffects = objs.OfType <ServerEffect>().ToList(); foreach (var entry in serverEffects) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var effects = objs.OfType <Effect>().ToList(); foreach (var entry in effects) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var monoliths = objs.OfType <Monolith>().Where(m => !m.IsMini).ToList(); foreach (var entry in monoliths) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var miniMonoliths = objs.OfType <MiniMonolith>().ToList(); foreach (var entry in miniMonoliths) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var breaches = objs.OfType <Breach>().ToList(); foreach (var entry in breaches) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss1 = objs.OfType <AbyssStartNode>().ToList(); foreach (var entry in abyss1) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss2 = objs.OfType <AbyssNodeMini>().ToList(); foreach (var entry in abyss2) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss3 = objs.OfType <AbyssNodeSmall>().ToList(); foreach (var entry in abyss3) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss4 = objs.OfType <AbyssFinalNodeChest>().ToList(); foreach (var entry in abyss4) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss5 = objs.OfType <AbyssCrackSpawner>().ToList(); foreach (var entry in abyss5) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss6 = objs.OfType <AbyssFinalNodeSubArea>().ToList(); foreach (var entry in abyss6) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var abyss7 = objs.OfType <AbyssNodeLarge>().ToList(); foreach (var entry in abyss7) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var shrines = objs.OfType <Shrine>().ToList(); foreach (var entry in shrines) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var darkShrines = objs.OfType <DarkShrine>().ToList(); foreach (var entry in darkShrines) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var stoneAltars = objs.OfType <StoneAltar>().ToList(); foreach (var entry in stoneAltars) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var players = objs.OfType <Player>().ToList(); foreach (var entry in players) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var monsters = objs.OfType <Monster>().ToList(); foreach (var entry in monsters) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var npcs = objs.OfType <Npc>().ToList(); foreach (var entry in npcs) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var worldItems = objs.OfType <WorldItem>().ToList(); foreach (var entry in worldItems) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var portals = objs.OfType <Portal>().ToList(); foreach (var entry in portals) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var chests = objs.OfType <Chest>().ToList(); foreach (var entry in chests) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var areaTransitions = objs.OfType <AreaTransition>().ToList(); foreach (var entry in areaTransitions) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var doors = LokiPoe.ObjectManager.Doors.OrderBy(o => o.Distance).ToList(); foreach (var entry in doors) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var triggerableBlockages = objs.OfType <TriggerableBlockage>().Where(o => !doors.Contains(o) && !abyss3.Contains(o) && !abyss4.Contains(o) && !abyss6.Contains(o) && !abyss7.Contains(o)) .ToList(); foreach (var entry in triggerableBlockages) { if (!used.ContainsKey(entry.Id)) { used.Add(entry.Id, true); } } var others = objs.Where(o => !used.ContainsKey(o.Id)).ToList(); var skills = LokiPoe.ObjectManager.Me.AvailableSkills.ToList(); var abyss = new List <NetworkObject>(); abyss.AddRange(abyss1); abyss.AddRange(abyss2); abyss.AddRange(abyss3); abyss.AddRange(abyss4); abyss.AddRange(abyss6); abyss.AddRange(abyss7); abyss = abyss.OrderBy(n => n.DistanceSqr).ToList(); // Find a list of types... TreeViewObjects.Items.Add(FillTreeNode(new List <DatWorldAreaWrapper> { LokiPoe.CurrentWorldArea }, "Current Area")); TreeViewObjects.Items.Add(""); var header = new TreeViewItem { Header = "Current Player" }; var header2 = new TreeViewItem { Header = "Inventories" }; header2.Items.Add(FillTreeNode(LokiPoe.Me.EquippedItems, "Equipped Items")); header2.Items.Add(FillTreeNode(LokiPoe.InstanceInfo.GetPlayerInventoryItemsBySlot(InventorySlot.Flasks), "Equipped Flasks")); header2.Items.Add(FillTreeNode(LokiPoe.InstanceInfo.GetPlayerInventoryItemsBySlot(InventorySlot.Main), "Inventory Items")); header.Items.Add(header2); header.Items.Add(FillTreeNode(Dat.Quests, "Quests")); header.Items.Add(FillTreeNode(skills, "Skills")); TreeViewObjects.Items.Add(header); TreeViewObjects.Items.Add(""); TreeViewObjects.Items.Add(FillTreeNode(areaTransitions, "Area Transitions")); TreeViewObjects.Items.Add(FillTreeNode(chests, "Chests")); TreeViewObjects.Items.Add(FillTreeNode(worldItems, "Items [Ground]")); TreeViewObjects.Items.Add(FillTreeNode(monsters, "Monsters")); TreeViewObjects.Items.Add(FillTreeNode(npcs, "NPCs")); TreeViewObjects.Items.Add(FillTreeNode(players, "Players")); TreeViewObjects.Items.Add(""); header = new TreeViewItem { Header = "Abyss" }; header.Items.Add(FillTreeNode(abyss, "Nodes")); header.Items.Add(FillTreeNode(abyss5, "Spawners")); TreeViewObjects.Items.Add(header); TreeViewObjects.Items.Add(FillTreeNode(breaches, "Breaches")); TreeViewObjects.Items.Add(FillTreeNode(darkShrines, "Dark Shrines")); TreeViewObjects.Items.Add(FillTreeNode(doors, "Doors")); TreeViewObjects.Items.Add(FillTreeNode(effects, "Effects")); TreeViewObjects.Items.Add(FillTreeNode(miniMonoliths, "MiniMonoliths")); TreeViewObjects.Items.Add(FillTreeNode(monoliths, "Monoliths")); TreeViewObjects.Items.Add(FillTreeNode(portals, "Portals")); TreeViewObjects.Items.Add(FillTreeNode(serverEffects, "ServerEffects")); TreeViewObjects.Items.Add(FillTreeNode(shrines, "Shrines")); TreeViewObjects.Items.Add(FillTreeNode(stoneAltars, "Stone Altars")); TreeViewObjects.Items.Add(FillTreeNode(triggerableBlockages, "Triggerable Blockages")); TreeViewObjects.Items.Add(""); TreeViewObjects.Items.Add(FillTreeNode(others, "<Uncategorized>")); } } }
/// <summary> /// Attempts to move towards a position. This function will perform pathfinding logic and take into consideration move distance /// to try and smoothly move towards a point. /// </summary> /// <param name="position">The position to move towards.</param> /// <param name="user">A user object passed.</param> /// <returns>true if the position was moved towards, and false if there was a pathfinding error.</returns> public bool MoveTowards(Vector2i position, params dynamic[] user) { _coroutinePosition = position; _coroutineUser = user; if (_coroutine == null || _coroutine.IsFinished) { _coroutine = new Coroutine(() => MainCoroutine()); } // Variant 1: If you do not want all execution to be blocked inside MoveTowards, and instead let // other logic run between MoveTowards calls when you need to yield execution, then you would simply // only call Resume once per MoveTowards call, and coroutine execution would continue where it left off. // However, this might result in unexpected side-effects since it's a new design, so use with care... /* * try * { * _coroutine.Resume(); * } * catch * { * var c = _coroutine; * _coroutine = null; * c.Dispose(); * throw; * } */ // Variant 2: If you want all execution to be blocked inside MoveTowards, as it is // with the normal player mover, then you would want to loop until the coroutine is finished, // and release the frame at the end of the loop. The main coroutine would be re-created after // it finishes each time. while (!_coroutine.IsFinished) { try { _coroutine.Resume(); } catch { // This block of code gets copied around, but isn't explained. The reason why this is done // this way, is in the event Dispose throws an exception, the coroutine object ('_coroutine') would not // get set to null, and execution would be locked up with an invalid coroutine object. By keeping it in // a local first, then clearing the class variable, if an exception happens in Dispose, we can // recover because '_coroutine' was set to null and will be created again next Tick. var c = _coroutine; _coroutine = null; c.Dispose(); throw; } if (!_coroutine.IsFinished) { // Just like normal player mover, we release the frame after logic is done running, to trigger // the next frame for execution to continue. Execution control stays within this loop though. LokiPoe.ReleaseFrameProfiler("OldCoroutinePlayerMover.MoveTowards", () => { // How you Sleep is up to the mover and what is actually needed, but here's one example // of what you can do (allows changing the sleep inside the coroutine to affect here)/ Thread.Sleep(_coroutineSleepValue); }); } } // If the coroutine finished, return what it returned. if (_coroutine.IsFinished) { return((bool)_coroutine.Result); } // Otherwise, the coroutine is still running, so we're going to return true // since the move is in progress (if it wasn't the coroutine would have returned false, // and we'd not reach here.) return(true); }