00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
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 );
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
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 }
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 ) {
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
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 }
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