public ControlState controlState; //get and set the control state #endregion #region constructor/load public TacticalBattle(List<Piece> player1Army, List<Piece> player2Army, TacMap map, ContentManager content) { //p1Avatar = player1; //p2Avatar = player2; this.player1Army = player1Army; this.player2Army = player2Army; isPlayer1Turn = true; this.map = map; battleOver = false; gridOn = false; mouseVisible = true; controlState = ControlState.selectUnit; selectedUnit = null; status = "Combat begins"; selectionTiles = new List<Tile>(); unitInfo = ""; //load interface items TODO confirmation = content.Load<Texture2D>("confirmationPopup"); background = content.Load<Texture2D>("TerrainSprites/battle"); statusFont = content.Load<SpriteFont>("Arial"); playerFont = content.Load<SpriteFont>("playerFont"); infoFont = content.Load<SpriteFont>("infoFont"); moveBox = content.Load<Texture2D>("TerrainSprites/move"); targetBox = content.Load<Texture2D>("TerrainSprites/target"); selectedBox = content.Load<Texture2D>("TerrainSprites/selected"); horizontal = content.Load<Texture2D>("TerrainSprites/horizontal"); vertical = content.Load<Texture2D>("TerrainSprites/vertical"); winBox = content.Load<Texture2D>("Menu/Win message"); //set units to starting positions startingPositions(); }
public Tile(String terrain, int x, int y) { xCoord = x; yCoord = y; this.terrain = terrain; unit = null; }
//TODO similar to valid moves, find a list of all tiles within public List<Tile> findValidMoves(Piece piece) { //List<Tile> validMoves = new List<Tile>(); piece.validMoves = new List<Tile>(); findMoves(piece.getLocation(), piece.getAP(), piece); return piece.validMoves; }
//Returns a list of tiles containing a valid target in range of the given ability //That list is stored on the ability object and is cleared with each new (non-recursive) call to this method public List<Tile> checkRange(Tile origin, Ability ability, int range, Piece user) { //Clears the list if this is the initial call because the parameter "range" will only equal ability.range if this is the first call if (ability.getRange() == range) { validTargets = new List<Tile>(); } List<Tile> frontier = getNeighbors(origin, new List<Tile>()); if (!origin.isEmpty()) { //If ability targets enemies & the tile contains a unit from the other faction & if the tile is not already in the list THEN the tile is added if (ability.getTargetType().Equals("Enemy") && !(origin.getResident().getFaction().Equals(user.getFaction())) && !validTargets.Contains(origin)) { validTargets.Add(origin); } //If ability targets friendlies & the tile contains a unit from the same faction & if the tile is not already in the list THEN the tile is added else if (ability.getTargetType().Equals("Friendly") && (origin.getResident().getFaction().Equals(user.getFaction())) && !validTargets.Contains(origin)) { validTargets.Add(origin); } } //decrement range for the next round of checks int nRange = range - 1; if (nRange >= 0) { for (int i = 0; i < frontier.Count(); i++) { checkRange(frontier[i], ability, nRange, user); } } return validTargets; }
public TacticalBattle(Array player1Army, Array player2Army, TacMap map, ContentManager content) { //p1Avatar = player1; //p2Avatar = player2; this.player1Army = player1Army; this.player2Army = player2Army; isPlayer1Turn = true; this.map = map; battleOver = false; mouseVisible = true; controlState = ControlState.selectUnit; selectedUnit = null; status = "Combat begins"; selectionTiles = new List<Tile>(); //load interface items TODO background = content.Load<Texture2D>("TerrainSprites/background"); }
private void findMoves(Tile location, int ap, Piece piece) { int remainingPoints = ap; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { Tile tile = neighbors[i]; int cost; if (tile.getTerrain().Equals("Plain")) { cost = 1; } else if (tile.getTerrain().Equals("Woods")) { cost = 2; } else if (tile.getTerrain().Equals("Mountain")) { cost = 4; } else { cost = 999; } if (remainingPoints >= cost && !piece.validMoves.Contains(neighbors[i])) { if (neighbors[i].isEmpty()) { piece.validMoves.Add(neighbors[i]); findMoves(neighbors[i], remainingPoints - cost, piece); return; } else { if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findMoves(neighbors[i], remainingPoints - cost, piece); return; } else { return; } } } else { return; } } }
public String movePiece(Tile origin, Tile destination, Piece piece) { if (piece.validMoves.Contains(destination)) { origin.removePiece(); origin.enterPiece(piece); // promptAbility(); piece.move(); piece.validMoves = null; return piece.getName() + " has moved"; } else return "invalid location"; }
private void findMoves(Tile location, int ap, Piece piece) { int remainingPoints = ap; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { Tile tile = neighbors[i]; int cost; if (tile.getTerrain().Equals("Plain")) { cost = 1; } else if (tile.getTerrain().Equals("Woods")) { cost = 2; } else if (tile.getTerrain().Equals("Mountain")) { cost = 4; } else { cost = 999; } //If there is sufficient ap if (remainingPoints >= cost) { //If the tile is empty it is added to the list and another call made if (neighbors[i].isEmpty()) { //if validMoves does not already hold the tile if (!validMoves.Contains(neighbors[i])) { validMoves.Add(neighbors[i]); } findMoves(neighbors[i], remainingPoints - cost, piece); } else { //if the tile is occupied BUT is occupied by a friendly another call is made but the tile is not added, the tile is not a valid move //but the search still "paths" through it if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findMoves(neighbors[i], remainingPoints - cost, piece); } } } } }
public List<Tile> findValidTargets(Piece piece) { //returns a list of Tiles that contain units whose faction != to the passed faction validTargets = new List<Tile>(); findTargets(map[piece.getXPosition(), piece.getYPosition()], piece.getRange(), piece); return validTargets; }
public Tile(String terrain) { this.terrain = terrain; unit = null; }
//use to move a unit into the tile public void enterPiece(Piece unit) { this.unit = unit; unit.setPosition(xCoord, yCoord); unit.setTerrain(terrain); }
public override String execute(Piece user, Piece target) { String result; Random r = new Random(); int chanceToHit; if (user.getName().Equals("Nomad") || user.getName().Equals("Archer")) { result = user.getFaction() + " " + user.getName(); if (user.getName().Equals("Archer")) { chanceToHit = 99 - 5 * (target.getDefense()/2 - user.getAttack()); } else { chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); } if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage(); target.applyDamage(user.getDamage()); } else result += " misses"; if (target.getHealth() < 1) { result += ", " + target.getFaction() + " " + target.getName(); result += " is killed"; } } else { if (target.getName().Equals("Pikeman") && !user.getName().Equals("Pikeman")) { result = target.getFaction() + " " + target.getName(); chanceToHit = 99 - 5 * (user.getDefense() - target.getAttack()); if (r.Next(100) < chanceToHit) { if (user.hasPieceMoved()) { result += " hits for " + target.getDamage() * 2; user.applyDamage(target.getDamage() * 2); } else { result += " hits for " + target.getDamage(); user.applyDamage(target.getDamage()); } } else result += " misses"; result += ", " + user.getFaction() + " " + user.getName(); if (user.getHealth() > 0) { chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); result += "'s retailiation"; if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage() / 2; target.applyDamage(user.getDamage() / 2); } else result += " misses"; } else result += " is killed"; } else if (user.getName().Equals("Swordsman")) { result = user.getFaction() + " " + user.getName(); chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage(); target.applyDamage(user.getDamage()); } else result += " misses"; result += ", " + target.getFaction() + " " + target.getName(); if (target.getHealth() > 0) { chanceToHit = 99 - 5 * (user.getDefense() - target.getAttack()); result += "'s retailiation"; if (r.Next(100) < chanceToHit) { result += " hits for " + target.getDamage() / 2; user.applyDamage(target.getDamage() / 2); } else result += " misses"; if (user.getHealth() < 1) { result += ", " + user.getFaction() + " " + user.getName(); result += " is killed"; } } else result += " is killed"; result += user.getFaction() + " " + user.getName(); chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage(); target.applyDamage(user.getDamage()); } else result += " misses"; if (target.getHealth() < 1) { result += ", " + target.getFaction() + " " + target.getName(); result += " is killed"; } } else if (user.getName().Equals("Knight")) { result = user.getFaction() + " " + user.getName(); chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage(); target.applyDamage(user.getDamage()); } else result += " misses"; result += ", " + target.getFaction() + " " + target.getName(); if (target.getHealth() > 0) { if (!(user.hasPieceMoved() && r.Next(2) == 1)) { chanceToHit = 99 - 5 * (user.getDefense() - target.getAttack()); result += "'s retailiation"; if (r.Next(100) < chanceToHit) { result += " hits for " + target.getDamage() / 2; user.applyDamage(target.getDamage() / 2); } else result += " misses"; if (user.getHealth() < 1) { result += ", " + user.getFaction() + " " + user.getName(); result += " is killed"; } } else result += "loses retailiation to charge"; } else result += " is killed"; } else { result = user.getFaction() + " " + user.getName(); chanceToHit = 99 - 5 * (target.getDefense() - user.getAttack()); if (r.Next(100) < chanceToHit) { result += " hits for " + user.getDamage(); target.applyDamage(user.getDamage()); } else result += " misses"; result += ", " + target.getFaction() + " " + target.getName(); if (target.getHealth() > 0) { chanceToHit = 99 - 5 * (user.getDefense() - target.getAttack()); result += "'s retailiation"; if (r.Next(100) < chanceToHit) { result += " hits for " + target.getDamage() / 2; user.applyDamage(target.getDamage() / 2); } else result += " misses"; if (user.getHealth() < 1) { result += ", " + user.getFaction() + " " + user.getName(); result += " is killed"; } } else result += " is killed"; } } if (target.getHealth() < 1) //if target dies give user extra xp, else give the target xp. Prevents reviving dead units with lvling up user.addXP(80 * target.getLevel()); //amount of xp is determined by level else target.addXP(10 * user.getLevel()); if (user.getHealth() < 1) target.addXP(55 * user.getLevel()); else user.addXP(40 * target.getLevel()); return result; }
public abstract String execute(Piece user, Piece target);
public Attack(Piece user) { range = user.getRange() ; targetType = "Enemy"; name = "Melee Attack"; }
//remove a unit from a tile public void removePiece() { unit = null; }
//use to move a unit into the tile public void enterPiece(Piece unit) { this.unit = unit; }
public void update() //gathers input, updates positions, and handles combat { //update inputs oldMouse = mouseState; mouseState = Mouse.GetState(); oldKeyboardState = keyboardState; keyboardState = Keyboard.GetState(); Rectangle endTurn = new Rectangle(918, 818, 268, 69); Rectangle toggleGrid = new Rectangle(1076, 70, 115, 20); Rectangle mouse = new Rectangle(mouseState.X, mouseState.Y, 1, 1); //TODO find unspent unit //click toggle grid button if (mouse.Intersects(toggleGrid) && mouseState.LeftButton == ButtonState.Pressed && oldMouse.LeftButton != ButtonState.Pressed) gridOn = !gridOn; if (controlState == ControlState.selectUnit) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and scrolled over friendly unit set unit to selected and change state to choose option if (mouseState.LeftButton == ButtonState.Pressed) { if (mouse.Intersects(endTurn) && oldMouse.LeftButton != ButtonState.Pressed) { //if end turn is clicked then refresh armies and switch players controlState = ControlState.endTurn; } else { if (mouseState.X < 900 && mouseState.Y < 900 && scrolledOver != null && !scrolledOver.isEmpty()) { if((scrolledOver.getResident().getFaction().Equals("RED") && isPlayer1Turn) || (scrolledOver.getResident().getFaction().Equals("BLUE") && !isPlayer1Turn)) { if (!scrolledOver.getResident().hasPieceAttacked()) { selectedTile = scrolledOver; selectedUnit = scrolledOver.getResident(); selectionTiles = map.getValidMoves(); controlState = ControlState.chooseOption; //hide mouse mouseVisible = false; } else status = "Unit is spent for this turn"; } } } } if (keyboardState.IsKeyDown(Keys.K)) //test win screen { status = "Nobody wins! YAY!"; controlState = ControlState.endGame; } } else if (controlState == ControlState.chooseOption) { //if keyboardState has a button pressed coressponding to the options then change state and show mouse TODO if (keyboardState.IsKeyDown(Keys.W) && !selectedUnit.hasPieceMoved()) //move { mouseVisible = true; selectionTiles = map.findValidMoves(selectedUnit); controlState = ControlState.move; } else if (keyboardState.IsKeyDown(Keys.A) && !selectedUnit.hasPieceAttacked()) //attack { mouseVisible = true; currentAbility = new Attack(selectedUnit); selectionTiles = map.checkRange(selectedTile, currentAbility, currentAbility.getRange(), selectedUnit); //if no targets in range status "says so" and don't change state controlState = ControlState.selectTarget; } else if (keyboardState.IsKeyDown(Keys.T)) //end turn { //selectedUnit.move(); selectedUnit.attack(); //TODO mouseVisible = true; controlState = ControlState.selectUnit; } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { mouseVisible = true; controlState = ControlState.selectUnit; } //space = cancel, go back to selectUnit } else if (controlState == ControlState.move) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and mouse XY corresponds to valid tile then move unit and return to chooseoption TODO if (selectionTiles.Contains(mouseOverTile()) && mouseState.LeftButton == ButtonState.Pressed) { map.movePiece(selectedTile, scrolledOver, selectedUnit); selectedTile = scrolledOver; selectedUnit.move(); status = selectedUnit.getName() + " has moved."; mouseVisible = false; controlState = ControlState.chooseOption; } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { mouseVisible = false; controlState = ControlState.chooseOption; } //space = cancel, go back to chooseOption } else if (controlState == ControlState.selectTarget) { //change scroll-over display based on mouse coordinates scrolledOver = mouseOverTile(); //if click and tile is in target list than initiate combat between selected unit and target, show mouse, return to select unit TODO if (mouseState.LeftButton == ButtonState.Pressed) { //if scrolled over tile is within targetTiles then initiate combat if(selectionTiles.Contains(scrolledOver)) { //change status to combat result string status = currentAbility.execute(selectedUnit, scrolledOver.getResident()); selectedUnit.attack(); //remove dead units if (selectedUnit.getHealth() < 1) selectedTile.removePiece(); if (scrolledOver.getResident().getHealth() < 1) scrolledOver.removePiece(); controlState = ControlState.selectUnit; //status = "attack"; } } else if (keyboardState.IsKeyDown(Keys.Space) && !oldKeyboardState.IsKeyDown(Keys.Space)) { currentAbility = null; mouseVisible = false; controlState = ControlState.chooseOption; } //space = cancel, go back to chooseOption } else if (controlState == ControlState.endTurn) { if (keyboardState.IsKeyDown(Keys.Y)) { refreshArmy(); isPlayer1Turn = !isPlayer1Turn; //refreshArmy(); status = "Turn ended, next player's turn begins"; controlState = ControlState.selectUnit; } else if (keyboardState.IsKeyDown(Keys.Space)) { controlState = ControlState.selectUnit; } } else if(controlState == ControlState.endGame) { //continue if (keyboardState.IsKeyDown(Keys.Space)) { endBattle(); } } if (isArmyDead(player1Army)) { status = "Blue Player 2 Wins!"; } else if (isArmyDead(player2Army)) { status = "Red Player 1 Wins!"; } }
//TODO similar to valid moves, find a list of all tiles within //Reinitializes the list of moves and starts the recursive call public List<Tile> findValidMoves(Piece piece) { //List<Tile> validMoves = new List<Tile>(); validMoves = new List<Tile>(); findMoves(map[piece.getXPosition(), piece.getYPosition()], piece.getAP(), piece); return validMoves; }
public void findTargets(Tile location, int range, Piece piece) { int remainingRange = range; List<Tile> neighbors = getNeighbors(location, new List<Tile>()); for (int i = 0; i < neighbors.Count; i++) { //If there is sufficient ap and validMoves does not already hold that tile if (remainingRange >= 1 && !validTargets.Contains(neighbors[i])) { //If the tile is empty it is not added to the list and another call made if (neighbors[i].isEmpty()) { //validTargets.Add(neighbors[i]); findTargets(neighbors[i], remainingRange - 1, piece); } else { //if the tile is occupied BUT is occupied by a friendly another call is made but the tile is not added, the tile is not a valid target //but the search still "paths" through it if (neighbors[i].getResident().getFaction().Equals(piece.getFaction())) { findTargets(neighbors[i], remainingRange - 1, piece); } //if the tile is occupied by an enemy faction, add it to validTargets else { validTargets.Add(neighbors[i]); findTargets(neighbors[i], remainingRange - 1, piece); } } } } }
public void execute(Piece user, Piece target) { }