public void wander() { var offset = UnityEngine.Random.Range(0, 4); for (var @base = 0; @base < 4; @base += 1) { var ordinal = (offset + @base) % 4; var dir = (OrthoDir)ordinal; if (dir.Px2DX() == 0) { continue; } var newPos = mapEvent.Position + dir.XY2D(); if (mapEvent.Map.IsChipPassableAt(newPos)) { if (Global.Instance().Maps.Avatar.Event.Position == newPos) { mapEvent.GetComponent <CharaEvent>().Facing = dir; var context = Global.Instance().Maps.Lua; Run(MapEvent.PropertyLuaCollide); break; } else if (mapEvent.CanPassAt(newPos) && mapEvent.Map.GetEventAt <MapEvent>(newPos) == null) { var context = Global.Instance().Maps.Lua; mapEvent.StartCoroutine(mapEvent.StepRoutine(dir)); break; } } } }
public List <Vector2Int> FindPath(MapEvent actor, Vector2Int to, int maxPathLength) { if (ManhattanDistance(actor.GetComponent <MapEvent>().position, to) > maxPathLength) { return(null); } if (!actor.CanPassAt(to)) { return(null); } HashSet <Vector2Int> visited = new HashSet <Vector2Int>(); List <List <Vector2Int> > heads = new List <List <Vector2Int> >(); List <Vector2Int> firstHead = new List <Vector2Int>(); firstHead.Add(actor.GetComponent <MapEvent>().position); heads.Add(firstHead); while (heads.Count > 0) { heads.Sort(delegate(List <Vector2Int> pathA, List <Vector2Int> pathB) { int pathACost = pathA.Count + ManhattanDistance(pathA[pathA.Count - 1], to); int pathBCost = pathB.Count + ManhattanDistance(pathB[pathB.Count - 1], to); return(pathACost.CompareTo(pathBCost)); }); List <Vector2Int> head = heads[0]; heads.RemoveAt(0); Vector2Int at = head[head.Count - 1]; if (at == to) { // trim to remove the current location from the beginning return(head.GetRange(1, head.Count - 1)); } if (head.Count < maxPathLength) { foreach (OrthoDir dir in Enum.GetValues(typeof(OrthoDir))) { Vector2Int next = head[head.Count - 1]; // minor perf here, this is critical code switch (dir) { case OrthoDir.East: next.x += 1; break; case OrthoDir.North: next.y += 1; break; case OrthoDir.West: next.x -= 1; break; case OrthoDir.South: next.y -= 1; break; } if (!visited.Contains(next) && actor.CanPassAt(next) && (actor.GetComponent <CharaEvent>() == null || actor.CanPassAt(next)) && (actor.GetComponent <CharaEvent>() == null || actor.GetComponent <CharaEvent>().CanCrossTileGradient(at, next))) { List <Vector2Int> newHead = new List <Vector2Int>(head) { next }; heads.Add(newHead); visited.Add(next); } } } } return(null); }
public void StepOrAttack(EightDir dir, Result <bool> executeResult) { MapEvent parent = me; Vector2Int vectors = me.location; Vector2Int target = vectors + dir.XY(); GetComponent <CharaEvent>().facing = dir; List <MapEvent> targetEvents = me.map.GetEventsAt(target); if (!GetComponent <BattleEvent>().CanCrossTileGradient(parent.location, target)) { executeResult.value = false; return; } List <MapEvent> toCollide = new List <MapEvent>(); bool passable = parent.CanPassAt(target); foreach (MapEvent targetEvent in targetEvents) { toCollide.Add(targetEvent); passable &= targetEvent.IsPassableBy(parent); } if (passable) { chara.PerformWhenDoneAnimating(me.StepRoutine(location, location + dir.XY(), false)); me.location = target; if (unit.Get(StatTag.MOVE) > 1) { unit.canActAgain = !unit.canActAgain; } else if (unit.Get(StatTag.MOVE) < 1) { unit.isRecovering = true; } if (GetComponent <PCEvent>() != null) { foreach (MapEvent targetEvent in toCollide) { if (targetEvent.switchEnabled) { StartCoroutine(CoUtils.RunWithCallback(targetEvent.CollideRoutine(GetComponent <PCEvent>()), () => { executeResult.value = true; })); return; } } } executeResult.value = true; return; } else { foreach (MapEvent targetEvent in toCollide) { float h1 = unit.battle.map.terrain.HeightAt(location); float h2 = unit.battle.map.terrain.HeightAt(target); //if (GetComponent<PCEvent>() != null) { // if (targetEvent.switchEnabled && !targetEvent.IsPassableBy(parent) // && Mathf.Abs(h1 - h2) <= AttackHeightMax) { // StartCoroutine(CollideRoutine(GetComponent<PCEvent>()); // } //} if (targetEvent.GetComponent <BattleEvent>() != null) { BattleEvent other = targetEvent.GetComponent <BattleEvent>(); if (unit.align != other.unit.align) { if (Mathf.Abs(h1 - h2) > AttackHeightMax) { if (GetComponent <PCEvent>() != null) { unit.battle.Log("Too high up to attack!"); } executeResult.value = false; return; } else { unit.MeleeAttack(other.unit); executeResult.value = true; return; } } } // 7drl antipattern hack alert if (GetComponent <PCEvent>() != null && targetEvent.GetComponent <ChestEvent>() != null) { ChestEvent chest = targetEvent.GetComponent <ChestEvent>(); if (!chest.opened) { StartCoroutine(CoUtils.RunWithCallback(chest.OpenRoutine(GetComponent <PCEvent>()), () => { executeResult.value = true; })); return; } } } } executeResult.value = false; }
public List <Vector2Int> FindPath(MapEvent actor, Vector2Int to, int maxPathLength) { if (Vector2.Distance(actor.GetComponent <MapEvent>().location, to) * Mathf.Sqrt(2) > maxPathLength) { return(null); } if (!IsChipPassableAt(layers[0], to)) { return(null); } HashSet <Vector2Int> visited = new HashSet <Vector2Int>(); List <List <Vector2Int> > heads = new List <List <Vector2Int> >(); List <Vector2Int> firstHead = new List <Vector2Int>(); firstHead.Add(actor.GetComponent <MapEvent>().location); heads.Add(firstHead); while (heads.Count > 0) { heads.Sort(delegate(List <Vector2Int> pathA, List <Vector2Int> pathB) { int pathACost = pathA.Count + ManhattanDistance(pathA[pathA.Count - 1], to); int pathBCost = pathB.Count + ManhattanDistance(pathB[pathB.Count - 1], to); return(pathACost.CompareTo(pathBCost)); }); List <Vector2Int> head = heads[0]; heads.RemoveAt(0); Vector2Int at = head[head.Count - 1]; if (at == to) { // trim to remove the current location from the beginning return(head.GetRange(1, head.Count - 1)); } if (head.Count < maxPathLength) { foreach (EightDir dir in Enum.GetValues(typeof(EightDir))) { Vector2Int next = head[head.Count - 1]; // minor perf here, this is critical code switch (dir) { case EightDir.N: next.y += 1; break; case EightDir.E: next.x += 1; break; case EightDir.S: next.y -= 1; break; case EightDir.W: next.x -= 1; break; case EightDir.NE: next.y += 1; next.x += 1; break; case EightDir.SE: next.y -= 1; next.x += 1; break; case EightDir.SW: next.y -= 1; next.x -= 1; break; case EightDir.NW: next.y += 1; next.x -= 1; break; } if (visited.Contains(next)) { continue; } if (next != to && !actor.CanPassAt(next)) { continue; } if (actor.GetComponent <BattleEvent>() != null && !actor.GetComponent <BattleEvent>().CanCrossTileGradient(at, next)) { continue; } if (next == to && Mathf.Abs(terrain.HeightAt(at) - terrain.HeightAt(to)) > BattleEvent.AttackHeightMax) { continue; } if (next != to && (GetEventAt <BattleEvent>(next) != null && GetEventAt <BattleEvent>(next).unit.IsDead())) { continue; } List <Vector2Int> newHead = new List <Vector2Int>(head) { next }; heads.Add(newHead); visited.Add(next); } } } return(null); }