コード例 #1
0
    public void ModoDeMovimento()
    {
        UnidadeNoTabuleiro atual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];

        if (!atual.gridDeMovimento)
        {
            BatalhaController.instancia.removerTileHighlights();
            atual.gridDeMovimento = true;
            atual.gridDeAtaque    = false;
            //Se a unidade atual tem combustivel
            if (atual.unidadeAssociada.status[13] > 0)
            {
                BatalhaController.instancia.highlightTilesAt(atual.gridPosition, BatalhaController.instancia.TileGridMovimento, atual.unidadeAssociada.status[3]);
            }
            else
            {
                BatalhaController.instancia.highlightTilesAt(atual.gridPosition, BatalhaController.instancia.TileGridMovimento, 1);
            }
        }
        else
        {
            atual.gridDeMovimento = false;
            atual.gridDeAtaque    = false;
            BatalhaController.instancia.removerTileHighlights();
        }
        if (botoesDeAcao.activeSelf)
        {
            botoesDeAcao.SetActive(false);
        }
    }
コード例 #2
0
    private void tooglarBotoesDeAcoes()
    {
        UnidadeNoTabuleiro atual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];

        if (!botoesDeAcao.activeSelf)
        {
            botoesDeAcao.SetActive(true);
            if (atual.artilharia)
            {
                posicionar.gameObject.SetActive(true);
                if (atual.preparada)
                {
                    atacar.interactable = true; posicionar.interactable = false;
                }
                else
                {
                    atacar.interactable = false; posicionar.interactable = true;
                }
            }
            else
            {
                posicionar.gameObject.SetActive(false);
            }
        }
        else
        {
            botoesDeAcao.SetActive(false);
        }
    }
コード例 #3
0
    public UnidadeNoTabuleiro ProcurarMaisProximoInimigo()
    {
        List <UnidadeNoTabuleiro> inimigosNoTabuleiro = BatalhaController.instancia.aliadosEmCampo;
        float menorDistancia    = inimigosNoTabuleiro.Min(uni => Vector2.Distance(gridPosition, uni.gridPosition));
        UnidadeNoTabuleiro alvo = inimigosNoTabuleiro.First(uni => Vector2.Distance(gridPosition, uni.gridPosition) == menorDistancia);

        return(alvo);
    }
コード例 #4
0
 public static UnidadeXml CreateUnidadeXml(UnidadeNoTabuleiro unidade)
 {
     return(new UnidadeXml()
     {
         id = (int)unidade.unidadeAssociada.idNoBancoDeDados,
         locX = (int)unidade.gridPosition.x,
         locY = (int)unidade.gridPosition.y
     });
 }
コード例 #5
0
 public void setarUnidadeNoSlot(Tile tile)
 {
     unidadeSendoSetada.gridPosition = tile.posicaoNoTabuleiro;
     unidadesNoTabuleiro.Add(unidadeSendoSetada);
     colocandoUnidade   = false;
     tile.ocupado       = true;
     unidadeSendoSetada = null;
     //instanciarUnidade(unidadeSendoSetada.unidadeAssociada.id);
 }
コード例 #6
0
 void Update()
 {
     if (Input.GetMouseButtonDown(1) && colocandoUnidade)
     {
         colocandoUnidade = false;
         Destroy(unidadeSendoSetada.gameObject);
         unidadeSendoSetada = null;
     }
 }
コード例 #7
0
 public void reposicionarUnidade(Tile tile)
 {
     tile.ocupado = false;
     if (unidadeSendoSetada != null)
     {
         unidadeSendoSetada = null;
     }
     unidadeSendoSetada = unidadesNoTabuleiro.First(uni => uni.gridPosition == tile.posicaoNoTabuleiro);
     unidadesNoTabuleiro.Remove(unidadeSendoSetada);
 }
コード例 #8
0
    public void terminouVez()
    {
        if (botoesDeAcao.activeSelf)
        {
            botoesDeAcao.SetActive(false);
        }
        UnidadeNoTabuleiro atual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];

        tooglarAcoesDoPlayer(!atual.inimigo);
        mostrarHoras();
        atualizarCountdown();
    }
