Fiz essa magia (um Blink) para tentar mostrar um pouco de jass para um padawan meu. Espero que ajude mais pessoas também.
Leia Mais...
library Exemplo1 struct MyStruct // Meu primeiro código static method onInit takes nothing returns nothing call BJDebugMsg("Hello World!") endmethod endstruct endlibraryEntão essa nossa struct apenas mostrava uma mensagem ("Hello World") quando o jogo começava. Vamos ir além dessa vez. Antes de prosserguimos gostaria que vocês entendessem que uma struct é um "objeto". Um objeto pode ter caracteristicas e comportamentos e além disso um objeto é um tipo de dado (assim como unit, effect, player, group, etc). O method onInit, por exemplo, é um "comportamento inicial" da nossa struct. Veja:
library Exemplo2 struct Object // Agora nossa struct chama Object // nosso Object tem um comportamento (method) stop. method stop takes nothing returns nothing call BJDebugMsg("object paused") call TriggerSleepAction(10) call BJDebugMsg("object unpaused!") endmethod static method onInit takes nothing returns nothing local Object obj = Object.create() // cria um objeto do tipo Object call obj.stop() call obj.destroy() //destroi o objeto endmethod endstruct endlibraryNo código acima a struct Object tem um method (comportamento) chamado stop. Esse method faz a mensagem object paused aparecer na tela e executa uma function chamada
TriggerSleepAction
, essa function é o famoso wait do GUI. O numero 10 indicado entre parenteses é o numero de segundos que pausará, no caso 10 segundos. Logo depois dos 10 segundos do wait, mostra a mensagem object unpaused. Percebeu que aquele method não tem static na declaração dele? Isso quer dizer que aquele method só pode ser executado de um Object "criado" ou como dizemos em programação instanciado.local Object obj = Object.create()O que fizemos ali foi criar uma variável para guardar o Object que criamos. O local significa que aquela variavel só vai existir dentro daquele method (no caso, o
onInit
). Object é o tipo da variável (lembra que as struct são tipos?) e por ultimo, obj é apenas o nome da nossa variável local. Agora sim, Object.create() isso é que cria um objeto (instancia uma struct). Voce poderia chamar isso sem colocar numa variavel:call Object.create()Mas voce não poderia acessar aquele objeto, pois ele não teria um registro (uma variável). Quando executamos obj.stop(), fizemos o objeto criado que estava guardado na variavel obj chamar o method stop dele. O ponto final entre o nome e o method é importante, nunca esqueçam dele. Logo em seguida, destruímos nosso objeto com o
obj.destroy()
. O comando destroy libera o espaço daquela instancia da struct. "Cada struct" só pode ter 8190 instancias, ou seja, só pode ser criada 8190 vezes de uma vez. Então Para completar a aula ensinarei a criar variáveis locais. É facil:local tipo-da-variavel nome-da-variavelExemplos:
local unit caster local effect efeito local timer tempo local player jogador1 local integer iVoce pode "setar" o valor dela na criação ou durante o method, como qualquer variável:
set caster = GetTriggerUnit() set i = 1348Mas cuidado, as variáveis locais podem causar leak quando você não remover o conteúdo delas. Apenas as variaveis do tipo
handle
podem causar leak. Handle é tudo que não é integer, real, boolean e string. Ou seja, unit
, effect
, timer
, group
, force
, etc. Dê uma olhada no documento Common.j
dentro do MPQ do war3 para saber mais. E qualquer variável do tipo de uma struct também não causa leak, voce só precisa destruir aquela instancia quando não precisa mais dela. Mas como remove um conteudo de uma handle? Apenas no final seu method dê set para null
. Veja:method XXX takes nothing returns nothing local unit u = GetTriggerUnit() local integer i = 12 // integer não causa leaks // código restante do method // ... set u = null endmethodEspero que essa aula tenha sido muito esclarecedora.
- Consertado um bug no torrent que fazia ele não explodir.
- Consertado um bug no torrent que fazia ele abrir visão da área permanentemente.
- Guia de configuração para Ravege e Avalanche adicionado.
- Trigger de configuração do Torrent adicionado.
- Damage do Torrent agora pode ser dividido em duas partes.
- Torrent agora causa slow e libera visão da área da explosão (como no DotA).
- Adicionado Trigger de "Respawn de creeps" e "Remoção de dummies".
- Torrent (Kunkka)Lista de Magias que estão por vim:
- Avalanche (Tiny)
- Ravege (Tidehunter)
- Meat Hook (Pudge)Changelogs:
- Chronosphere (Void)
- Fissure (Earthshaker)
- Consertado um bug no torrent que fazia ele não explodir.
- Consertado um bug no torrent que fazia ele abrir visão da área permanentemente.
- Guia de configuração para Ravege e Avalanche adicionado.
- Trigger de configuração do Torrent adicionado.
- Damage do Torrent agora pode ser dividido em duas partes.
- Torrent agora causa slow e libera visão da área da explosão (como no DotA).
- Adicionado Trigger de "Respawn de creeps" e "Remoção de dummies".
- Criação do spellpack.
Vendo essa tabela imaginem uma trigger que roda a cada 1 segundo. Toda vez que ela roda ela busca todos os index, do primeiro (1) ao ultimo (3), Fazendo o CASTER[index] causar o DAMAGE_PER_SECOND[index] ao TARGET[index]. Assim quando o index ser 1, o CASTER[1] (Paladin) vai causar DAMAGE_PER_SECOND[1] (30) ao TARGET[1] (Death Knight), quando ser 2 seria... ah, só olhar na tabela.SW_indexCount (Integer – Default Value: 0)Obs: outras variáveis vão aparecer no tutorial, tipo TempUnit. Com essas você pode usar alguma que já tenha ou crie elas se precisar.
SW_newIndex (Integer – Default Value: 0)
SW_MUI_indexExists (Boolean – array – Size: 1)
SW_MUI_waveCount (Integer – Default Value: 0)
SW_MUI_Dummy (Unit – array – Size: 1)
SW_MUI_Distance (Real – array – Size: 1)
SW_Loop (Integer)
Bom essa será nossa segunda aula, sugiro que leiam ela como muita atenção.
library Exemplo1
struct MyStruct
// Meu primeiro código
static method onInit takes nothing returns nothing
call BJDebugMsg("Hello World!")
endmethod
endstruct
endlibrary
Olha ai, essa function (que é quase a mesma coisa que um method) requer uma string: takes string msg. Uma string é um conjunto de caracteres, quem conhece de trigger editor sabe disso. O comando BJDebugMsg exibe a string msg na tela por um minuto. Só!function BJDebugMsg takes string msg returns nothing
call BJDebugMsg("Game Over")
As coisas escritas dentro dos parenteses são os parametros do comando, o takes dela. Quando um comando tem takes nothing você precisa apenas deixar os parenteses vazios.
Quando um comando tem algum returns, voce pode preferir guarda o valor do retorno dela. O comando CreateTimer, por exemplo, é takes nothing returns timer. Ou seja ele retorna um timer, um timer que acabou de ser criado. Faz de conta que voce tem uma variável chamada TempTimer e você quer guarda um novo timer nela:call CreateTimer() // um comando que cria um countdown timer.
call CreateTimer // assim daria erro, faltou os parenteses.
set TempTimer = CreateTimer()
// O comando CreateTimer foi chamado e seu valor de retorno
// foi guardado na variavel TempTimer
Events
Unit - A unit Acquires an item
Conditions
Or - Any (Conditions) are true
Conditions
(Item-type of (Item being manipulated)) Equal to Item 1
(Item-type of (Item being manipulated)) Equal to Item 2
ActionsEfeitos:
-------- Primeiro confira se a unidade tem os itens que precisa --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Triggering unit) has an item of type Item 1) Equal to True
((Triggering unit) has an item of type Item 2) Equal to True
Then - Actions
-------- Se ela tiver, remova os itens de requerimento --------
Item - Remove (Item carried by (Triggering unit) of type Item 1)
Item - Remove (Item carried by (Triggering unit) of type Item 2)
-------- Adicione o item novo --------
Hero - Create Item 3 and give it to (Triggering unit)
Else - Actions
-------- Cria um efeito na unidade --------
Special Effect - Create a special effect attached to the origin of (Triggering unit) using Abilities\Spells\Items\AIam\AIamTarget.mdl
-------- Destrua o efeito, para não causar lag --------
Special Effect - Destroy (Last created special effect)
Trigger ProntaEspero do fundo do coração que você tenha entendido tudinho. Caso não tenha encontrado alguma ação ou condição, poste que eu te ajudo.
Events
Unit - A unit Acquires an item
Conditions
Or - Any (Conditions) are true
Conditions
(Item-type of (Item being manipulated)) Equal to Item 1
(Item-type of (Item being manipulated)) Equal to Item 2
Actions
-------- Primeiro confira se a unidade tem os itens que precisa --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Triggering unit) has an item of type Item 1) Equal to True
((Triggering unit) has an item of type Item 2) Equal to True
Then - Actions
-------- Se ela tiver, remova os itens de requerimento --------
Item - Remove (Item carried by (Triggering unit) of type Item 1)
Item - Remove (Item carried by (Triggering unit) of type Item 2)
-------- Adicione o item novo --------
Hero - Create Item 3 and give it to (Triggering unit)
-------- Cria um efeito especial na unidade (isso é opcional) --------
Special Effect - Create a special effect attached to the origin of (Triggering unit) using Abilities\Spells\Items\AIam\AIamTarget.mdl
Special Effect - Destroy (Last created special effect)
Else - Actions
Antes de falar sobre bons jogos você deve saber o que um jogo é em primeiro lugar. Há uma quantidade surpreendente de discussões sobre esta questão e há muitas definições diferentes. É mais fácil dizer o que um jogo não é.
Um jogo é uma atividade (vamos dizer assim) em que um ou mais jogadores tomam decisões através do controle de objetos do jogo e de recursos, em busca de um objetivo.
Note que a definição não fala sobre gráficos ou efeitos sonoros (no caso de jogos de computador). Tais aspectos, obviamente, desempenham um papel importante para torna-los jogos atraentes, mas não são os aspectos essenciais dos jogos. Vejamos os ingredientes diferentes da definição em alguns detalhes. Focando sempre nos jogos de video game e computador.
Você já sabe o que é um jogo, pelo menos um de computador. No entanto lá não fala quando um jogo é bom. Tudo citado acima são elementos que um jogo bom de ter, porém faltou dizer que a criatividade e a inovação são igualmente importantes.
Como eu disse, este tutorial deve ter-lhe dado uma idéia das coisas que importam ao tentar criar um bom jogo de computador. Mas no final a melhor maneira de aprender é você fazer um jogo e criticar seus próprios resultados.
Outro conselho é aprender com os erros de outras pessoas. Sempre que você planejar fazer um determinado tipo de jogo, olhe para os jogos similares. Tente jogá-los e ver o que eles fizeram certo e o que eles fizeram de errado. É muito comum ainda ver alguns jogos repitindo os erros de outros jogos.
Essa function adiciona uma quantidade de hp (amount) a unidade desejada (whichUnit). Simples!function UnitAddLife takes unit whichUnit, real amount returns nothing
library AddLife
// Add Life System
// Criado por "Bills"
// Versão: 1.2
//=====================================
// Como implementar:
// Crie uma nova trigger,
// converta ela para custom script,
// salve seu mapa,
// feche-o,
// reabra-o
// e apague o ! da linha abaixo.
//! external ObjectMerger w3a AIlz ALBA anam "Life Bonus" ansf "(Bills's AddLife System)" Ilif 1 500000 aite 0
//=====================================================================
//Caso ja tenha essa native declarada, "comenta" a linha abaixo
native UnitAlive takes unit whichUnit returns boolean
private struct AL extends array // struct array não possui method create/destroy
private static constant integer LIFE_BONUS_ABIL = 'ALBA'
private static unit array tempUnit
private static integer index
private static timer timerFunc
private static method removeLifeBonus takes nothing returns nothing
loop
exitwhen (index==0)
call UnitRemoveAbility(tempUnit[index],LIFE_BONUS_ABIL)
if (UnitAlive(tempUnit[index])) then
call SetWidgetLife(tempUnit[index],GetWidgetLife(tempUnit[index]))
endif
set index=index-1
endloop
endmethod
static method unitAddLife takes unit u, real amount returns nothing
set amount=GetWidgetLife(u)+amount
call SetWidgetLife(u,amount)
if (GetWidgetLife(u)<amount) then
call UnitAddAbility(u,LIFE_BONUS_ABIL)
call SetWidgetLife(u,amount)
set index=index+1
set tempUnit[index]=u
call ResumeTimer(timerFunc)
endif
endmethod
private static method onInit takes nothing returns nothing
set index=0
set timerFunc=CreateTimer()
call TimerStart(timerFunc,0.00,false,function thistype.removeLifeBonus)
endmethod
endstruct
function UnitAddLife takes unit u, real amount returns nothing // por compatibilidade
call AL.unitAddLife(u,amount)
endfunction
endlibrary
private constant integer BUFF_CHECKER = 'B000'
Agora mude o valor da variable USE_BUFF_CHECKER para true.local unit udg_UnitEsse udg_ antes do nome da nossa local refere-se as variables criadas em GUI, em outras palavras, criadas naquela caixinha de variables do Trigger Editor. Toda variable criada lá é global e recebe o prefixo "udg_" no nome dela.
Events
Map Initialization
Conditions
Actions
local unit udg_Unit
Create 1 Footman for Player 1 (Red) at (Center of (Playable map area)) facing 0.00 degrees
Set Unit = (Last created unit)
...
Set Unit = No unitPor rasões ainda desconhecidas, apenas uma "global local variable" de cada tipo funciona por trigger. Ou seja, você não pode usar duas varibles do tipo unit em um mesmo trigger pra fazer uma global local das duas, apenas uma funcionaria.