Django Wars [Parte 27]: É Luta, briga, fight, x1 no rio, cacete comendo no centro…

O Django Wars foi idealizado e desenvolvido no Django 1.4. Algumas funcionalidades aqui descritas podem não funcionar ou funcionar de forma diferente em outras versões do Django

Agora é a hora boa, a hora que nosso site vai separar os meninos dos homens.
Os homens estão no trabalho e os meninos estão em casa atacando os coitados que estão ocupados…

Primeiro, a url que leva ao coro comer no centro.

url(r'^alvos/atacar/(\d+)/$', djangowars.views.luta.atacar),

Agora que vem a parte boa, a view que calcula o fight.
Vou colocá-la no arquivo views/luta.py:

#view da luta
def atacar(request, alvo_id):
    if not request.user.is_authenticated():
        return redirect('pagina_de_login')
    
    
    #verifica se esta sendo passado um alvo valido
    alvo = get_object_or_404(Player, pk=alvo_id)
    
    
    #pega o nosso jogador da sessao
    jogador = request.user.get_profile()
    
    
    #verifica se a experiencia do alvo eh menor que 60% da experiencia do atacante
    if jogador.experiencia * 0.6 > alvo.experiencia:
        return redirect(alvos)
    
    
    #atualiza o alvo e o jogador
    alvo.refresh()
    jogador.refresh()
    
    
    #verifica se o nosso jogador possui raiva para atacar
    if jogador.raiva_atual == 0:
        return redirect(alvos)
    
    
    #verifica se o nosso jogador esta "morto"
    if jogador.hp == 0:
        return redirect(alvos)
    
    #verifica se o alvo esta 'morto'
    if alvo.hp == 0:
        return redirect(alvos)
    
    
    #salva o hp inicial do jogador e do alvo para fazer um pequeno relatorio no final
    jogador_hp = jogador.hp
    alvo_hp = alvo.hp
    
    
    #pega o valor da arma do jogador
    if jogador.arma_ativa:
        jogador_arma = jogador.arma_ativa.poder
    else:
        jogador_arma = 1
    
    #pega o valor da armadura do jogador
    if jogador.armadura_ativa:
        jogador_armadura = jogador.armadura_ativa.poder
    else:
        jogador_armadura = 1
    
    
    #pega o valor da arma do alvo
    if alvo.arma_ativa:
        alvo_arma = alvo.arma_ativa.poder
    else:
        alvo_arma = 1
    
    #pega o valor da armadura do alvo
    if alvo.armadura_ativa:
        alvo_armadura = alvo.armadura_ativa.poder
    else:
        alvo_armadura = 1
    
    
    #agora o bicho vai pegar!
    #a luta dura 5 turnos
    for turno in [1, 2, 3, 4, 5]:
        #primeiro o jogador ataca
        ataque = randint(jogador.ataque/3, jogador.ataque)
        defesa = randint(alvo.defesa/3, alvo.defesa)
        
        #calcula o dano
        dano = ataque * jogador_arma - defesa * alvo_armadura
        
        if dano > 0:
            alvo.hp = alvo.hp - dano
        
        
        #agora o alvo ataca
        ataque = randint(alvo.ataque/3, alvo.ataque)
        defesa = randint(jogador.defesa/3, jogador.defesa)
        
        #calcula o dano
        dano = ataque * alvo_arma - defesa * jogador_armadura
        
        if dano > 0:
            jogador.hp = jogador.hp - dano
        
        
        #verifica se alguem morreu no combate
        if jogador.hp == 0 or alvo.hp == 0:
            break
    
    
    #descobrindo quem perdeu
    if jogador.hp == 0:
        vitoria = False
    elif alvo.hp == 0:
        vitoria = True
    elif alvo_hp - alvo.hp > jogador_hp - jogador.hp:
        vitoria = True
    else:
        vitoria = False
    
    
    #se o jogador ganhou, tira dinheiro do alvo e da ao jogador
    if vitoria:
        grana = alvo.carteira * ( randint(10, 90)/100.0 ) #entre 10% e 90% do valor da carteira
        grana = round(grana)
        
        alvo.carteira = alvo.carteira - grana
        jogador.carteira = jogador.carteira + grana
        
        #ganha 10% da experiencia do adversario
        jogador.experiencia = jogador.experiencia + alvo.experiencia * 0.1
    else:
        grana = jogador.carteira * ( randint(10, 90)/100.0 ) #entre 10% e 90% do valor da carteira
        grana = round(grana)
        
        alvo.carteira = alvo.carteira + grana
        jogador.carteira = jogador.carteira - grana
        
        #ganha 10% da experiencia do adversario
        alvo.experiencia = alvo.experiencia + jogador.experiencia * 0.1
    
    
    # o nosso atacante perde 1 de raiva
    jogador.raiva_atual = jogador.raiva_atual - 1
    
    
    #verifica se alguem deu level up
    alvo.level_up()
    jogador.level_up()
    
    
    #salva todas as alteracoes no banco de dados
    alvo.save()
    jogador.save()
    
    
    #exibe o template com o resultado da luta
    return render_to_response("atacar.html", {"player": jogador,
                                              "vida": jogador.vida * 10,
                                              "alvo": alvo,
                                              "vitoria": vitoria,
                                              "grana": grana,
                                              "jogador_hp": jogador_hp,
                                              "alvo_hp": alvo_hp})