コード例 #9
0
 void OnMouseDown()
 {
     if (Input.GetMouseButtonDown(0))
     {
         if (!noConstrutor)
         {
             if (BatalhaController.instancia.preBattle && !ocupado && sobreHighlight)
             {
                 BatalhaController.instancia.setarUnidadeNoSlot(this);
             }
             else if (BatalhaController.instancia.preBattle && ocupado)
             {
                 BatalhaController.instancia.reposicionarUnidadeNoTabuleiro(this);
             }
             else
             {
                 UnidadeNoTabuleiro atual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];
                 if (atual.gridDeMovimento)
                 {
                     BatalhaController.instancia.verificarTentativaDeMovimento(this);
                 }
                 else if (atual.gridDeAtaque)
                 {
                     BatalhaController.instancia.atacarComPlayerAtual(this);
                 }
                 else if (!atual.gridDeAtaque && !atual.gridDeMovimento && ocupado)
                 {
                     BatalhaController.instancia.mostrarInformacoesDaUnidadeClicada(this);
                 }
             }
         }
         else
         {
             if (MapCreatorManager.instance.mudandoTipo)
             {
                 setarTipoeVisual(MapCreatorManager.instance.palletSelection);
             }
             else if (MapCreatorManager.instance.mudandoMecanica)
             {
                 setarMecanicaeVisual(MapCreatorManager.instance.mechanicPallet);
             }
             else if (MapCreatorManager.instance.colocandoUnidade && !ocupado)
             {
                 MapCreatorManager.instance.setarUnidadeNoSlot(this);
             }
             else if (!MapCreatorManager.instance.colocandoUnidade && ocupado)
             {
                 MapCreatorManager.instance.colocandoUnidade = true;
                 MapCreatorManager.instance.reposicionarUnidade(this);
             }
         }
     }
 }
コード例 #10
0
    public void instanciarUnidade(int id)
    {
        if (unidadeSendoSetada != null)
        {
            unidadeSendoSetada = null;
        }
        UnidadeNoTabuleiro unidadeNova = ((GameObject)Instantiate(unidadePrefab)).GetComponent <UnidadeNoTabuleiro>();

        unidadeSendoSetada = unidadeNova;
        unidadeSendoSetada.unidadeAssociada = banco.retornarUnidade(id);
        unidadeSendoSetada.gameObject.GetComponent <Animator>().runtimeAnimatorController = controladoresInimigos[(int)unidadeNova.unidadeAssociada.classe];
    }
コード例 #11
0
    //Aqui que vamos calcular o caminho caminho mais curto até o destino a partir da origem
    public static List <Tile> FindPathTilesReturn(Tile origem, Tile destino)
    {
        List <Tile>     closed = new List <Tile>();
        List <TilePath> open   = new List <TilePath>();

        UnidadeNoTabuleiro unidadeAtual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];

        TilePath originPath = new TilePath();

        originPath.addTile(origem);

        open.Add(originPath);

        while (open.Count > 0)
        {
            open = open.OrderBy(x => x.custoDoCaminho).ToList();
            TilePath current = open[0];
            open.Remove(open[0]);

            if (closed.Contains(current.ultimoTile))
            {
                continue;
            }
            if (current.ultimoTile == destino)
            {
                current.listaDeTiles.Remove(origem);
                return(current.listaDeTiles);
            }

            closed.Add(current.ultimoTile);

            foreach (Tile t in current.ultimoTile.vizinhos)
            {
                if (t.instransponivel)
                {
                    continue;
                }
                if (unidadeAtual.gridDeMovimento && t.ocupado)
                {
                    continue;
                }
                if (unidadeAtual.gridDeMovimento && t.classesRestritas.Contains(unidadeAtual.unidadeAssociada.classe))
                {
                    continue;
                }
                TilePath newTilePath = new TilePath(current);
                newTilePath.addTile(t);
                open.Add(newTilePath);
            }
        }
        return(null);
    }
コード例 #12
0
    public void mostrarAcoes()
    {
        UnidadeNoTabuleiro atual = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];

        if (atual.inimigo)
        {
            desativarAcoesDoPlayer();
        }
        else
        {
            ativarAcoesDoPlayer();
        }
        atual.gridDeMovimento = false;
        atual.gridDeAtaque    = false;
        BatalhaController.instancia.removerTileHighlights();
        tooglarBotoesDeAcoes();
    }
