//Battle Tile Array uses 32x32 px tiles. Also includes tileSpriteLookup metadata object private void loadBattleTileArray(GameObject tileMapGameObject) { string strTileArray = ""; Bounds mapBounds = tileMapGameObject.GetComponentInChildren<Renderer>().bounds; int tileWidth = (int)Math.Ceiling(mapBounds.size.x ); int tileHeight = (int)Math.Ceiling(mapBounds.size.y ); battleTileArray = new Tile[tileWidth, tileHeight]; for (int y = 0; y < tileHeight; y++) { for (int x = 0; x < tileWidth; x++) { Vector3 center = new Vector3(x + Tile.TILE_SIZE, -y + Tile.TILE_SIZE,0); Vector3 size = new Vector3(Tile.TILE_SIZE, Tile.TILE_SIZE); Bounds tileBounds = new Bounds(center, size); bool empty = !checkCollision(tileBounds); battleTileArray[x, y] = new Tile(x, y, empty); //Extra metadata on tile battleTileArray[x, y].tileSpriteLookup = getTileSpriteLookup(tileBounds, x, y, empty); strTileArray += empty ? "." : "#"; } strTileArray += System.Environment.NewLine; } int i = 1; }
private static void UseAbilityTempEffect(BattleGame game,GameCharacter character, Tile target, Ability ability) { foreach (var ae in ability.activeEffects) { switch (ae.effectType) { case TempEffectType.Particle: game.gameControllerScript.StartTempParticles(ae.effectName, new UnityEngine.Vector3(target.x, -target.y)); break; case TempEffectType.Sprite: var spriteVector = new UnityEngine.Vector3(target.x, -target.y); game.gameControllerScript.StartTempSprite(spriteVector, spriteVector, ae.effectName, ae.effectIndex); break; case TempEffectType.Text: game.gameControllerScript.StartTempText(new UnityEngine.Vector3(target.x, -target.y), UnityEngine.Color.grey, ability.name); break; case TempEffectType.ProjectileSprite: var spriteVector1 = new UnityEngine.Vector3(game.ActiveCharacter.x, -game.ActiveCharacter.y); var spriteVector2 = new UnityEngine.Vector3(target.x, -target.y); game.gameControllerScript.StartTempSpriteProjectile(spriteVector1, spriteVector2, ae.effectName, ae.effectIndex); break; default: break; } } }
private static bool UseAbilityLOSEmpty(GameCharacter character, Ability ability, Tile target, BattleGame game) { if (target.empty) { return UseAbilityLOS(character, ability, target, game); } return false; }
private static Tile[,] copyTileArray(Tile[,] tileArray1) { int width = tileArray1.GetLength(0); int height = tileArray1.GetLength(1); Tile[,] newTileArray = new Tile[width, height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { newTileArray[x, y] = tileArray1[x, y]; } } return newTileArray; }
private static bool UseAbilityLOS(GameCharacter character, Ability ability, Tile target, BattleGame game) { Tile ActiveTile = game.board.getTileFromLocation(character.x, character.y); var tileLOSList = game.board.getBoardLOS(ActiveTile, target); if (tileLOSList.Count <= ability.range && tileLOSList[tileLOSList.Count - 1] == target) { if (character.SpendAP(ability.ap)) { return UseAbilityAOEHelper(character, ability, target, game); } return false; } else { return false; } }
private static bool UseAbilityAOEHelper(GameCharacter character, Ability ability, Tile target, BattleGame game) { var tileAOEList = game.board.getTileListFromPattern(target, ability.tilePatternType); //draw AOE effect foreach (var t in tileAOEList) { game.board.AddTempChar(t, '*'); game.board.AddTempEffect(t, ability.sheetname, ability.spriteindex); UseAbilityTempEffect(game, character, t, ability); } var charAOEList = game.getCharactersFromTileList(tileAOEList); return UseAbilityOnCharList(character,target, ability, charAOEList, game); }
public Tile getAdjascentTile(Tile t, DirectionType dir) { Tile retval = null; switch(dir) { case DirectionType.West: retval = getTileFromLocation(t.x, t.y - 1); break; case DirectionType.East: retval = getTileFromLocation(t.x, t.y + 1); break; case DirectionType.North: retval = getTileFromLocation(t.x - 1, t.y); break; case DirectionType.South: retval = getTileFromLocation(t.x + 1, t.y); break; default: break; } return retval; }
public static bool UseAbility(GameCharacter character, Ability ability, Tile target, BattleGame game) { bool useValue = false; if (ability.cooldownTimer == 0) { switch (ability.targetType) { case AbilityTargetType.Self: useValue= UseAbilitySelf(character, ability, target, game); break; case AbilityTargetType.SingleFriend: useValue= UseAbilitySingleFriend(character, ability, target, game); break; case AbilityTargetType.SingleFoe: useValue= UseAbilitySingleFoe(character, ability, target, game); break; case AbilityTargetType.AllFriends: useValue= UseAbilityAllFriends(character, ability, target, game); break; case AbilityTargetType.AllFoes: useValue = UseAbilityAllFoes(character, ability, target, game); break; case AbilityTargetType.PointEmpty: useValue = UseAbilityPointEmpty(character, ability, target, game); break; case AbilityTargetType.PointTarget: useValue = UseAbilityPoint(character, ability, target, game); break; case AbilityTargetType.LOSEmpty: useValue = UseAbilityLOSEmpty(character, ability, target, game); break; case AbilityTargetType.LOSTarget: useValue = UseAbilityLOS(character, ability, target, game); break; default: useValue = false; break; } } if (useValue) { ability.cooldownTimer = ability.cooldown; } return useValue; }
private static bool UseAbilitySelf(GameCharacter character, Ability ability, Tile target, BattleGame game) { if (character.SpendAP(ability.ap)) { return UseAbilityOnCharList(character,target, ability, new List<GameCharacter>() { character }, game); } else { return false; } }
private static bool UseAbilitySingleFoe(GameCharacter character, Ability ability, Tile target, BattleGame game) { if (character.SpendAP(ability.ap)) { GameCharacter targetChar = game.getCharacterFromTile(target); if (targetChar != null & targetChar.type != character.type) { return UseAbilityOnCharList(character,target, ability, new List<GameCharacter>() { targetChar }, game); } } return false; }
private static bool UseAbilityAllFoes(GameCharacter character, Ability ability, Tile target, BattleGame game) { if (character.SpendAP(ability.ap)) { var foeList = from data in game.characterList where data.type != character.type select data; return UseAbilityOnCharList(character,target, ability, foeList.ToList(), game); } else { return false; } }
private static bool UseAbilityPoint(GameCharacter character, Ability ability, Tile target, BattleGame game) { Tile ActiveTile = game.board.getTileFromLocation(character.x, character.y); int dist = PlotLine.GetPointsOnLine(character.x, character.y, target.x, target.y).Count()-1; if(dist <= ability.range) { if (character.SpendAP(ability.ap)) { return UseAbilityAOEHelper(character, ability, target, game); } } return false; }
//return the tile (or list of tiles) that forms a straight line from the origin, through the target outward, for range tiles //using Bresenham Plotline along empty squares) public List<Tile> getMoveTargetTileList(Tile origin, Tile target, int range) { List<Tile> retvalList = new List<Tile>(); Point rangedPoint = PlotLine.getRangedPointOnLine(getPointFromTile(origin), getPointFromTile(target), range); List<Point> pointList = PlotLine.GetPointsOnLine(target.x,target.y,rangedPoint.x,rangedPoint.y).ToList(); foreach(Point p in pointList) { Tile tempTile = getTileFromPoint(p); if(tempTile != null && tempTile.empty) { retvalList.Add(tempTile); } } return retvalList; }
public List<Tile> getBoardLOS(Tile origin, Tile destination) { List<Tile> tileList = new List<Tile>(); if (origin != null && destination != null) { List<Point> pointList = PlotLine.GetPointsOnLine(origin.x, origin.y, destination.x, destination.y).ToList(); tileList.Add(origin); if (pointList != null) { foreach (var p in pointList) { Tile tempTile = this.getTileFromLocation(p.x, p.y); if (tempTile != origin && tempTile != destination) { if (tempTile.empty) { tileList.Add(tempTile); } else { return tileList; } } } } tileList.Add(destination); } return tileList; }
public static List<Point> Pathfind(Tile[,] tileArray, int x, int y, int x2, int y2) { int Width = tileArray.GetLength(1); int Height = tileArray.GetLength(0); int[,] cost = new int[Width, Height]; cost[x, y] = 1; //floor type List<Point> active = new List<Point>(); active.Add(new Point(x, y)); // pathfind while (true) { // get lowest cost point in active list Point point = active[0]; for (int i = 1; i < active.Count; i++) { Point p = active[i]; if (cost[p.x, p.y] < cost[point.x, point.y]) point = p; } // if end point if (point.x == x2 && point.y == y2) break; // move in directions int currentCost = cost[point.x, point.y]; if (point.x - 1 >= 0 && cost[point.x - 1, point.y] == 0) { active.Add(new Point(point.x - 1, point.y)); cost[point.x - 1, point.y] = currentCost + getCost(tileArray[point.x - 1, point.y]); } if (point.x + 1 < Width && cost[point.x + 1, point.y] == 0) { active.Add(new Point(point.x + 1, point.y)); cost[point.x + 1, point.y] = currentCost + getCost(tileArray[point.x + 1, point.y]); } if (point.y - 1 >= 0 && cost[point.x, point.y - 1] == 0) { active.Add(new Point(point.x, point.y - 1)); cost[point.x, point.y - 1] = currentCost + getCost(tileArray[point.x, point.y - 1]); } if (point.y + 1 < Height && cost[point.x, point.y + 1] == 0) { active.Add(new Point(point.x, point.y + 1)); cost[point.x, point.y + 1] = currentCost + getCost(tileArray[point.x, point.y + 1]); } active.Remove(point); } // work backwards and find path List<Point> points = new List<Point>(); Point current = new Point(x2, y2); points.Add(current); while (current.x != x || current.y != y) { int highest = cost[current.x, current.y]; int left = highest, right = highest, up = highest, down = highest; // get cost of each direction if (current.x - 1 >= 0 && cost[current.x - 1, current.y] != 0) { left = cost[current.x - 1, current.y]; } if (current.x + 1 < Width && cost[current.x + 1, current.y] != 0) { right = cost[current.x + 1, current.y]; } if (current.y - 1 >= 0 && cost[current.x, current.y - 1] != 0) { up = cost[current.x, current.y - 1]; } if (current.y + 1 < Height && cost[current.x, current.y + 1] != 0) { down = cost[current.x, current.y + 1]; } // move in the lowest direction if (left <= GetMin(up, down, right)) { points.Add(current = new Point(current.x - 1, current.y)); } else if (right <= GetMin(left, down, up)) { points.Add(current = new Point(current.x + 1, current.y)); } else if (up <= GetMin(left, right, down)) { points.Add(current = new Point(current.x, current.y - 1)); } else { points.Add(current = new Point(current.x, current.y + 1)); } } points.Reverse(); return points; }
public List<Tile> getTileListFromPattern(Tile origin, TilePatternType pattern) { switch (pattern) { case TilePatternType.FourAdj: return getTileListFromPointList(origin, PatternFactory.getFourAdj()); case TilePatternType.NineSquare: return getTileListFromPointList(origin, PatternFactory.getNineSquare()); default: return new List<Tile>() { origin }; } }
private List<Tile> getTileListFromPointList(Tile origin, List<Point> pointList) { List<Tile> retvalList = new List<Tile>(); foreach(var p in pointList) { var t = getNearTile(origin, p); if(t != null) { retvalList.Add(t); } } return retvalList; }
//return the tile that is a distance away (used to get tile patterns) public Tile getNearTile(Tile t, Point diff) { return getTileFromLocation(t.x + diff.x, t.y + diff.y); }
//Return a path to the tile that has LOS with the destination public List<Point> getPathToLOS(Tile origin, Tile destination) { List<Point> pathList = PathFind.Pathfind(this, origin.x, origin.y, destination.x, destination.y); pathList.RemoveAt(0); pathList.RemoveAt(pathList.Count-1); int counter=0; foreach(var p in pathList) { if(checkLOS(getTileFromPoint(p),destination)) { break; } counter++; } pathList.RemoveRange(0, counter); return pathList; }
public bool checkLOS(Tile origin, Tile destination) { if (origin != null && destination != null) { List<Tile> tileLOSList = getBoardLOS(origin, destination); if (tileLOSList[tileLOSList.Count - 1] == destination) { return true; } else { return false; } } return false; }
public void AddTempEffect(Tile t, string sheetname, int spriteindex) { t.tempSheetName = sheetname; t.tempSpriteIndex = spriteindex; }
public void AddTempChar(Tile t, char c) { t.TempChar = c; }
public Point getPointFromTile(Tile t) { return new Point() { x = t.x, y = t.y }; }
public List<Point> getBoardLOSPointList(Tile origin, Tile destination) { List<Tile> tileList = getBoardLOS(origin, destination); List<Point> pointList = new List<Point>(); foreach (var t in tileList) { pointList.Add(new Point(t.x, t.y)); } return pointList; }
public static bool RangedAttack(GameCharacter attacker, GameCharacter defender, Tile targetTile, BattleGame game) { bool retval = false; //check for ranged weapon if(attacker.weapon is RangedWeapon) { RangedWeapon w = (RangedWeapon)attacker.weapon; Ammo a = (Ammo)ItemHelper.getFirstItemWithID(attacker.inventory,attacker.Ammo.itemID); //check we have ammo if(attacker.Ammo != null && attacker.Ammo.count > 0 && a.ammoType == w.ammoType) { List<Tile> tileLOSList = game.board.getBoardLOS(game.ActiveTile, targetTile); //check LOS //check range if (tileLOSList[tileLOSList.Count - 1] == targetTile ) { if (tileLOSList.Count <= w.range) { if (attacker.SpendAP(attacker.weapon.actionPoints)) { var attackerPos = new UnityEngine.Vector3(attacker.x, -attacker.y); var targetPos = new UnityEngine.Vector3(defender.x, -defender.y); game.gameControllerScript.StartTempSpriteProjectile(attackerPos, targetPos, GameConstants.rangedAttackSpritesheet, GameConstants.rangedAttackSpriteindex); //check for hit if (game.r.Next(20) + attacker.attack > defender.ac) { retval = Hit(attacker, defender, game,a); //remove ammo attacker.inventory.Remove(a); attacker.Ammo = ItemHelper.getItemSet(attacker.inventory, a); retval = true; } else { game.battleLog.AddEntry(string.Format("{0} missed {1}.", attacker.name, defender.name)); } } } else { game.battleLog.AddEntry(string.Format("{0} is out of range.", defender.name)); } } else { game.battleLog.AddEntry(string.Format("Unable to hit {0}", defender.name)); } } else { game.battleLog.AddEntry(string.Format("{0} requires {1} ammo equipped", w.name,w.ammoType)); } } else { game.battleLog.AddEntry(string.Format("Equip a ranged weapon for ranged attack")); } return retval; }
//Need to use A* to get this distance public int getTileDistance(Tile a, Tile b) { return Math.Abs(a.x - b.x) + Math.Abs(a.y-b.y); }
//Zone TileArray uses 16x16 px tiles, used only for zone pathfinding private void loadZoneTileArray(GameObject tileMapGameObject) { string strTileArray = ""; Bounds mapBounds = tileMapGameObject.GetComponentInChildren<Renderer>().bounds; int tileWidth = (int)Math.Ceiling(mapBounds.size.x / Tile.TILE_SIZE); int tileHeight = (int)Math.Ceiling(mapBounds.size.y / Tile.TILE_SIZE); zoneTileArray = new Tile[tileWidth, tileHeight]; for (int y = 0; y < tileHeight; y++) { for (int x = 0; x < tileWidth; x++) { Vector3 center = new Vector3(x * Tile.TILE_SIZE + (Tile.TILE_SIZE / 2), -y * Tile.TILE_SIZE + (Tile.TILE_SIZE / 2), 0); Vector3 size = new Vector3(Tile.TILE_SIZE, Tile.TILE_SIZE); Bounds tileBounds = new Bounds(center, size); bool empty = !checkCollision(tileBounds); zoneTileArray[x, y] = new Tile(x, y, empty); strTileArray += empty ? "." : "#"; } strTileArray += System.Environment.NewLine; } }
//Move character without spending Action Points public bool MoveCharacterFree(GameCharacter gc, Tile Destination) { bool retval = false; if (Destination != null) { if (Destination.empty) { if (!CoreHelper.checkEffect(gc.activeEffects, gc.passiveEffects, StatType.Stuck)) { EmptyTile(board[gc.x, gc.y]); FillTile(gc, Destination); retval = true; } } } return retval; }
private static int getCost(Tile t) { if (!t.empty) { return 99; } else { return 1; } }
private static bool UseAbilityOnCharList(GameCharacter sourceCharacter, Tile target, Ability ability, List<GameCharacter> characterList, BattleGame game) { //Draw Temp Character game.board.AddTempChar(target, 'X'); game.board.AddTempEffect(target, ability.sheetname, ability.spriteindex); foreach(var c in characterList) { UseAbilityTempEffect(game, sourceCharacter, c, ability); } //special conditions if we're doing something on sourceCharacter if(characterList.Count ==0) { foreach (var ae in ability.activeEffects) { if (ae.statType == StatType.Teleport) { game.board.MoveCharacterFree(sourceCharacter, target); } } } foreach (var character in characterList) { foreach (var ae in ability.activeEffects) { if (ae.statType == StatType.Teleport) { game.board.MoveCharacterFree(sourceCharacter, target); //for now, can only teleport self. } else if (ae.statType == StatType.Knockback) //move away from sourceCharacter { Tile sourceTile = game.board.getTileFromLocation(sourceCharacter.x, sourceCharacter.y); Tile charTile = game.board.getTileFromLocation(character.x, character.y); List<Tile> moveTargetList = game.board.getMoveTargetTileList(sourceTile, charTile, ae.minAmount); if (moveTargetList.Count > 0) { Tile moveTile = moveTargetList[moveTargetList.Count - 1]; game.board.MoveCharacterFree(character, moveTile); } } else if(ae.statType == StatType.Explode) //move away from target { Tile charTile = game.board.getTileFromLocation(character.x, character.y); List<Tile> moveTargetList = game.board.getMoveTargetTileList(target, charTile, ae.minAmount); if (moveTargetList.Count > 0) { Tile moveTile = moveTargetList[moveTargetList.Count - 1]; game.board.MoveCharacterFree(character, moveTile); } } else { character.AddActiveEffect(cloneActiveEffect(ae), game); } } } return true; }