Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

reactionfire.cpp

Go to the documentation of this file.
00001 
00002 
00003 /*
00004     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00005     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; see the file COPYING. If not, write to the 
00019     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00020     Boston, MA  02111-1307  USA
00021 */
00022 
00023 
00024 #include "buildings.h"
00025 #include "vehicle.h"
00026 #include "typen.h"
00027 #include "gamemap.h"
00028 #include "stack.h"
00029 #include "viewcalculation.h"
00030 #include "replay.h"
00031 #include "attack.h"
00032 #include "messaginghub.h"
00033 #include "mapdisplayinterface.h"
00034 #include "reactionfire.h"
00035 #include "spfst.h"
00036 #include "itemrepository.h"
00037 
00038 
00039 treactionfirereplay :: treactionfirereplay ( void )
00040 {
00041    num = 0;
00042    unit = NULL;
00043 }
00044 
00045 void treactionfirereplay :: init ( Vehicle* eht, const AStar3D::Path& fieldlist )
00046 {
00047    if ( runreplay.status > 0 ) {
00048       treactionfire_replayinfo* rpli;
00049       do {
00050          rpli = runreplay.getnextreplayinfo ( );
00051          if ( rpli )
00052             replay[num++] = rpli;
00053 
00054       } while ( rpli );
00055 
00056       unit = eht;
00057    }
00058 }
00059 
00060 int  treactionfirereplay :: checkfield ( const MapCoordinate3D& pos, Vehicle* &eht, MapDisplayInterface* md )
00061 {
00062    int attacks = 0;
00063 
00064    if ( eht == unit ) {
00065       for ( int i = 0; i < num; i++ ) {
00066          treactionfire_replayinfo* rpli = replay[ i ];
00067          if ( eht && rpli->x2 == pos.x  && rpli->y2 == pos.y ) {
00068 
00069              tfield* fld = getfield ( rpli->x1, rpli->y1 );
00070              tfield* targ = getfield ( rpli->x2, rpli->y2 );
00071 
00072              npush ( targ->vehicle );
00073              targ->vehicle = eht;
00074              eht->xpos = pos.x;
00075              eht->ypos = pos.y;
00076              eht->height = pos.getBitmappedHeight();
00077 
00078 
00079              int attackvisible = fieldvisiblenow ( fld ) || fieldvisiblenow ( targ );
00080 
00081 
00082              if ( md && attackvisible ) {
00083              /*
00084                // cursor.setcolor ( 8 );
00085 
00086                cursor.gotoxy ( rpli->x1, rpli->y1 );
00087                int t = ticker;
00088                while ( t + 15 > ticker )
00089                   releasetimeslice();
00090 
00091                cursor.gotoxy ( pos.x, pos.y );
00092                t = ticker;
00093                while ( t + 15 > ticker )
00094                   releasetimeslice();
00095 
00096                // cursor.setcolor ( 0 );
00097                // cursor.hide();
00098                */
00099              }
00100              attacks++;
00101 
00102              tunitattacksunit battle ( fld->vehicle, targ->vehicle, 1, rpli->wpnum );
00103              battle.av.damage = rpli->ad1;
00104              battle.dv.damage = rpli->dd1;
00105              if ( md && attackvisible  )
00106                 md->showBattle( battle ); // .calcdisplay ( rpli->ad2, rpli->dd2 );
00107              else {
00108                 battle.calc ();
00109                 battle.av.damage = rpli->ad2;
00110                 battle.dv.damage = rpli->dd2;
00111              }
00112 
00113              int killed = 0;
00114              if ( battle.dv.damage >= 100 )
00115                 killed = 1;
00116 
00117              battle.setresult ();
00118              updateFieldInfo();
00119 
00120              npop ( targ->vehicle );
00121 
00122              if ( killed )
00123                 eht = NULL;
00124          }
00125       }
00126    }
00127    return attacks;
00128 }
00129 
00130 treactionfirereplay :: ~treactionfirereplay ( )
00131 {
00132    for ( int i = 0; i < num; i++ )
00133       delete replay[i];
00134 }
00135 
00136 
00137 
00138                 typedef struct tunitlist* punitlist;
00139                 struct tunitlist {
00140                         Vehicle* eht;
00141                         punitlist next;
00142                      };
00143 
00144                 punitlist unitlist[8];
00145 
00146 
00147 int tsearchreactionfireingunits :: maxshootdist[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
00148 
00149 tsearchreactionfireingunits :: tsearchreactionfireingunits ( void )
00150 {
00151    for ( int i = 0; i < 8; i++ )
00152       unitlist[i] = NULL;
00153 }
00154 
00155 void tsearchreactionfireingunits :: init ( Vehicle* eht, const MapCoordinate3D& pos )
00156 {
00157    initLimits();
00158    findOffensiveUnits( eht, pos.getNumericalHeight(), pos.x, pos.y, pos.x, pos.y );
00159 }
00160 
00161 
00162 void tsearchreactionfireingunits :: initLimits()
00163 {
00164    if ( maxshootdist[0] == -1 ) {
00165       for (int i = 0; i < 8; i++ )
00166          maxshootdist[i] = 0;
00167 
00168       for (int i = 0; i < vehicleTypeRepository.getNum(); i++ ) {
00169          Vehicletype* fzt = vehicleTypeRepository.getObject_byPos ( i );
00170          if ( fzt )
00171             for (int j = 0; j < fzt->weapons.count; j++ )
00172                if ( fzt->weapons.weapon[j].shootable() )
00173                   for (int h = 0; h < 8; h++ )
00174                      if ( fzt->weapons.weapon[j].targ & ( 1 << h ) )
00175                         if ( fzt->weapons.weapon[j].maxdistance > maxshootdist[h] )
00176                            maxshootdist[h] = fzt->weapons.weapon[j].maxdistance;
00177       }
00178    }
00179 }
00180 
00181 void tsearchreactionfireingunits :: findOffensiveUnits( Vehicle* vehicle, int height, int x1, int y1, int x2, int y2 )
00182 {
00183    x1 -= maxshootdist[height];
00184    y1 -= maxshootdist[height];
00185    x2 += maxshootdist[height];
00186    y2 += maxshootdist[height];
00187 
00188    if ( x1 < 0 )
00189       x1 = 0;
00190    if ( y1 < 0 )
00191       y1 = 0;
00192    if ( x2 >= actmap->xsize )
00193       x2 = actmap->xsize -1;
00194    if ( y2 >= actmap->ysize )
00195       y2 = actmap->ysize -1;
00196 
00197    for ( int y = y1; y <= y2; y++ )
00198       for ( int x = x1; x <= x2; x++ ) {
00199          Vehicle* eht = getfield ( x, y )->vehicle;
00200          if ( eht )
00201             if ( eht->color != vehicle->color )
00202                if ( eht->reactionfire.getStatus() >= Vehicle::ReactionFire::ready )
00203                   // if ( eht->reactionfire.enemiesAttackable & ( 1 << ( vehicle->color / 8 )))
00204                      if ( actmap->player[eht->getOwner()].diplomacy.isHostile( actmap->actplayer))
00205                         if ( attackpossible2u ( eht, vehicle, NULL, vehicle->typ->height ) )
00206                            addunit ( eht );
00207 
00208       }
00209    if ( getfield(vehicle->xpos, vehicle->ypos)->vehicle == vehicle )
00210       for ( int i = 0; i < 8; i++ )
00211          if ( fieldvisiblenow ( getfield ( vehicle->xpos, vehicle->ypos ), i )) {
00212             punitlist ul  = unitlist[i];
00213             while ( ul ) {
00214                punitlist next = ul->next;
00215                
00216                pattackweap atw = attackpossible ( ul->eht, vehicle->xpos, vehicle->ypos );
00217                for ( int j = 0; j < atw->count; ++j )
00218                   if ( ul->eht->reactionfire.weaponShots[atw->num[j]] ) {
00219                      removeunit ( ul->eht );
00220                      break;
00221                   }   
00222 
00223                delete atw;
00224                ul = next;
00225             } /* endwhile */
00226          }
00227 
00228    for ( int player = 0; player < actmap->getPlayerCount(); ++player ) {
00229       if ( actmap->getPlayer(vehicle).diplomacy.isHostile( player )) {
00230          for ( Player::VehicleList::iterator i = actmap->getPlayer(vehicle).vehicleList.begin(); i != actmap->getPlayer(vehicle).vehicleList.end(); ++i) {
00231             if ( fieldvisiblenow( actmap->getField( (*i)->getPosition() ), player, actmap )) {
00232                if ( visibleUnits.find( *i ) == visibleUnits.end() )
00233                   visibleUnits[*i] = 1 << player;
00234                else
00235                   visibleUnits[*i] |= 1 << player;
00236             }
00237          }
00238       }
00239    }
00240      
00241 
00242 }
00243 
00244 
00245 void tsearchreactionfireingunits :: init ( Vehicle* vehicle, const AStar3D::Path& fieldlist )
00246 {
00247    initLimits();
00248 
00249    int x1 = maxint;
00250    int y1 = maxint;
00251    int x2 = 0;
00252    int y2 = 0;
00253 
00254    for ( AStar3D::Path::const_iterator i = fieldlist.begin(); i != fieldlist.end(); i++) {
00255       if ( i->x > x2 )
00256          x2 = i->x ;
00257       if ( i->y > y2 )
00258          y2 = i->y ;
00259 
00260       if ( i->x < x1 )
00261          x1 = i->x ;
00262       if ( i->y < y1 )
00263          y1 = i->y ;
00264    }
00265    findOffensiveUnits ( vehicle, log2 ( vehicle->height ), x1,y1,x2,y2);
00266           
00267 }
00268 
00269 void  tsearchreactionfireingunits :: addunit ( Vehicle* eht )
00270 {
00271    int c = eht->color / 8;
00272    punitlist ul = new tunitlist;
00273    ul->eht = eht;
00274    ul->next= unitlist[c];
00275    unitlist[c] = ul;
00276 }
00277 
00278 
00279 void tsearchreactionfireingunits :: removeunit ( Vehicle* vehicle )
00280 {
00281    int c = vehicle->color / 8;
00282    punitlist ul = unitlist[c];
00283    punitlist last = NULL;
00284    while ( ul  &&  ul->eht != vehicle ) {
00285       last = ul;
00286       ul = ul->next;
00287   }
00288   if ( ul  &&  ul->eht == vehicle ) {
00289      if ( last )
00290         last->next = ul->next;
00291      else
00292         unitlist[c] = ul->next;
00293 
00294      delete ul;
00295   }
00296 }
00297 
00298 
00299 int tsearchreactionfireingunits :: attack( Vehicle* attacker, Vehicle* target, MapDisplayInterface* md )
00300 {
00301    tfield* fld = target->getMap()->getField( target->getPosition() );
00302    
00303    
00304    int result = 0;
00305    if ( attacker->reactionfire.canPerformAttack( target )) { 
00306       pattackweap atw = attackpossible ( attacker, target->xpos, target->ypos );
00307       if ( atw->count ) { // && (attacker->reactionfire.enemiesAttackable & (1 << (target->color / 8)))) {
00308 
00309          int ad1, ad2, dd1, dd2;
00310 
00311          int strength = 0;
00312          int num = -1;
00313          for ( int j = 0; j < atw->count; j++ )
00314             if ( attacker->reactionfire.weaponShots[atw->num[j]] > 0 )
00315                if ( atw->strength[j]  > strength ) {
00316                   strength = atw->strength[j];
00317                   num = j;
00318                }
00319 
00320                if ( num >= 0 ) {
00321 
00322                   int visibility = 0;
00323                   if ( md ) {
00324                      MessagingHub::Instance().statusInformation( "attacking with weapon " + ASCString::toString( atw->num[num] ));
00325 
00326                      if ( fieldvisiblenow ( getfield (attacker->xpos, attacker->ypos ), actmap->getPlayerView())) {
00327                         ++visibility;
00328                         md->cursor_goto( attacker->getPosition() );
00329                         int t = ticker;
00330                         while ( t + 15 > ticker )
00331                            releasetimeslice();
00332                      }
00333 
00334                      if ( fieldvisiblenow ( fld, actmap->getPlayerView())) {
00335                         ++visibility;
00336                         md->cursor_goto( target->getPosition() );
00337                         int t = ticker;
00338                         while ( t + 15 > ticker )
00339                            releasetimeslice();
00340                      }
00341                   }
00342 
00343                   tunitattacksunit battle ( attacker, target, 0, atw->num[num], true );
00344                   // int nwid = target->networkid;
00345 
00346                   ad1 = battle.av.damage;
00347                   dd1 = battle.dv.damage;
00348 
00349                   if ( md && visibility)
00350                      md->showBattle( battle ); 
00351                   else
00352                      battle.calc();
00353 
00354                   ad2 = battle.av.damage;
00355                   dd2 = battle.dv.damage;
00356 
00357                   if ( battle.dv.damage >= 100 )
00358                      result = 2;
00359                   else
00360                      result = 1;
00361 
00362                   battle.setresult();
00363 
00364                   updateFieldInfo();
00365                }
00366       }
00367       delete atw;
00368    }
00369 
00370    return result;
00371 }
00372 
00373 
00374 int  tsearchreactionfireingunits :: checkfield ( const MapCoordinate3D& pos, Vehicle* &vehicle, MapDisplayInterface* md )
00375 {
00376 
00377    int attacks = 0;
00378    int result = 0;
00379 
00380    tfield* fld = getfield( pos.x, pos.y );
00381    npush ( fld->vehicle );
00382    fld->vehicle = vehicle;
00383    vehicle->xpos = pos.x;
00384    vehicle->ypos = pos.y;
00385    int oldheight = vehicle->height;
00386    if ( pos.getNumericalHeight() >= 0 )
00387       vehicle->height = pos.getBitmappedHeight();
00388 
00389    for ( int i = 0; i < 8; i++ ) {
00390       evaluatevisibilityfield ( actmap, fld, i, -1, actmap->getgameparameter ( cgp_initialMapVisibility ) );
00391       if ( fieldvisiblenow ( fld, i )) {
00392          punitlist ul  = unitlist[i];
00393          while ( ul  &&  !result ) {
00394             punitlist next = ul->next;
00395             
00396             int r = attack( ul->eht, vehicle, md );
00397             if ( r > 0 )
00398                ++attacks;
00399             
00400             if ( r > 1 )
00401                result = 1;
00402             
00403             ul = next;
00404          } /* endwhile */
00405       }
00406    }
00407    npop ( fld->vehicle );
00408    for ( int i = 0; i < 8; i++ )
00409       evaluatevisibilityfield ( actmap, fld, i, -1, actmap->getgameparameter ( cgp_initialMapVisibility ) );
00410 
00411    if ( result )
00412       vehicle = NULL;
00413    else
00414       vehicle->height = oldheight;
00415 
00416    return attacks;
00417 }
00418 
00419 
00420 int  tsearchreactionfireingunits :: finalCheck ( MapDisplayInterface* md, int currentPlayer )
00421 {
00422    int destroyedUnits = 0;
00423    for ( int player = 0; player < actmap->getPlayerCount(); ++player ) {
00424       if ( actmap->getPlayer(currentPlayer).diplomacy.isHostile( player )) {
00425          list<int> exposedTargets;
00426          for ( Player::VehicleList::iterator exposedTarget = actmap->getPlayer(currentPlayer).vehicleList.begin(); exposedTarget != actmap->getPlayer(currentPlayer).vehicleList.end(); ++exposedTarget) {
00427             if ( fieldvisiblenow( actmap->getField( (*exposedTarget)->getPosition() ), player, actmap )) {
00428                if ( visibleUnits.find( *exposedTarget ) == visibleUnits.end() || !(visibleUnits[*exposedTarget] & (1 << player)) ) { 
00429                   if ( (*exposedTarget)->getMap()->getField( (*exposedTarget)->getPosition() )->unitHere( *exposedTarget ))
00430                      exposedTargets.push_back( (*exposedTarget )->networkid );
00431                }
00432             }
00433          }
00434           
00435          for ( list<int>::iterator exposedTargetID = exposedTargets.begin(); exposedTargetID != exposedTargets.end(); ++exposedTargetID ) {
00436             Vehicle* exposedTarget = actmap->getUnit( *exposedTargetID );
00437             if ( exposedTarget )  {
00438                bool destroyed = false;
00439                
00440                for ( Player::VehicleList::iterator enemyUnit = actmap->getPlayer(player).vehicleList.begin(); enemyUnit != actmap->getPlayer(player).vehicleList.end() && !destroyed; ++enemyUnit) {
00441                   if ( (*enemyUnit)->reactionfire.canPerformAttack( exposedTarget )) {
00442                      if ( beeline( *enemyUnit, exposedTarget ) <= maxshootdist[ exposedTarget->getPosition().getNumericalHeight()]) {
00443                         int r = attack( *enemyUnit, exposedTarget, md );
00444                         if ( r > 1 ) { 
00445                            destroyed = true;
00446                            ++destroyedUnits;
00447                         }
00448                      }
00449                   } 
00450                }
00451             }
00452          }
00453       }
00454    }
00455    return destroyedUnits;
00456 }
00457 
00458 
00459 
00460 tsearchreactionfireingunits :: ~tsearchreactionfireingunits()
00461 {
00462    for ( int i = 0; i < 8; i++ ) {
00463       punitlist ul = unitlist[i];
00464       while ( ul ) {
00465          punitlist ul2 = ul->next;
00466          delete ul;
00467          ul = ul2;
00468       }
00469    }
00470 }
00471 
00472 
00473 

Generated on Tue Jun 24 01:27:50 2008 for Advanced Strategic Command by  doxygen 1.4.2