646 lines
17 KiB
C++
646 lines
17 KiB
C++
/***************************************************************************
|
|
alienBlaster
|
|
Copyright (C) 2004
|
|
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
***************************************************************************/
|
|
#include "formation.h"
|
|
#include "enemy.h"
|
|
#include "enemys.h"
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
|
|
Formation::Formation( FormationTypes whichFormation, Vector2D centerAtStart,
|
|
Vector2D startVel, int nrEnemys,
|
|
FormationEnemySets enemyTypes,
|
|
int flagsFormationChangePolicy,
|
|
FormationShotPatterns shotPattern ) {
|
|
|
|
formationType = whichFormation;
|
|
formationCenter = centerAtStart;
|
|
formationSpeed = startVel;
|
|
|
|
changeOnKill = flagsFormationChangePolicy & FORMATION_CHANGE_ON_KILL;
|
|
changeSpontaneous = flagsFormationChangePolicy & FORMATION_CHANGE_SPONTANEOUS;
|
|
changeOften = flagsFormationChangePolicy & FORMATION_CHANGE_OFTEN;
|
|
changeSeldom = flagsFormationChangePolicy & FORMATION_CHANGE_SELDOM;
|
|
if ( changeSpontaneous && !changeSeldom && !changeOften ) changeSeldom = true;
|
|
if ( changeOften ) {
|
|
nextFormationChange =
|
|
FORMATION_CHANGE_OFTEN_DELAY +
|
|
rand() % (FORMATION_CHANGE_OFTEN_RAND_DELAY+1);
|
|
} else if ( changeSeldom ) {
|
|
nextFormationChange =
|
|
FORMATION_CHANGE_SELDOM_DELAY +
|
|
rand() % (FORMATION_CHANGE_SELDOM_RAND_DELAY+1);
|
|
}
|
|
|
|
if ( nrEnemys > FORMATION_MAX_NR_ENEMYS[ formationType ] )
|
|
nrInvolved = FORMATION_MAX_NR_ENEMYS[ formationType ];
|
|
else if ( nrEnemys < 0 ) nrInvolved = 0;
|
|
else nrInvolved = nrEnemys;
|
|
|
|
this->shotPattern = shotPattern;
|
|
actShootingEnemy = 0;
|
|
|
|
if ( shotPattern == FORMATION_SP_NONE ) formationFires = false;
|
|
else formationFires = true;
|
|
|
|
vector<Vector2D> targetPos;
|
|
fillTargetPos( targetPos );
|
|
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
Enemy *newOne;
|
|
switch ( enemyTypes ) {
|
|
case FORMATION_ENEMY_SET_DEFAULT:
|
|
case FORMATION_ENEMY_SET_FIGHTER:
|
|
{
|
|
newOne = new Enemy( formationCenter + targetPos[ i ], formationSpeed, FIGHTER,
|
|
true, formationFires );
|
|
break;
|
|
}
|
|
case FORMATION_ENEMY_SET_BOMBER:
|
|
{
|
|
newOne = new Enemy( formationCenter + targetPos[ i ], formationSpeed, BOMBER,
|
|
true, formationFires );
|
|
break;
|
|
}
|
|
case FORMATION_ENEMY_SET_FIGHTER_BOMBER:
|
|
{
|
|
newOne =
|
|
new Enemy( formationCenter + targetPos[ i ], formationSpeed,
|
|
(EnemyTypes)(FIGHTER + (i % 2)),
|
|
true, formationFires );
|
|
break;
|
|
}
|
|
}
|
|
enemys->addEnemy( newOne );
|
|
involvedEnemys.push_back( newOne );
|
|
}
|
|
|
|
enemyWasKilled = false;
|
|
// wait at least 100 ms before the first shot
|
|
nextFirePrimary = 100;
|
|
nextFireSecondary = 100;
|
|
|
|
// cout << "Type: " << formationType << " SP: " << shotPattern << endl;
|
|
}
|
|
|
|
Formation::~Formation() {}
|
|
|
|
|
|
void Formation::enemyKilled( Enemy *killedEnemy ) {
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
if ( involvedEnemys[i] == killedEnemy ) {
|
|
enemyWasKilled = true;
|
|
involvedEnemys.erase( involvedEnemys.begin() + i );
|
|
nrInvolved--;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Formation::update( int dT ) {
|
|
if ( changeSpontaneous ) handleSpontaneousFormationChange( dT );
|
|
|
|
if ( enemyWasKilled ) {
|
|
// change the formation?
|
|
if ( changeOnKill && (rand() % 100 < 70) ) chooseNewFormationType();
|
|
moveEnemyInFormation();
|
|
enemyWasKilled = false;
|
|
}
|
|
formationCenter += formationSpeed * dT / 1000.0;
|
|
shoot( dT );
|
|
}
|
|
|
|
|
|
void Formation::handleSpontaneousFormationChange( int dT ) {
|
|
nextFormationChange -= dT;
|
|
if ( changeSpontaneous && nextFormationChange < 0 ) {
|
|
|
|
chooseNewFormationType();
|
|
moveEnemyInFormation();
|
|
|
|
if ( changeOften ) {
|
|
nextFormationChange =
|
|
FORMATION_CHANGE_OFTEN_DELAY +
|
|
rand() % (FORMATION_CHANGE_OFTEN_RAND_DELAY+1);
|
|
} else if ( changeSeldom ) {
|
|
nextFormationChange =
|
|
FORMATION_CHANGE_SELDOM_DELAY +
|
|
rand() % (FORMATION_CHANGE_SELDOM_RAND_DELAY+1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::moveEnemyInFormation() {
|
|
// calc the target positions in the new formation (relative to the center of the formation)
|
|
vector<Vector2D> targetPos;
|
|
fillTargetPos( targetPos );
|
|
|
|
// choose the best mapping from enemy to targetPosition
|
|
// (shortest way for enemy to its position is best)
|
|
vector<Vector2D> relPosForEnemies;
|
|
getBestMapping( targetPos, relPosForEnemies );
|
|
|
|
// give the enemy its order
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
involvedEnemys[i]->setNewRelTargetPos( relPosForEnemies[ i ] );
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::chooseNewFormationType() {
|
|
bool found = false;
|
|
int i = 0;
|
|
while ( i < 10 && !found ) {
|
|
FormationTypes newFormationType = (FormationTypes)(rand() % (NR_FORMATION_TYPES-1));
|
|
if ( formationType == newFormationType ) {
|
|
newFormationType = (FormationTypes)(NR_FORMATION_TYPES - 1);
|
|
}
|
|
if ( nrInvolved <= FORMATION_MAX_NR_ENEMYS[ newFormationType ] ) {
|
|
formationType = newFormationType;
|
|
found = true;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::fillTargetPos( vector<Vector2D> &targetPos ) {
|
|
switch ( formationType ) {
|
|
case FORMATION_V:
|
|
{
|
|
fillTargetPosFormationV( targetPos );
|
|
break;
|
|
}
|
|
case FORMATION_REVERSE_V:
|
|
{
|
|
fillTargetPosFormationReverseV( targetPos );
|
|
break;
|
|
}
|
|
case FORMATION_BLOCK:
|
|
{
|
|
fillTargetPosFormationBlock( targetPos );
|
|
break;
|
|
}
|
|
case FORMATION_LINE:
|
|
{
|
|
fillTargetPosFormationLine( targetPos );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::fillTargetPosFormationV( vector<Vector2D> &targetPos ) {
|
|
switch ( nrInvolved ) {
|
|
case 1:
|
|
{
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
targetPos.push_back( Vector2D(-50,25) );
|
|
targetPos.push_back( Vector2D(0,-25) );
|
|
targetPos.push_back( Vector2D(50,25) );
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
targetPos.push_back( Vector2D(-80,25) );
|
|
targetPos.push_back( Vector2D(-30,-25) );
|
|
targetPos.push_back( Vector2D(30,-25) );
|
|
targetPos.push_back( Vector2D(80,25) );
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
targetPos.push_back( Vector2D(-100,50) );
|
|
targetPos.push_back( Vector2D(-50,0) );
|
|
targetPos.push_back( Vector2D(0,-50) );
|
|
targetPos.push_back( Vector2D(50,0) );
|
|
targetPos.push_back( Vector2D(100,50) );
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
targetPos.push_back( Vector2D(-130,50) );
|
|
targetPos.push_back( Vector2D(-80,0) );
|
|
targetPos.push_back( Vector2D(-30,-50) );
|
|
targetPos.push_back( Vector2D(30,-50) );
|
|
targetPos.push_back( Vector2D(80,0) );
|
|
targetPos.push_back( Vector2D(130,50) );
|
|
break;
|
|
}
|
|
case 7:
|
|
{
|
|
targetPos.push_back( Vector2D(-150,75) );
|
|
targetPos.push_back( Vector2D(-100,25) );
|
|
targetPos.push_back( Vector2D(-50,-25) );
|
|
targetPos.push_back( Vector2D(0,-75) );
|
|
targetPos.push_back( Vector2D(50,-25) );
|
|
targetPos.push_back( Vector2D(100,25) );
|
|
targetPos.push_back( Vector2D(150,75) );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
cout << "fillTargetPosFormationV: too many enemys involved: " << nrInvolved << endl;
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::fillTargetPosFormationReverseV( vector<Vector2D> &targetPos ) {
|
|
switch ( nrInvolved ) {
|
|
case 1:
|
|
{
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
targetPos.push_back( Vector2D(-50,-25) );
|
|
targetPos.push_back( Vector2D(0,25) );
|
|
targetPos.push_back( Vector2D(50,-25) );
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
targetPos.push_back( Vector2D(-80,-25) );
|
|
targetPos.push_back( Vector2D(-30,25) );
|
|
targetPos.push_back( Vector2D(30,25) );
|
|
targetPos.push_back( Vector2D(80,-25) );
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
targetPos.push_back( Vector2D(-100,-50) );
|
|
targetPos.push_back( Vector2D(-50,0) );
|
|
targetPos.push_back( Vector2D(0,50) );
|
|
targetPos.push_back( Vector2D(50,0) );
|
|
targetPos.push_back( Vector2D(100,-50) );
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
targetPos.push_back( Vector2D(-130,-50) );
|
|
targetPos.push_back( Vector2D(-80,0) );
|
|
targetPos.push_back( Vector2D(-30,50) );
|
|
targetPos.push_back( Vector2D(30,50) );
|
|
targetPos.push_back( Vector2D(80,0) );
|
|
targetPos.push_back( Vector2D(130,-50) );
|
|
break;
|
|
}
|
|
case 7:
|
|
{
|
|
targetPos.push_back( Vector2D(-150,-75) );
|
|
targetPos.push_back( Vector2D(-100,-25) );
|
|
targetPos.push_back( Vector2D(-50,25) );
|
|
targetPos.push_back( Vector2D(0,75) );
|
|
targetPos.push_back( Vector2D(50,25) );
|
|
targetPos.push_back( Vector2D(100,-25) );
|
|
targetPos.push_back( Vector2D(150,-75) );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
cout << "fillTargetPosFormationReverseV: too many enemys involved: "
|
|
<< nrInvolved << endl;
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::fillTargetPosFormationBlock( vector<Vector2D> &targetPos ) {
|
|
switch ( nrInvolved ) {
|
|
case 1:
|
|
{
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,25) );
|
|
targetPos.push_back( Vector2D(0,-25) );
|
|
targetPos.push_back( Vector2D(30,25) );
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,-25) );
|
|
targetPos.push_back( Vector2D(-30,25) );
|
|
targetPos.push_back( Vector2D(30,-25) );
|
|
targetPos.push_back( Vector2D(30,25) );
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
targetPos.push_back( Vector2D(-40,-30) );
|
|
targetPos.push_back( Vector2D(-40,30) );
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
targetPos.push_back( Vector2D(40,-30) );
|
|
targetPos.push_back( Vector2D(40,30) );
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
targetPos.push_back( Vector2D(-60,-30) );
|
|
targetPos.push_back( Vector2D(-60,30) );
|
|
targetPos.push_back( Vector2D(0,-30) );
|
|
targetPos.push_back( Vector2D(0,30) );
|
|
targetPos.push_back( Vector2D(60,-30) );
|
|
targetPos.push_back( Vector2D(60,30) );
|
|
break;
|
|
}
|
|
case 7:
|
|
{
|
|
targetPos.push_back( Vector2D(-60,-50) );
|
|
targetPos.push_back( Vector2D(-60,0) );
|
|
targetPos.push_back( Vector2D(0,-50) );
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
targetPos.push_back( Vector2D(0,50) );
|
|
targetPos.push_back( Vector2D(60,-50) );
|
|
targetPos.push_back( Vector2D(60,0) );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
cout << "fillTargetPosFormationBlock: too many enemys involved: " << nrInvolved << endl;
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Formation::fillTargetPosFormationLine( vector<Vector2D> &targetPos ) {
|
|
switch ( nrInvolved ) {
|
|
case 1:
|
|
{
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
targetPos.push_back( Vector2D(-60,0) );
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
targetPos.push_back( Vector2D(60,0) );
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
targetPos.push_back( Vector2D(-90,0) );
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
targetPos.push_back( Vector2D(90,0) );
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
targetPos.push_back( Vector2D(-120,0) );
|
|
targetPos.push_back( Vector2D(-60,0) );
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
targetPos.push_back( Vector2D(60,0) );
|
|
targetPos.push_back( Vector2D(120,0) );
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
targetPos.push_back( Vector2D(-150,0) );
|
|
targetPos.push_back( Vector2D(-90,0) );
|
|
targetPos.push_back( Vector2D(-30,0) );
|
|
targetPos.push_back( Vector2D(30,0) );
|
|
targetPos.push_back( Vector2D(90,0) );
|
|
targetPos.push_back( Vector2D(150,0) );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
cout << "fillTargetPosFormationLine: too many enemys involved: " << nrInvolved << endl;
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
targetPos.push_back( Vector2D(0,0) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
|
|
void Formation::getBestMapping( vector<Vector2D> &targetPos,
|
|
vector<Vector2D> &relPosForFighters ) {
|
|
|
|
int actPerm[nrInvolved];
|
|
vector<Vector2D> *bestMapping = new vector<Vector2D>();
|
|
vector<Vector2D> *testMapping = new vector<Vector2D>();
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
bestMapping->push_back( Vector2D( 0,0 ) );
|
|
testMapping->push_back( Vector2D( 0,0 ) );
|
|
actPerm[ i ] = i;
|
|
}
|
|
float mapCost = 1000000;
|
|
|
|
int nrPerm = factorial( nrInvolved );
|
|
|
|
for ( int perm = 0; perm < nrPerm; perm++ ) {
|
|
calcNextPerm( actPerm );
|
|
float testMappingCost = calcTestMapping( actPerm, targetPos, testMapping );
|
|
if ( mapCost > testMappingCost ) {
|
|
vector<Vector2D> *tmpMapping = bestMapping;
|
|
bestMapping = testMapping;
|
|
testMapping = tmpMapping;
|
|
mapCost = testMappingCost;
|
|
}
|
|
}
|
|
|
|
for ( int e = 0; e < nrInvolved; e++ ) {
|
|
relPosForFighters.push_back( (*bestMapping)[e] );
|
|
}
|
|
delete bestMapping;
|
|
delete testMapping;
|
|
}
|
|
|
|
|
|
void Formation::calcNextPerm( int *perm ) {
|
|
int n = nrInvolved;
|
|
int i = n-1;
|
|
int j = n;
|
|
int tmp;
|
|
|
|
while ( i != 0 && perm[ i-1 ] >= perm[ i ] ) {
|
|
i--;
|
|
}
|
|
if ( i == 0 ) {
|
|
for ( int k = 0; k < n/2; k++ ) {
|
|
tmp = perm[ k ];
|
|
perm[ k ] = perm[ n - k - 1 ];
|
|
perm[ n - k - 1 ] = tmp;
|
|
}
|
|
return;
|
|
}
|
|
while ( perm[ j-1 ] <= perm[ i-1 ] ) {
|
|
--j;
|
|
}
|
|
tmp = perm[ i-1 ];
|
|
perm[ i-1 ] = perm[ j-1 ];
|
|
perm[ j-1 ] = tmp;
|
|
|
|
i++;
|
|
j = n;
|
|
|
|
while ( i < j ) {
|
|
tmp = perm[ i-1 ];
|
|
perm[ i-1 ] = perm[ j-1 ];
|
|
perm[ j-1 ] = tmp;
|
|
i++;
|
|
j--;
|
|
}
|
|
}
|
|
|
|
|
|
float Formation::calcTestMapping( int *perm, vector<Vector2D> &targetPos,
|
|
vector<Vector2D> *mapping ) {
|
|
|
|
float cost = 0;
|
|
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
// enemy i shall fly to the position targetPos[perm[i]]
|
|
// save the vector from its actual pos to its new targetpos in mapping
|
|
(*mapping)[ i ] =
|
|
targetPos[ perm[i] ] + formationCenter -
|
|
involvedEnemys[ i ]->getPos();
|
|
|
|
if ( cost < (*mapping)[ i ].getLength() ) {
|
|
cost = (*mapping)[ i ].getLength();
|
|
}
|
|
}
|
|
return cost;
|
|
}
|
|
|
|
|
|
int Formation::factorial( int n ) {
|
|
int result = 1;
|
|
for ( int i = 2; i <= n; i++ ) {
|
|
result *= i;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void Formation::shoot( int dT ) {
|
|
if ( shotPattern == FORMATION_SP_NONE ) return;
|
|
nextFirePrimary -= dT;
|
|
// nextFireSecondary -= dT;
|
|
|
|
float enemyRatio = FORMATION_MAX_NR_ENEMYS[ formationType ] / (float)nrInvolved;
|
|
|
|
while ( nextFirePrimary < 0 ) {
|
|
switch ( shotPattern ) {
|
|
case FORMATION_SP_VOLLEY_FAST:
|
|
case FORMATION_SP_VOLLEY_MEDIUM:
|
|
case FORMATION_SP_VOLLEY_SLOW:
|
|
{
|
|
for ( int i = 0; i < nrInvolved; i++ ) {
|
|
involvedEnemys[ i ]->firePrimary();
|
|
}
|
|
break;
|
|
}
|
|
case FORMATION_SP_RAND_FAST:
|
|
case FORMATION_SP_RAND_MEDIUM:
|
|
case FORMATION_SP_RAND_SLOW:
|
|
{
|
|
involvedEnemys[ rand() % nrInvolved ]->firePrimary();
|
|
break;
|
|
}
|
|
case FORMATION_SP_LEFT_RIGHT_FAST:
|
|
case FORMATION_SP_LEFT_RIGHT_MEDIUM:
|
|
{
|
|
actShootingEnemy = (actShootingEnemy + 1) % nrInvolved;
|
|
involvedEnemys[ actShootingEnemy ]->firePrimary();
|
|
break;
|
|
}
|
|
case FORMATION_SP_RIGHT_LEFT_FAST:
|
|
case FORMATION_SP_RIGHT_LEFT_MEDIUM:
|
|
{
|
|
actShootingEnemy--;
|
|
if ( actShootingEnemy < 0 ) actShootingEnemy = nrInvolved-1;
|
|
involvedEnemys[ actShootingEnemy ]->firePrimary();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
nextFirePrimary +=
|
|
lroundf( (FORMATION_SP_PRIMARY_DELAY[ shotPattern ] +
|
|
rand() % (FORMATION_SP_PRIMARY_RAND_DELAY[ shotPattern ] + 1)) * enemyRatio );
|
|
}
|
|
}
|
|
|