quinta-feira, 19 de novembro de 2009

Criando a Primeira Missão p2 - Apoio Externo (Reforço Inimigo) aéreo e blindado.


Bom Pessoal.
Vamos continuar as explanações acerca de nossa primeira missão. Lembrando que seria ideal que você a baixasse e tivesse em sua máquina para acompanhar. Os arquivos e as explicações para baixar e "instalar" a missão segue aqui (http://ofp2editor.blogspot.com/2009/11/criando-primeira-missao-metralhadoras.html)

O assunto principal deste post serão os Reforços Inimigos vindos das redondezas. E para que um reforço externo funcione adequadamente, ou seja, ele deve ser chamado através de uma trigger ou condição específica do jogo, sair de onde está, se deslocar até o ponto e iniciar o combate. Não é difícil, mas pode envolver diferentes métodos e sempre usando diversos recursos, inclusive funções em script.

Em nosso mapa temos 5 conjuntos reforços, e digo conjunto porque alguns são echelons de infantaria, outros unidades blindadas com tripulação virtual, e outro um echelon de pilotos que irá entrar dentro helicóptero e seguir até o ponto ou rota.
A oeste da Estação de Bombeamento, em D21 X1Y6, temos 4 dos 5 conjuntos totais de grupos e unidades que integrarão o reforço até a Estação de Bombeamento quando ela for atacada.




Note que ao sudoeste, em H20 X4Y3 está o helicóptero com sua tripulação (desembarcada).



O Helicóptero e as infantarias e blindados irão prestar o reforço utilizando métodos diferentes. No o Heli, simplesmente levantará vôo e assumirá uma path para uma rota de patrulha cíclica. Para dar um realismo do tipo "Search and destroy" vamos mexer em doctrine e mood. Já as unidades de infantaria irão simplesmente moverem-se até o alvo utilizando a função OFP:defendPos, que como o próprio nome já diz, manda uma unidade/echelon defender uma posição.

ADENDO: Detectando Destruição de Elementos do Cenário.

Em nossa missão, o reforço terrestre só virá quando o objetivo principal de destruir o tanque de óleo tiver sido cumprido. Apanhei muito e ainda não acertei um método para descobrir se um elemento do mapa está ou não danificado.
Portanto, nessa missão tive que elaborar uma gambiarra. Note que "dentro" do tanque de óleo, deixei várias caixas de munição, cujo estas serão responsáveis por "informar" quando o tanque de óleo foi destruído, pois destruindo o tanque, a caixa de munição dentro dele será destruída por estar "próximo" a explosão.




Para o caso de elementos da palheta Props , o evento onDeath_nomeObjeto não irá servir para nos dizer que o objeto(no caso a caixa de munição) foi destruído. Neste caso, devemos usar a função de evento onPlaceableKill. Nomeei apenas uma das caixas de munição com o nome de municaoOleo que usaremos como condição dentro da função para saber se o que foi destruído foi realmente a caixa de munição e não qualquer outro objeto colocado no cenário. Pois lembre-se, que as funções de evento são genéricas a menos que você identifique o sufixo da função com o nome do objeto, como aqui por exemplo, poderíamos usar onPlaceableKill_municaoOleo.
Mas aqui preferí usar um if dentro da função e comparar com o nome do objeto que foi destruído é "municaoOleo". E caso seja verdadeiro, então move os reforços. A função então fica assim:

function onPlaceableKill(placeable, attacker)
--OFP:displaySystemMessage(placeable);
if placeable == "municaooleo" then
OFP:setObjectiveState("objective2", "COMPLETED");
OFP:setObjectiveState("objExtracao", "IN_PROGRESS");
OFP:displaySystemMessage("Estacao de Oleo destruida.");
OFP:displaySystemMessage("Retirar-se imediatamente. Mantenha-se sem ser detectado");
OFP:startParticleSystem( "FogoOleo1", 0 );
OFP:startParticleSystem( "FogoOleo2", 0 );
OFP:startParticleSystem( "FogoOleo3", 0 );


-- sequencia que move o hei
OFP:mountVehicle("grpHeli", "Heli1", "Any", "OVERRIDE" );
OFP:takeoff("grpHeli");
OFP:defendPos("grpHeli" , victim, 400,"OVERRIDE");
OFP:patrol("grpHeli", "WayHelip", "ECYCLIC", 0, "OVERRIDE");
-- fim da sequencia que move o hei
OFP:disableEvent("onPlaceableKill");
-- Movendo Reforcos vindos do oeste
OFP:defendPos( "grpRefBase1", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "grpRefBase2", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "tankRefBase1", "wpReforco", 400, "OVERRIDE" );
OFP:defendPos( "tankRefBase2", "wpReforco", 400, "OVERRIDE" );
end
end
Caso utilizasse a função de evento onPlaceableKill_municaoOleo, o código ficaria quase idêntico, só que sem o if.
function onPlaceableKill(placeable, attacker)
--OFP:displaySystemMessage(placeable);
OFP:setObjectiveState("objective2", "COMPLETED");
OFP:setObjectiveState("objExtracao", "IN_PROGRESS");
OFP:displaySystemMessage("Estacao de Oleo destruida.");
OFP:displaySystemMessage("Retirar-se imediatamente. Mantenha-se sem ser detectado");
OFP:startParticleSystem( "FogoOleo1", 0 );
OFP:startParticleSystem( "FogoOleo2", 0 );
OFP:startParticleSystem( "FogoOleo3", 0 );


-- sequencia que move o hei
OFP:mountVehicle("grpHeli", "Heli1", "Any", "OVERRIDE" );
OFP:takeoff("grpHeli");
OFP:defendPos("grpHeli" , victim, 400,"OVERRIDE");
OFP:patrol("grpHeli", "WayHelip", "ECYCLIC", 0, "OVERRIDE");
-- fim da sequencia que move o hei
OFP:disableEvent("onPlaceableKill_municaoOleo");
-- Movendo Reforcos vindos do oeste
OFP:defendPos( "grpRefBase1", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "grpRefBase2", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "tankRefBase1", "wpReforco", 400, "OVERRIDE" );
OFP:defendPos( "tankRefBase2", "wpReforco", 400, "OVERRIDE" );

end

Caso utilizasse a função de evento onPlaceableKill_municaoOleo, o código ficaria idêntico, só que sem o if.

Chamando o Reforço

Bom. Já vimos acima um dos casos de ativação de reforço inimigo: a destruição do Tanque de Óleo dentro da estação de bombeamento. Também haverá um outro caso de reforço que é se os jogadores forem detectados, porém isso é feito via um script de controle meio complexo e que será explicado em outro post, no entanto as funções são as mesmas, só irá mudar o local onde elas serão chamadas.
Vamos então entender as instruções da função onPlaceableKill. A primeira é o envio do helicóptero para a rota de patrulha. Segue abaixo o trecho.
-- sequencia que move o hei
OFP:mountVehicle("grpHeli", "Heli1", "Any", "OVERRIDE" );
OFP:takeoff("grpHeli");
OFP:defendPos("grpHeli" , victim, 400,"OVERRIDE");
OFP:patrol("grpHeli", "WayHelip", "ECYCLIC", 0, "OVERRIDE");
-- fim da sequencia que move o hei


A função mountVehicle ordena que o grupo entre dentro do heli.
A função takeoff manda o grupo decolar o heli.
A função defendPos deve ser ignorada, pois aí no código ela será sobrecarregada pela função patrol. O problema é que se vc usar mandar o Heli executar o defendpos, o que acontece é que o heli chega no local, pousa, os pilotos desembarcam e fazem a defesa.. é escroto.
A função patrol manda então helicóptero seguir o path WayHelip.

No caso das unidades terrestre, utilizaremos apenas a função defendPos informando o local, que é um waypoint único(nao é um path) chamado de wpReforco, mas que na verdade poderia ser qualquer objeto ou unidade colocada no mapa, ou até mesmo coordenadas puras (ainda nao testei).
As chamadas das funções defendPos das unidades terrestres ficaram assim:

-- Movendo Reforcos vindos do oeste
OFP:defendPos( "grpRefBase1", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "grpRefBase2", "wpReforco", 300, "OVERRIDE" );
OFP:defendPos( "tankRefBase1", "wpReforco", 400, "OVERRIDE" );
OFP:defendPos( "tankRefBase2", "wpReforco", 400, "OVERRIDE" );

E aí estão as chamadas das funções, informando o nome do grupo que vai prestar o reforço, o local onde o reforço será prestado, e o raio de ação dessas unidades de reforço.
Apenas para complementar o post, você poderia por exemplo colocar essas instruções dentro de uma função de evento onSuspected, que seria chamada quando alguém fosse detectado na missão. Por exemplo:

function onSuspected(victim, suspector)
-- capturando o nome do Echelon do soldado que detectou
local grupoAtaque = getParentEchelon(suspector)

--Verificando se a vítima é uma unidade dos americanos função getSide
-- 0=USMC 1 1=LPA
if (OFP:getSide(victim ) == 0) then
OFP:defendPos( grupoAtaque, victim, 100, "OVERRIDE" );
-- ou ainda a função searchAndDestroy
OFP:searchAndDestroy( grupoAtaque, victim, 100, false, "OVERRIDE" );
end
end


É isso, são diversas as formas que podemos trabalhar com grupos de reforços. Não explorei tudo ainda, mas podemos ainda regular a agressividade e a moral do grupo de reforço para dar uma maior imersão a batalha.
Peço aos leitores que consultem no help as funções citadas aqui hoje para que vcs entendam e passem a conhecer suas características e parâmetros. O help ainda é uma das melhores documentações que encontrei acerca do mission editor.
Por hoje é isso meus caros.


Saudações

Nenhum comentário:

Seguidores