コード例 #13
0
    //Diferente das unidades de mais de 1 tiles de Range, close combat units não devem ir atrás de um inimigo que ja está cercado
    public UnidadeNoTabuleiro ProcurarMaisProximoInimigoDeCloseCombat()
    {
        List <UnidadeNoTabuleiro> inimigosNoTabuleiro = BatalhaController.instancia.aliadosEmCampo;

        while (true)
        {
            float menorDistancia    = inimigosNoTabuleiro.Min(uni => Vector2.Distance(gridPosition, uni.gridPosition));
            UnidadeNoTabuleiro alvo = inimigosNoTabuleiro.First(uni => Vector2.Distance(gridPosition, uni.gridPosition) == menorDistancia);
            Tile tileDoAlvo         = BatalhaController.instancia.tabuleiro[(int)alvo.gridPosition.x][(int)alvo.gridPosition.y];
            foreach (Tile t in tileDoAlvo.vizinhos)
            {
                if (!t.ocupado)
                {
                    return(alvo);
                }
            }
            inimigosNoTabuleiro.Remove(alvo);
        }
    }
コード例 #14
0
    //A Partir daqui os codigos da IA
    public void AITurno()
    {
        if (!viva)
        {
            Debug.Log("Algo estranho, unidade morta teve turno chamado");
            return;
        }//Seja lá o que aconteceu, uma unidade morta não faz ação

        //Caso sofra do efeito blitzkrieg, a unidade inimiga perderá a vez
        if (pontosDeAcao == 0 && !AIfazAcaoEspecial)
        {
            BatalhaController.instancia.AdministrarFimDeAcao();
        }
        //Novo turno = novo alvo, e portanto, o caminho pode ser que seja nescessario backtrackar
        if (pontosDeAcao == 2)
        {
            alvoDeAtaque = null;
        }

        DecidirAcao();
    }
コード例 #15
0
    public void loadMapFromXml(string nome)
    {
        MapXmlContainer container = MapSaveLoad.MapBuildLoad(nome + ".xml");

        colunas = container.coluns;
        linhas  = container.lines;

        destruirTabuleiroAtual();

        for (int i = 0; i < colunas; i++)
        {
            List <Tile> row = new List <Tile>();
            for (int j = 0; j < linhas; j++)
            {
                Tile tile = ((GameObject)Instantiate(tilePrefab, new Vector3(i - Mathf.Floor(linhas / 2), 0, -j + Mathf.Floor(colunas / 2)), Quaternion.Euler(new Vector3()))).GetComponent <Tile>();
                tile.transform.parent   = mapHolder.transform;
                tile.noConstrutor       = true;
                tile.posicaoNoTabuleiro = new Vector2(i, j);
                tile.setarTipoeVisual((TileType)container.tiles.Where(x => x.locX == i && x.locY == j).First().id);
                tile.setarMecanicaeVisual((TileMechanic)container.tiles.Where(x => x.locX == i && x.locY == j).First().mechanic);
                row.Add(tile);
            }
            tabuleiro.Add(row);
        }
        foreach (UnidadeXml uXML in container.unidadesNoTabuleiro)
        {
            UnidadeNoTabuleiro unidadeNova = ((GameObject)Instantiate(unidadePrefab, tabuleiro[uXML.locX][uXML.locY].transform.position + 1 * Vector3.up, Quaternion.Euler(new Vector3(90, 0, 0)))).GetComponent <UnidadeNoTabuleiro>();
            unidadeNova.gridPosition     = new Vector2(uXML.locX, uXML.locY);
            unidadeNova.unidadeAssociada = BancoDeDados.instancia.retornarUnidade(uXML.id);
            unidadeNova.gameObject.GetComponent <Animator>().runtimeAnimatorController = controladoresInimigos[(int)unidadeNova.unidadeAssociada.classe];
            //Aqui so entrarão unidades que vão estar contra você no jogo, então sempre serão inimigos
            unidadeNova.inimigo = true;
            tabuleiro[uXML.locX][uXML.locY].ocupado = true;
            unidadesNoTabuleiro.Add(unidadeNova);
        }
        configurarCameraParaNovoTabuleiro(tabuleiro);
    }