É grande, mas é bem fácil de compreender:
1 – a gente verifica se está sendo passado um jogador válido
2 – verifica se o alvo tem o mínimo de experiência requisitada. Assim, se algum jogador tentar criar uma URL na mão, não vai atacar um jogador mais fraco.
3 – verifica se tem raiva o suficiente para atacar
4 – verifica se nem o alvo e nem o jogador estão mortos. Morto não pode atacar e nem ser atacado, a não ser que sejam zumbis ou vampiros ou mumias.
5 – salva quanto de hp cada um tem antes de começar a luta. Fazemos isso para saber quem perdeu mais hp no final do combate.
6 – pegamos o poder da arma e da armadura do jogador e do alvo.
7 – pequeno loop da luta. as lutas duram 5 turnos
8 – verifica quem venceu. quem morrer, perde. quem perder mais hp, perde
9 – calcula a quantidade de dinheiro que o vencedor rouba do perdedor
10 – tira um ponto de raiva do atacante
11 – verifica se alguem deu level_up
12 – salva tudo
13 – exibe template.

O loop da luta é bem mobral.
Randomiza um número entre um terço do atributo ataque e o ataque inteiro e multiplica esse valor na arma.
Faz o mesmo para a defesa e multiplica o valor na armadura.
A diferença entre o resultado do ataque e o resultado da defesa é o dano que o atacante causa no defensor.
Sussa demais, né?
Eu poderia tentar algo mais parecido com sistemas de RPG de mesa, mas queremos um jogo simples.

Para finalizar, mostramos o template.
atacar.html

<div class="container">
    <p>
        Informações do usuário:
        Nível {{  player.nivel }}
        |
        Energia {{  player.energia_atual }}/{{ player.energia }}
        |
        Raiva {{ player.raiva_atual }}/{{ player.raiva }}
        HP: {{ player.hp }}/{{ vida }}
        |
        Carteira {{ player.carteira }}
    </p>

    <!--lista de alvos-->
    Você atacou <b>{{ alvo.user.username }}</b><br />
    Resultado da luta: {% if vitoria %}<b>VITÓRIA!</b>{% else %}<b>DERROTA!</b>{% endif %}<br />
    Seu Hp inicial: <b>{{ jogador_hp }}</b>, Hp final: <b>{{ player.hp }}</b><br />
    Hp inicial de {{ alvo.user.username }}: <b>{{ alvo_hp }}</b>, Hp final: <b>{{ alvo.hp }}</b><br />
    
    {% if vitoria %}
        Você recebeu: <b>{{ grana }}</b><br />
    {% else %}
        Você perdeu: <b>{{ grana }}</b><br />
    {% endif %}

</div> <!-- /container -->

O código fonte de toda essa gambiarra desse maravilhoso jogo encontra-se em:
https://github.com/frenetic/django-wars

5 thoughts on “Django Wars [Parte 27]: É Luta, briga, fight, x1 no rio, cacete comendo no centro…

    1. na verdade, tá quase certo

      na linha 109 era pra ser
      alvo_arma = alvo.arma_ativa.poder

      mas ao invés de escrever “alvo_arma” eu só escrevi “alvo”.
      Que burro, dá zero pra mim…

      Vou corrigir aqui no post e depois coloco no github

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *