public override void onHitTank(Tank t, Vector2 point)
        {
            t.health -= 18;

            battlefield.createExplosion((int) point.X, (int) point.Y);
            int dist = 30;
            for(int i = 0; i < 9; i++) {
                double x = dist * Math.Cos(i * MathHelper.PiOver4);
                double y = dist * Math.Sin(i * MathHelper.PiOver4);
                battlefield.createDelayedExplosion((int) (point.X + x), (int) (point.Y + y), 3);
            }

            foreach(Tank t2 in battlefield.friendlyTanks)
                if(Math.Abs(t2.position.X - t.position.X) / Battlefield.tileSize == 1 && Math.Abs(t2.position.Y - t.position.Y) / Battlefield.tileSize == 1) //diagonal
                    t2.health -= 7;
                else if(Math.Abs(t2.position.X - t.position.X) / Battlefield.tileSize <= 1 && Math.Abs(t2.position.Y - t.position.Y) / Battlefield.tileSize <= 1) //next to
                    t2.health -= 11;

            foreach(Tank t2 in battlefield.enemyTanks)
                if(Math.Abs(t2.position.X - t.position.X) / Battlefield.tileSize == 1 && Math.Abs(t2.position.Y - t.position.Y) / Battlefield.tileSize == 1) //diagonal
                    t2.health -= 7;
                else if(Math.Abs(t2.position.X - t.position.X) / Battlefield.tileSize <= 1 && Math.Abs(t2.position.Y - t.position.Y) / Battlefield.tileSize <= 1) //next to
                    t2.health -= 11;
        }
        public void onUpdate()
        {
            KeyboardState keyboard = Keyboard.GetState();
            if(storyTimer > 0) {
                if(keyboard.IsKeyDown(Keys.Enter))
                    storyTimer = 0;
            }
            else {
                if(!showWinner) {
                    List<Tank> deadTanks = new List<Tank>();
                    foreach(Tank t in friendlyTanks)
                        if(t.health <= 0) {
                            deadTanks.Add(t);
                            map[(int) t.position.X / tileSize, (int) t.position.Y / tileSize] = MapObject.deadTank;
                        }
                    foreach(Tank t in enemyTanks)
                        if(t.health <= 0) {
                            deadTanks.Add(t);
                            map[(int) t.position.X / tileSize, (int) t.position.Y / tileSize] = MapObject.deadTank;
                        }
                    foreach(Tank t in deadTanks) {
                        if(friendlyTanks.Contains(t)) friendlyTanks.Remove(t);
                        if(enemyTanks.Contains(t)) enemyTanks.Remove(t);
                    }
                    if(friendlyTanks.Count == 0 || enemyTanks.Count == 0)
                        showWinner = true;

                    beingMoved = turn % 2 == 0 ? friendlyTanks[(turn / 2) % friendlyTanks.Count] : enemyTanks[(turn / 2) % enemyTanks.Count];

                    WeaponController controller = controllers[(int) weapon[turn % 2]];

                    if(nextTurnTimer > 0) {
                        nextTurnTimer--;
                        if(nextTurnTimer == 0) {
                            movesLeft = 5;
                            moving = false;
                            shot = false;
                            shooting = false;
                            turn++;
                            nextTurnTimer = 1800;
                        }
                    }

                    if(movesLeft == 0 && nextTurnTimer > (shot ? 90 : 300)) {
                        nextTurnTimer = shot ? 90 : 300;
                        moving = false;
                    }
                    else if(!moving && !shooting) {
                        lastPos = beingMoved.position / tileSize;
                        if(turn % 2 == 0 || is2Player) {
                            if(movesLeft > 0) {
                                if(keyboard.IsKeyDown(Keys.Up) && canMoveTo((int) beingMoved.position.X / tileSize, (int) beingMoved.position.Y / tileSize - 1)) {
                                    moving = true;
                                    beingMoved.dir = Tank.Dir.up;
                                }
                                else if(keyboard.IsKeyDown(Keys.Right) && canMoveTo((int) beingMoved.position.X / tileSize + 1, (int) beingMoved.position.Y / tileSize)) {
                                    moving = true;
                                    beingMoved.dir = Tank.Dir.right;
                                }
                                else if(keyboard.IsKeyDown(Keys.Down) && canMoveTo((int) beingMoved.position.X / tileSize, (int) beingMoved.position.Y / tileSize + 1)) {
                                    moving = true;
                                    beingMoved.dir = Tank.Dir.down;
                                }
                                else if(keyboard.IsKeyDown(Keys.Left) && canMoveTo((int) beingMoved.position.X / tileSize - 1, (int) beingMoved.position.Y / tileSize)) {
                                    moving = true;
                                    beingMoved.dir = Tank.Dir.left;
                                }
                            }

                            if(!moving && !shot && keyboard.IsKeyDown(Keys.Space)) {
                                shooting = true;
                                targetPos = targetStart = beingMoved.position + dirToVector(beingMoved.gunDir) * (tileSize / 2) + new Vector2(tileSize / 2, tileSize / 2);
                                targetDir = dirToVector(beingMoved.gunDir);
                            }
                        }
                        else {
                            if(movesLeft > 0)
                                botAI.moveRequestAvailable();
                            if(!moving && !shooting && !shot)
                                botAI.lookForTarget();
                        }
                    }
                    else if(!shooting) {
                        beingMoved.position += 2 * dirToVector(beingMoved.dir);
                        if((beingMoved.position.X % tileSize == 0 && beingMoved.position.Y % tileSize == 0) || (beingMoved.position - lastPos * tileSize).Length() > tileSize) {
                            beingMoved.position.X = ((int) (beingMoved.position.X / tileSize)) * tileSize;
                            beingMoved.position.Y = ((int) (beingMoved.position.Y / tileSize)) * tileSize;
                            map[(int) lastPos.X, (int) lastPos.Y] = MapObject.empty;
                            map[(int) beingMoved.position.X / tileSize, (int) beingMoved.position.Y / tileSize] = turn % 2 == 0 ? MapObject.friendlyTank : MapObject.enemyTank;
                            movesLeft--;
                            moving = false;
                        }
                    }
                    else if((keyboard.IsKeyDown(Keys.Space) && (turn % 2 == 0 || is2Player)) || (turn % 2 == 1 && !is2Player && !botAI.finishedShooting())) {
                        targetPos += controller.targetSpeed * targetDir;
                        Vector2 offset = targetPos - targetStart;
                        double dist = offset.Length() / (double) tileSize;
                        if(dist >= controller.range || offset.X * dirToVector(beingMoved.gunDir).X < 0 || offset.Y * dirToVector(beingMoved.gunDir).Y < 0)
                            targetDir *= -1;

                        if(targetPos.X < 0) {
                            targetPos.X = 0;
                            targetDir.X = Math.Abs(targetDir.X);
                        }
                        if(targetPos.X > tileSize * hTiles - 1) {
                            targetPos.X = tileSize * hTiles - 1;
                            targetDir.X = -Math.Abs(targetDir.X);
                        }
                        if(targetPos.Y < 0) {
                            targetPos.Y = 0;
                            targetDir.Y = Math.Abs(targetDir.Y);
                        }
                        if(targetPos.Y > tileSize * vTiles - 1) {
                            targetPos.Y = tileSize * vTiles - 1;
                            targetDir.Y = -Math.Abs(targetDir.Y);
                        }
                    }
                    else {
                        shooting = false;
                        shot = true;
                        if(movesLeft > 0) movesLeft = 1;
                        nextTurnTimer = 180;
                        Vector2 dir = dirToVector(beingMoved.gunDir);
                        Vector2 checkPos = beingMoved.position / tileSize + dir;
                        bool checking = true;
                        bool hit = false;
                        int maxRange = (int) (targetPos - targetStart).Length() / tileSize;
                        while(checking) {
                            if(checkPos.X < 0 || checkPos.Y < 0 || checkPos.X >= hTiles || checkPos.Y >= vTiles)
                                break;
                            if((checkPos - beingMoved.position / 32).Length() > maxRange)
                                break;
                            switch(map[(int) checkPos.X, (int) checkPos.Y]) {
                                case MapObject.deadTank:
                                case MapObject.box:
                                    checking = controller.penetratesBoxes;
                                    if(!checking) {
                                        hit = true;
                                        controller.onHitBox((int) checkPos.X, (int) checkPos.Y);
                                    }
                                    break;
                                case MapObject.enemyTank:
                                case MapObject.friendlyTank:
                                    Tank t = getTankAt(checkPos);
                                    if(t != null) {
                                        checking = controller.penetratesTanks;
                                        if(!checking) {
                                            hit = true;
                                            controller.onHitTank(t, checkPos * tileSize + new Vector2(Battlefield.tileSize / 2, Battlefield.tileSize / 2) - Battlefield.tileSize / 2 * dirToVector(beingMoved.gunDir));
                                        }
                                    }
                                    break;
                            }
                            checkPos += dir;
                        }
                        if(!hit)
                            switch(map[(int) checkPos.X, (int) checkPos.Y]) {
                                case MapObject.empty:
                                    controller.onHitNothing((int) checkPos.X, (int) checkPos.Y);
                                    break;
                                case MapObject.deadTank:
                                case MapObject.box:
                                    controller.onHitBox((int) checkPos.X, (int) checkPos.Y);
                                    break;
                                case MapObject.enemyTank:
                                case MapObject.friendlyTank:
                                    Tank t = getTankAt(checkPos);
                                    if(t != null)
                                        controller.onHitTank(t, checkPos * tileSize + new Vector2(Battlefield.tileSize / 2, Battlefield.tileSize / 2) - Battlefield.tileSize / 2 * dirToVector(beingMoved.gunDir));
                                    break;
                            }
                    }

                    if(!shooting && (turn % 2 == 0 || is2Player)) {
                        if(keyboard.IsKeyDown(Keys.W))
                            beingMoved.gunDir = Tank.Dir.up;
                        else if(keyboard.IsKeyDown(Keys.D))
                            beingMoved.gunDir = Tank.Dir.right;
                        else if(keyboard.IsKeyDown(Keys.S))
                            beingMoved.gunDir = Tank.Dir.down;
                        else if(keyboard.IsKeyDown(Keys.A))
                            beingMoved.gunDir = Tank.Dir.left;
                    }
                }
            }
        }
 public Vector2 dirToVector(Tank.Dir d)
 {
     return new Vector2(d == Tank.Dir.left ? -1 : d == Tank.Dir.right ? 1 : 0, d == Tank.Dir.up ? -1 : d == Tank.Dir.down ? 1 : 0);
 }
 public override void onHitTank(Tank t, Vector2 point)
 {
     t.health -= 40;
     battlefield.createExplosion((int) point.X, (int) point.Y);
 }
 public virtual void onHitTank(Tank t, Vector2 point)
 {
     battlefield.createExplosion((int) point.X, (int) point.Y);
 }