コード例 #16
0
    public void artilleryMove(UnidadeNoTabuleiro target, Tile tileDeOrigem)
    {
        Tile tileDoTarget = BatalhaController.instancia.tabuleiro[(int)target.gridPosition.x][(int)target.gridPosition.y];

        //Primeiro Caso, Alvo em Range e não precisa se mover a ele, portanto double attack
        gridDeAtaque    = true;
        gridDeMovimento = false;

        if (TileHighlight.FindHighlight(tileDeOrigem, unidadeAssociada.status[4]).Contains(tileDoTarget))
        {
            if (preparada)
            {
                BatalhaController.instancia.highlightTilesAt(tileDeOrigem.posicaoNoTabuleiro, BatalhaController.instancia.TileGridAtaque, unidadeAssociada.status[4]);
                BatalhaController.instancia.atacarComPlayerAtual(tileDoTarget);
            }
            else
            {
                BatalhaController.instancia.unidadeDeArtilhariaSePreparou();
            }
        }
        else
        {
            gridDeAtaque    = false;
            gridDeMovimento = true;
            Classe classeDaUnidade = unidadeAssociada.classe;

            if (!preparada)
            {
                BatalhaController.instancia.unidadeDeArtilhariaSePreparou();
            }
            else
            {
                BatalhaController.instancia.AdministrarFimDeAcao();
            }
            gridDeMovimento = false;
        }
    }
コード例 #17
0
    public void TrackDownEnemies(UnidadeNoTabuleiro target, Tile tileDeOrigem)
    {
        Tile tileDoTarget = BatalhaController.instancia.tabuleiro[(int)target.gridPosition.x][(int)target.gridPosition.y];

        //Primeiro Caso, Alvo em Range e não precisa se mover a ele, portanto double attack
        gridDeAtaque    = true;
        gridDeMovimento = false;

        if (TileHighlight.FindHighlight(tileDeOrigem, unidadeAssociada.status[4]).Contains(tileDoTarget))
        {
            BatalhaController.instancia.highlightTilesAt(tileDeOrigem.posicaoNoTabuleiro, BatalhaController.instancia.TileGridAtaque, unidadeAssociada.status[4]);
            BatalhaController.instancia.atacarComPlayerAtual(tileDoTarget);
        }
        //Segundo caso, Alvo não está em range, mas pode ser alcançado com um movimento
        else
        {
            gridDeAtaque    = false;
            gridDeMovimento = true;
            BatalhaController.instancia.highlightTilesAt(tileDeOrigem.posicaoNoTabuleiro, BatalhaController.instancia.TileGridMovimento, unidadeAssociada.status[3]);
            //Pegar todos os tiles de movimento possivel
            List <Tile> movementTiles = TileHighlight.FindHighlight(tileDeOrigem, unidadeAssociada.status[3]);
            //Verificar se algums dos tiles está a uma distancia que a unidade pode atacar após mover
            if (movementTiles.Any(tile => Vector2.Distance(tile.posicaoNoTabuleiro, tileDoTarget.posicaoNoTabuleiro) == unidadeAssociada.status[4]))
            {
                //Pegar qualquer tile cuja distancia para o alvo seja igual ao range maximo do seu ataque
                //List<Tile> possiveisParaMovimento = movementTiles.Where(tile => Vector2.Distance(tile.posicaoNoTabuleiro, tileDoTarget.posicaoNoTabuleiro) == unidadeAssociada.status[4]).ToList();
                //float maiorDistancia = movementTiles.Max(tile => Vector2.Distance(tileDoTarget.posicaoNoTabuleiro, tile.posicaoNoTabuleiro));
                Tile tileParaMoverMaisProximo = movementTiles.First(tile => Vector2.Distance(tile.posicaoNoTabuleiro, tileDoTarget.posicaoNoTabuleiro) == unidadeAssociada.status[4]);
                BatalhaController.instancia.verificarTentativaDeMovimento(tileParaMoverMaisProximo);
                alvoDeAtaque = target;
            }
            //Terceiro caso, Muito longe para atacar o inimigo depois do movimento, porntanto so se importar com chegar o mais proximo possivel
            else
            {
                List <Tile> CaminhoMaisCurtoParaOAlvo = null;
                foreach (Tile tile in tileDoTarget.vizinhos)
                {
                    if (!tile.ocupado)
                    {
                        CaminhoMaisCurtoParaOAlvo = TilePathFinder.FindPathTilesReturn(tileDeOrigem, tile); break;
                    }
                }

                if (CaminhoMaisCurtoParaOAlvo == null)
                {
                    BatalhaController.instancia.proximaVez();
                    return;
                }

                for (int i = CaminhoMaisCurtoParaOAlvo.Count - 1; i >= 0; i--)
                {
                    if (movementTiles.Contains(CaminhoMaisCurtoParaOAlvo[i]))
                    {
                        BatalhaController.instancia.verificarTentativaDeMovimento(CaminhoMaisCurtoParaOAlvo[i]);
                        break;
                    }
                }
                //movementTiles.Any(tile => CaminhoMaisCurtoParaOAlvo.Contains(tile));
            }
            gridDeMovimento = false;
        }
    }
