public void GetNextNode(ActionSet actionSet, Element player) { if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { actionSet.AddAction(If(Compare(Current.Get(player), Operator.NotEqual, Num(-1)))); } // Get last attribute. actionSet.AddAction(CurrentAttribute.SetVariable(GetCurrentSegmentAttribute(player), targetPlayer: player)); if (TrackNextAttribute) { actionSet.AddAction(NextAttribute.SetVariable(GetNextSegmentAttribute(player), targetPlayer: player)); } // Set current as the current's parent. actionSet.AddAction(Current.SetVariable(ParentArray.Get(player)[Current.Get(player)] - 1, targetPlayer: player)); // Update stuck UpdateStuckDetector(actionSet, player); // Invoke OnNodeReached OnNodeReached?.Invoke(actionSet); if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { actionSet.AddAction(Else()); } if (OnPathCompleted == null) { actionSet.AddAction(Part("Stop Throttle In Direction", player)); StopPathfinding(actionSet, player); } else if (!OnPathCompleted.EmptyBlock) { OnPathCompleted.Invoke(actionSet); } if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { actionSet.AddAction(End()); } }
private void GetResolveRoutine() { // Create the rule that will get the closest node. TranslateRule getResolveRule = new TranslateRule(DeltinScript, "Pathfinder: Resolve Current", RuleEvent.OngoingPlayer); // The rule will activate when DoGetCurrent is set to true. getResolveRule.Conditions.Add(new Condition((Element)DoGetCurrent.GetVariable(), Operators.Equal, new V_True())); // Set the Current variable to the closest node. getResolveRule.ActionSet.AddAction(Current.SetVariable(ClosestNode(getResolveRule.ActionSet, PlayerPosition()))); // If the OnPathStart hook is null, do the default which is throttling the player to the next node. if (OnPathStart == null) { // Start throttle to the current node. ThrottleEventPlayerToNextNode(getResolveRule.ActionSet); } // Otherwise, use the hook. else { OnPathStart.Invoke(getResolveRule.ActionSet); } // Update IsPathfindStuck data. UpdateStuckDetector(getResolveRule.ActionSet); // Reset DoGetCurrent to false. getResolveRule.ActionSet.AddAction(DoGetCurrent.SetVariable(new V_False())); // Add the rule. DeltinScript.WorkshopRules.Add(getResolveRule.GetRule()); // Resolve the rule that increments the current node. // The 'next' rule will set current to the next node index when the current node is reached. TranslateRule next = new TranslateRule(DeltinScript, "Pathfinder: Resolve Next", RuleEvent.OngoingPlayer); next.Conditions.Add(NodeReachedCondition(next.ActionSet)); next.Conditions.Add(new Condition(ParentArray.Get(), Operators.NotEqual, new V_Null())); if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { next.ActionSet.AddAction(Element.Part <A_If>(new V_Compare(Current.Get(), Operators.NotEqual, new V_Number(-1)))); } // Get last attribute. next.ActionSet.AddAction(CurrentAttribute.SetVariable(NextSegmentAttribute(new V_EventPlayer()))); // Set current as the current's parent. next.ActionSet.AddAction(Current.SetVariable(ParentArray.Get()[Current.Get()] - 1)); // Update stuck UpdateStuckDetector(next.ActionSet); // Invoke OnNodeReached OnNodeReached?.Invoke(next.ActionSet); if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { next.ActionSet.AddAction(Element.Part <A_Else>()); } if (OnPathCompleted == null) { next.ActionSet.AddAction(Element.Part <A_StopThrottleInDirection>(new V_EventPlayer())); StopPathfinding(next.ActionSet, new V_EventPlayer()); } else if (!OnPathCompleted.EmptyBlock) { OnPathCompleted.Invoke(next.ActionSet); } if (OnPathCompleted == null || !OnPathCompleted.EmptyBlock) { next.ActionSet.AddAction(Element.Part <A_End>()); } // Add rule DeltinScript.WorkshopRules.Add(next.GetRule()); }
internal void PathFound() { Debug.Log($"Path found from {From} to {To}"); OnPathCompleted?.Invoke(_path); }
public IEnumerator Run(T start, Func <T, bool> isGoal, Func <T, IEnumerable <WeightedNode <T> > > explode, Func <T, float> getHeuristic) { var queue = new PriorityQueue <T>(); var distances = new Dictionary <T, float>(); var parents = new Dictionary <T, T>(); var visited = new HashSet <T>(); distances[start] = 0; queue.Enqueue(new WeightedNode <T>(start, 0)); var stopwatch = new Stopwatch(); stopwatch.Start(); while (!queue.IsEmpty) { var dequeued = queue.Dequeue(); visited.Add(dequeued.Element); if (isGoal(dequeued.Element)) { var path = CommonUtils.CreatePath(parents, dequeued.Element); OnPathCompleted?.Invoke(path); yield break; } var toEnqueue = explode(dequeued.Element); foreach (var transition in toEnqueue) { var neighbour = transition.Element; var neighbourToDequeuedDistance = transition.Weight; var startToNeighbourDistance = distances.ContainsKey(neighbour) ? distances[neighbour] : float.MaxValue; var startToDequeuedDistance = distances[dequeued.Element]; var newDistance = startToDequeuedDistance + neighbourToDequeuedDistance; if (!visited.Contains(neighbour) && startToNeighbourDistance > newDistance) { distances[neighbour] = newDistance; parents[neighbour] = dequeued.Element; queue.Enqueue(new WeightedNode <T>(neighbour, newDistance + getHeuristic(neighbour))); } if (stopwatch.ElapsedMilliseconds < 1f / 60f) { yield return(null); stopwatch.Restart(); } } } OnCantCalculate?.Invoke(); }