public bool BeginTargetting(Vector2Int startPosition, LOSData los) { origin = startPosition; target = startPosition; currentLOS = los; points.Clear(); isFinished = false; int maxEffectSize = range + radius; offset = maxEffectSize; length = maxEffectSize * 2 + 1; //Fix 2D problems if (area == null || area.Length != length) { area = new bool[length, length]; } affected = new List <Monster>(); tempAffected = new List <Monster>(); isValid = IsValid(); return(!CanSkip()); //Returns true if we should open targetting, false if we can skip }
public static bool IsFloor(Vector2Int tile, Row r, LOSData l) { if (tile.x == -1 && tile.y == -1) { return(false); } return(!l.getAt(tile.y, tile.x, r.quad.dir)); }
public static bool IsWall(Vector2Int tile, Row r, LOSData l) { if (tile.x == -1 && tile.y == -1) { //Special case for starting tile return(false); } return(l.getAt(tile.y, tile.x, r.quad.dir)); }
public static LOSData GeneratePlayerLOS(Map map, Vector2Int location, int radius) { if (lastCall != null) { lastCall.Deprint(Map.current); } lastCall = LosAt(map, location, radius); lastCall.Imprint(Map.current); return(lastCall); }
public static LOSData LosAt(Map map, Vector2Int position, int distance) { if (distance <= 0) { return(new LOSData(0, position)); } LOSData toReturn = new LOSData(distance, position); toReturn.PrecalculateValues(); toReturn.setAt(0, 0, Direction.NORTH, true); for (int d = 0; d < 4; d++) { Quadrant q = new Quadrant((Direction)d, position); Row firstRow = new Row(1, new fraction(-1, 1), new fraction(1, 1), q); Scan(firstRow, toReturn); } toReturn.CollectEntities(map); return(toReturn); }
public static void Scan(Row r, LOSData l) { Vector2Int previous = -1 * Vector2Int.one; foreach (Vector2Int tile in r.tiles()) { if (IsWall(tile, r, l) || IsSymmetric(r, tile)) { Reveal(tile, l, r.quad.dir); } if (IsWall(previous, r, l) && IsFloor(tile, r, l)) { r.startSlope = Slope(tile); } if (IsFloor(previous, r, l) && IsWall(tile, r, l)) { if (r.depth != l.radius) { Row next_row = r.next(); next_row.endSlope = Slope(tile); Scan(next_row, l); } } previous = tile; } if (IsFloor(previous, r, l)) { if (r.depth != l.radius) { Scan(r.next(), l); } } }
//TODO: Update this to be individual maps public virtual void UpdateLOS() { this.view = LOS.LosAt(Map.current, location, visionRadius); }
public static void Reveal(Vector2Int tile, LOSData l, Direction d) { l.setAt(tile.y, tile.x, d, true); }
private void BuildRange(Vector2Int point) { switch (areaType) { case AreaType.SINGLE_TARGET: MarkArea(point.x, point.y, true); //Mark us again, just for funsies break; case AreaType.CHEBYSHEV_AREA: //Easy case first for (int i = point.x - radius; i <= point.x + radius; i++) { for (int j = point.y - radius; j <= point.y + radius; j++) { MarkArea(i, j, true); } } break; case AreaType.MANHATTAN_AREA: //Second easiest case for (int i = point.x - radius; i <= point.x + radius; i++) { for (int j = point.y - radius; j <= point.y + radius; j++) { if (Mathf.Abs(point.x - i) + Mathf.Abs(point.y - j) <= radius) { MarkArea(i, j, true); } } } break; case AreaType.EUCLID_AREA: //Most complex for (int i = point.x - radius; i <= point.x + radius; i++) { for (int j = point.y - radius; j <= point.y + radius; j++) { if (Vector2Int.Distance(point, new Vector2Int(i, j)) <= radius) //TODO: Confirm this actually works { MarkArea(i, j, true); } } } break; case AreaType.LOS_AREA: //Most expensive call, but easy to understand LOSData data = LOS.LosAt(Map.current, point, radius); for (int i = point.x - radius; i <= point.x + radius; i++) { for (int j = point.y - radius; j <= point.y + radius; j++) { if (data.ValueAtWorld(i, j)) { MarkArea(i, j, true); } } } break; case AreaType.CONE: //This one is pretty wack. Try some vector fanciness? /* * General Strategy: * Figure out the cosine value we're trying to reach (1/2 degree), and the main direction * Normalize everything down to 1 * Run through every square, and figure out it's direction. Normalize it, dot it with * other direction. Compare to cosine value, and if it's >, return a hit * * This trick works because dot(x, y) = |x||y|cos(theta), so by normalizing we can really * cheaply compute the angle between the vectors */ float cosDeg = Mathf.Cos(Mathf.Deg2Rad * degree / 2); Vector2 dir = ((Vector2)(point - origin)).normalized; //Get a good indicator of our direction for (int i = origin.x - radius; i <= origin.x + radius; i++) { for (int j = origin.y - radius; j <= origin.y + radius; j++) { //Perform checks for in cone Vector2 spot = new Vector2(i - origin.x, j - origin.y); float dist = Mathf.Max(Mathf.Abs(spot.x), Mathf.Abs(spot.y)); if (dist <= radius) //TODO: Should this be < ? { if (Vector2.Dot(dir, spot.normalized) > cosDeg) { MarkArea(i, j, true); } } } } break; } }