コード例 #18
0
    //Esse highlight vai "atirar" pra todo lado, sem um destino especifico, apenas indo até os pontosDeMovimento deixarem
    public static List <Tile> FindHighlight(Tile tileDeOrigem, int pontosDeMovimento)
    {
        List <Tile>        closed          = new List <Tile>();     //aqui são aqueles Tiles que ja foram "computados" e que vão voltar pro BatalhaController
        List <TilePath>    open            = new List <TilePath>(); //Tiles que ainda não foram processados
        UnidadeNoTabuleiro unidadeAtual    = BatalhaController.instancia.unidadesNoTabuleiro[BatalhaController.instancia.unidadeAtualIndex];
        TilePath           caminhoDeOrigem = new TilePath();        //Começando um um novo caminho

        caminhoDeOrigem.addTile(tileDeOrigem);                      //Esse caminho parte da origem

        open.Add(caminhoDeOrigem);                                  //Guardando esse caminho nas tiles opens, porque se tu der closed na origem so vai da pra fazer o primeiro caminho

        while (open.Count > 0)                                      //Enquanto houver tiles ainda não processados....
        {
            TilePath atual = open[0];
            open.Remove(open[0]);
            if (closed.Contains(atual.ultimoTile))
            {
                continue;                                              //Se esse tile ja foi fechado, não há porque computar
            }
            if (atual.custoDoCaminho > pontosDeMovimento + 1)
            {
                continue;                                                         //Se acabou os pontos de movimento
            }
            closed.Add(atual.ultimoTile);
            foreach (Tile t in atual.ultimoTile.vizinhos)
            {
                if (t.instransponivel)
                {
                    continue;
                }
                if ((t.ocupado && !unidadeAtual.gridDeAtaque))
                {
                    continue;
                }
                if (unidadeAtual.gridDeMovimento && t.classesRestritas.Contains(unidadeAtual.unidadeAssociada.classe))
                {
                    continue;
                }
                TilePath newTilePath = new TilePath(atual);
                newTilePath.addTile(t);
                open.Add(newTilePath);
            }
        }
        //Salvador, aqui vai verificar se caso os pontos de movimento forem muito poucos, adicionar todos os vizinhos
        //da origem pra evitar atolamento, isso não ignora tiles instraponiveis ou ocupados, apenas o custo da caminho
        if (unidadeAtual.gridDeMovimento)
        {
            //Checar se tem algo na lista de tiles além dos vizinhos do tile de origem
            //Caso tenha e porque ele pode ser mover em alguma direção além dessa sem estar atolado
            if (closed.Count == 0 || closed.Any(x => tileDeOrigem.vizinhos.Any(y => x != y)))
            {
                foreach (Tile vizinho in tileDeOrigem.vizinhos)
                {
                    if (vizinho.instransponivel || vizinho.ocupado ||
                        vizinho.classesRestritas.Contains(unidadeAtual.unidadeAssociada.classe))
                    {
                        continue;
                    }
                    closed.Add(vizinho);
                }
            }
        }


        closed.Remove(tileDeOrigem);
        return(closed);
    }
