O Boss Que Colhe as Suas Mortes
O Necrolord era um boss com cronômetro: morria, esperava e levantava de novo. Mecanicamente isso é uma barra de vida com passos extras, e nunca fez ninguém jogar diferente. Essa semana ele foi reconstruído em cima de duas mecânicas movidas a dano que punem exatamente aquilo que um jogador de tower defense faz melhor, que é matar muita coisa rápido num ponto só. Essa reforma precisava de um zumbi, então zumbi virou um modificador genérico de inimigo antes.
Zumbi é modificador, não tipo de inimigo
O zumbi é aplicado com a mesma notação com ponto das variantes de imunidade a tipo de dano: splitter.zombie é um splitter que por acaso é zumbi. É ortogonal ao tipo de inimigo, então todo inimigo do jogo ganhou uma forma zumbi de graça.
Um zumbi é renderizado em escala de cinza, é imune a todo status effect, anda a 75% da velocidade base, não usa nenhuma das mecânicas especiais do inimigo original e tem 25% de chance de levantar de novo com 35% de HP quando morre. Todo ponto do código com mecânica especial checa um único predicado isZombie, o que significa que habilidades que eu adicionar mês que vem já vão nascer suprimidas na forma zumbi sem eu precisar lembrar disso. A escala de cinza é pura apresentação: cópias dessaturadas das texturas dos inimigos são montadas uma vez no init. Replicado nos snapshots de co-op e exposto no dbg.spawn pra eu invocar um na hora.
O Necrolord, reconstruído
O HP base foi de 3500 pra 10500, e a auto-ressurreição por tempo foi trocada por duas mecânicas que se alimentam do seu próprio dano:
- Roubo de vida. Ele cura 35% de todo dano causado em inimigos não zumbis perto dele, dentro do
lifestealRadius. Aplicado a partir dodealDamagecontra um cache por frame dos ids de Necrolord, então não custa nada quando não tem nenhum no tabuleiro. - Reanimação. A cada três inimigos que morrem perto dele, um volta como zumbi com metade do HP, do tipo que morreu. O contador de mortes mora no
Enemy.auxTimer.
Zumbis não alimentam o dreno nem são reanimados, e é isso que impede o loop de ser infinito. O contador de reanimação no começo só avançava com kill direto de torre, o que significa que um build cheio de splash nunca disparava a mecânica; agora ele avança com mortes por perto vindas de qualquer fonte, tiro direto, splash e dano ao longo do tempo. O alcance de coleta é 50% maior que o raio de cura, então ele levanta corpo de mais longe do que drena. Toda a matemática está em helpers puros no lib/necrolord.ts, feitos com TDD, e a antiga fila recentDeaths foi embora.
O que isso faz com o jogo: despejar a defesa inteira no bolo de inimigos em volta do boss agora é a pior jogada disponível. Ele cura e depois levanta o que você matou.
Morrer duas vezes de propósito
O boss também trapaceia a morte duas vezes, em 25% e depois 10% do HP máximo, controlado no Enemy.bossRevivesUsed. Acertar a sensação levou três passadas.
Primeira versão: ele voltava na hora, o que parecia bug. Agora uma morte no meio da batalha começa uma animação de dois segundos, quatro ciclos de pulso vermelho de 500ms cada, durante os quais o boss fica totalmente invulnerável e sem poder ser mirado pelas torres. O anel roxo de ressurreição cresce e o novo som de resurrect toca quando a animação acaba e ele levanta de fato, não antes.
Segunda passada consertou os detalhes que quebravam a ilusão: ele continuava andando pelo caminho enquanto estava "morto", e as torres de beam mantinham a trava num alvo que não estava lá. Agora ele congela no lugar e a trava do beam cai.
Terceira: toda morte final de boss (a de verdade) agora dispara um tranco pesado de câmera em 0.9, pro momento ter peso.
A zumbificação acontece no lugar
A primeira implementação da reanimação criava uma entidade zumbi nova na posição da morte. Isso lê como substituição, não como transformação: o inimigo pisca pra fora e um cinza pisca pra dentro.
Agora o inimigo que está morrendo entra numa transição de zumbificação de um segundo, no lugar. Ele congela no caminho e desbota de colorido pra cinza num desenho de duas passadas (o sprite colorido e por cima um overlay cinza com alpha crescente). Durante essa janela as torres não conseguem mirar nele diretamente, mas splash de área ainda alcança e mata, e é essa a contrajogada: você tem um segundo pra negar o levante. Se ele sobreviver, converte ali mesmo, com velocidade reduzida e sem escudo nenhum.
Isso substituiu uma pilha de estado: a chamada de spawn na morte, um conjunto markReanimated/wasReanimated/clearReanimated e um rastreador de animação em tempo de relógio, tudo trocado por um único campo zombifyTimer que tanto os sistemas de simulação quanto o renderer leem direto, serializado no snapshot pro co-op concordar. Inimigos escolhidos pra reanimação também pulam a explosão de partículas normal de morte, já que eles não estão morrendo, e o zumbi novo toca uma transição de 500ms de flash branco pro cinza ao chegar.
Golden Shield no relógio
O boss Golden Shield baixava o escudo em reação aos hits, o que significava que um build de cadência alta descascava ele na hora e um build lento nunca passava. Agora ele roda um ciclo por tempo: escudado e depois exposto por 1.5 segundo (caiu de 3 depois do playtest), independente do que você está atirando. Os dois estados ganharam sheets de sprite dedicados, que chegaram com os dois PNGs salvos nos nomes trocados, então ele aparecia transparente enquanto escudado e opaco enquanto exposto. Exatamente ao contrário, e óbvio no primeiro minuto de jogo.
Shieldbearers, Aegis e um aviso
Três correções menores de boss e elite:
- A regeneração do shieldbearer acumulava a cada frame independente do combate, então o escudo voltava enquanto você atirava nele. Qualquer hit recebido, absorvido ou no HP de verdade, agora zera o timer: ele só recupera uma camada depois de alguns segundos sem dano nenhum entrando.
- O anel de escudo do Aegis era um círculo chapado. Agora tem 1.5 unidade de mundo de diâmetro, começa com 4 pixels de espessura e perde um pixel a cada 2 segundos da janela de 8 segundos, então o anel visivelmente afina conforme o escudo vence. A cada recuperação, um anel grande de 3.5 unidades contrai até o tamanho alvo em meio segundo, como sinal.
- Um aviso de boss chegando. Quando um boss (ou a minhoca) entra na fase, "!! BOSS INCOMING !!" pisca em vermelho alaranjado embaixo do banner de wave, 0.4s aceso e 0.4s apagado, três vezes. É controlado por um timestamp
bossAlertUntilno estado do jogo, sincronizado nos snapshots de co-op igual ao anúncio de wave. Os bosses também passaram a ser desenhados numa passada separada depois dos inimigos normais, então nunca ficam escondidos embaixo da multidão com que chegaram.
Os cinco bosses originais estão todos virando isso aos poucos: uma mecânica que pune um hábito específico, em vez de uma barra de vida grande.
Na próxima: duas torres novas e um cooldown pra estar pegando fogo.