using UnityEngine;
using System.Collections.Generic;
namespace Pathfinding {
[AddComponentMenu("Pathfinding/Modifiers/Alternative Path")]
[System.Serializable]
///
/// Applies penalty to the paths it processes telling other units to avoid choosing the same path.
///
/// Note that this might not work properly if penalties are modified by other actions as well (e.g graph update objects which reset the penalty to zero).
/// It will only work when all penalty modifications are relative, i.e adding or subtracting penalties, but not when setting penalties
/// to specific values.
///
/// When destroyed, it will correctly remove any added penalty.
///
/// \ingroup modifiers
///
[HelpURL("http://arongranberg.com/astar/docs/class_pathfinding_1_1_alternative_path.php")]
public class AlternativePath : MonoModifier {
#if UNITY_EDITOR
[UnityEditor.MenuItem("CONTEXT/Seeker/Add Alternative Path Modifier")]
public static void AddComp (UnityEditor.MenuCommand command) {
(command.context as Component).gameObject.AddComponent(typeof(AlternativePath));
}
#endif
public override int Order { get { return 10; } }
/// How much penalty (weight) to apply to nodes
public int penalty = 1000;
/// Max number of nodes to skip in a row
public int randomStep = 10;
/// The previous path
List prevNodes = new List();
/// The previous penalty used. Stored just in case it changes during operation
int prevPenalty;
/// A random object
readonly System.Random rnd = new System.Random();
bool destroyed;
public override void Apply (Path p) {
if (this == null) return;
ApplyNow(p.path);
}
protected void OnDestroy () {
destroyed = true;
ClearOnDestroy();
}
void ClearOnDestroy () {
InversePrevious();
}
void InversePrevious () {
// Remove previous penalty
if (prevNodes != null) {
bool warnPenalties = false;
for (int i = 0; i < prevNodes.Count; i++) {
if (prevNodes[i].Penalty < prevPenalty) {
warnPenalties = true;
prevNodes[i].Penalty = 0;
} else {
prevNodes[i].Penalty = (uint)(prevNodes[i].Penalty-prevPenalty);
}
}
if (warnPenalties) {
Debug.LogWarning("Penalty for some nodes has been reset while the AlternativePath modifier was active (possibly because of a graph update). Some penalties might be incorrect (they may be lower than expected for the affected nodes)");
}
}
}
void ApplyNow (List nodes) {
InversePrevious();
prevNodes.Clear();
if (destroyed) return;
if (nodes != null) {
int rndStart = rnd.Next(randomStep);
for (int i = rndStart; i < nodes.Count; i += rnd.Next(1, randomStep)) {
nodes[i].Penalty = (uint)(nodes[i].Penalty+penalty);
prevNodes.Add(nodes[i]);
}
}
prevPenalty = penalty;
}
}
}