コード例 #19
0
 public void focarNoPlayer(UnidadeNoTabuleiro playerAFocar)
 {
     transform.position = playerAFocar.transform.position + Vector3.up * 5;
     //this.GetComponent<Camera>().orthographicSize = 2;
 }
コード例 #20
0
    //Essa unidade está procurando alguém para entrar em confronto
    public void DecidirAcao()
    {
        //List<UnidadeNoTabuleiro> unidadesNoCampo = BatalhaController.instancia.unidadesNoTabuleiro;
        //List<UnidadeNoTabuleiro> alvosPrioritarios = BatalhaController.instancia.alvosPrioritarios;
        List <List <Tile> > tabuleiro = BatalhaController.instancia.tabuleiro;
        Tile tileAtual = tabuleiro[(int)gridPosition.x][(int)gridPosition.y];

        //Unidade está com problemas, retirar da batalha pra evitar mais casualidades
        if (unidadeAssociada.status[13] <= 10 || unidadeAssociada.status[15] <= 10 ||
            unidadeAssociada.status[1] <= (unidadeAssociada.status[0] * 25) / 100)
        {
            Tile tileARetirar = retiradaDaBatalhaDaAI(tileAtual);
            AIfazAcaoEspecial = true;
            if (tileARetirar != tileAtual)
            {
                BatalhaController.instancia.verificarTentativaDeMovimento(tileARetirar);
            }
            else
            {
                StartCoroutine(BatalhaController.instancia.RetiradaDaBatalha(this));
            }
            return;
        }
        AIfazAcaoEspecial = false;

        if (alvoDeAtaque == null || !alvoDeAtaque.viva)
        {
            if (unidadeAssociada.status[4] > 1)
            {
                alvoDeAtaque = ProcurarMaisProximoInimigo();
            }
            else
            {
                alvoDeAtaque = ProcurarMaisProximoInimigoDeCloseCombat();
            }
        }
        if (artilharia)
        {
            artilleryMove(alvoDeAtaque, tileAtual);
        }
        else
        {
            TrackDownEnemies(alvoDeAtaque, tileAtual);
        }
        //A IA vai sempre atrás de alvos prioritarios, mesmo se eles estiverem longe da linha de defesa

        /*if(alvosPrioritarios.Count != 0 && unidadesNoLimite.Intersect(alvosPrioritarios).Any()){
         *  List<UnidadeNoTabuleiro> alvosPrioritariosEmRange = unidadesNoLimite.Intersect(alvosPrioritarios).ToList();
         *  TrackDownEnemies(alvosPrioritarios.First(uni => uni.gridPosition.x == alvosPrioritarios.Max(coluna => coluna.gridPosition.x)),tileAtual);
         * }
         * //Sem nenhum alvo prioritario a AI vai verificar se está muito longe da linha defensiva
         * else if (gridPosition.x > colunaDeDefesa+5 || gridPosition.x < colunaDeDefesa-5){
         *  Debug.Log("Estamos fora da linha defensiva!");
         *  ReestruturarLinhaDefensiva(colunaDeDefesa,tileAtual);
         * }
         * //Estando na linha defensiva e sem nennhum alvo prioritario, ela vai atrás de atacar alguém
         * else{
         *  //Pegar o alvo com a menor distancia para com essa unidade de IA, o foco e atacar 2 vezes sempre que possivel
         *  UnidadeNoTabuleiro alvoMaisProximo = unidadesNoLimite.FirstOrDefault(uni => Vector2.Distance(tileAtual.posicaoNoTabuleiro, new Vector2(uni.gridPosition.x, uni.gridPosition.y)) == unidadesNoLimite.Min(min => Vector2.Distance(tileAtual.posicaoNoTabuleiro, new Vector2(min.gridPosition.x, min.gridPosition.y))));
         *  //Se tiver um alvo qualquer em Range
         *  if (alvoMaisProximo!=null) { TrackDownEnemies(alvoMaisProximo,tileAtual); }
         *  //Nenehum inimigo na area de influencia, ja está na linha de defesa, pular turno
         *  else {
         *      Debug.Log("Nada pra AI fazer, proximo");
         *      BatalhaController.instancia.proximaVez();
         *  }
         * }
         */
    }