public function executarTiro($char, $mao, $posicao, $redutor = 0, $danoExtra = 0)
 {
     $nh = 0;
     $arma = null;
     if ($mao == MAO_DIREITA && $this->maoDireitaArmada()) {
         $arma = $this->mao_direita;
     } elseif ($this->maoEsquerdaArmada()) {
         $arma = $this->mao_esquerda;
     }
     $nh = $this->getNH($arma->getPericiaSlug());
     $distancia = Mapa::ataqueDistancia($this, $char);
     $redutor += $distancia->visibilidade;
     $mensagem = $this->getNome() . " atirou em " . $char->getNome();
     $jogada = Dado::testeHabilidade($nh, $redutor);
     switch ($jogada->resultado) {
         case SUCESSO_DECISIVO:
             $sentido = Golpe::calcularSentido($char->getPos(), $this->getPos());
             $golpe = new GolpeTiro($this, $mao, $arma, $arma->getTipo(), $posicao, $sentido, $dano_extra, $distancia->distancia);
             $mensagem .= ' e o atinguiu com um golpe fuminante! ' . Dado::descreverJogada($nh, $redutor, $jogada->jogada);
             Sessao::escreverlog($mensagem, $this->id_original, LOG_SUCESSO_DECISIVO);
             $char->danoDeGolpe($golpe, true);
             break;
         case SUCESSO:
             $sentido = Golpe::calcularSentido($char->getPos(), $this->getPos());
             $golpe = new GolpeTiro($this, $mao, $arma, $arma->getTipo(), $posicao, $sentido, $dano_extra, $distancia->distancia);
             $mensagem .= ' e o atinguiu! ' . Dado::descreverJogada($nh, $redutor, $jogada->jogada);
             Sessao::escreverlog($mensagem, $this->id_original, LOG_ATAQUE);
             $sentido = Mapa::getSentido2DDefesa($this, $char);
             if ($sentido == SENTIDO_COSTAS) {
                 $mensagem = $char->getNome() . ' foi atinguido nas costas e não pode se defender!';
                 Sessao::escreverlog($mensagem, $this->id_original, LOG_FALHA);
                 $char->danoDeGolpe($golpe);
             } elseif (!$char->podeDefender()) {
                 $mensagem = $char->getNome() . ' não pode se defender!';
                 Sessao::escreverlog($mensagem, $this->id_original, LOG_FALHA);
                 $char->danoDeGolpe($golpe);
             } elseif ($char->getAutomatico()) {
                 $char->autodefesa($golpe);
             } else {
                 $char->atingido($golpe);
             }
             break;
         case FALHA:
             $mensagem .= ' mas não atinguiu no ' . $this->descreverMembro($posicao) . '.' . Dado::descreverJogada($nh, $redutor, $jogada->jogada);
             Sessao::escreverlog($mensagem, $this->id_original, LOG_FALHA);
             break;
         case FALHA_CRITICA:
             $mensagem = 'Falha Crítica!' . Dado::descreverJogada($nh, $redutor, $jogada->jogada);
             Sessao::escreverlog($mensagem, $this->id_original, LOG_FALHA_CRITICA);
             break;
     }
     if (!$char->estaVendo($this)) {
         $mensagem = $char->getNome() . ' não tinha visto ' . $this->getNome() . ". Agora ele viu.";
         Sessao::escreverlog($mensagem, $char->getIdOriginal());
         $char->marcarVisibilidade($this);
     }
 }