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 "util/messaginghub.h"
00033 #include "mapdisplayinterface.h"
00034 #include "reactionfire.h"
00035 #include "spfst.h"
00036 #include "itemrepository.h"
00037
00038 typedef struct tunitlist* punitlist;
00039 struct tunitlist {
00040 Vehicle* eht;
00041 punitlist next;
00042 };
00043
00044 punitlist unitlist[8];
00045
00046
00047 int tsearchreactionfireingunits :: maxshootdist[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
00048
00049 tsearchreactionfireingunits :: tsearchreactionfireingunits ( GameMap* gamemap )
00050 {
00051 this->gamemap = gamemap;
00052 for ( int i = 0; i < 8; i++ )
00053 unitlist[i] = NULL;
00054 }
00055
00056 void tsearchreactionfireingunits :: init ( Vehicle* eht, const MapCoordinate3D& pos )
00057 {
00058 initLimits();
00059 findOffensiveUnits( eht, pos.getNumericalHeight(), pos.x, pos.y, pos.x, pos.y );
00060 }
00061
00062
00063 void tsearchreactionfireingunits :: initLimits()
00064 {
00065 if ( maxshootdist[0] == -1 ) {
00066 for (int i = 0; i < 8; i++ )
00067 maxshootdist[i] = 0;
00068
00069 for (int i = 0; i < vehicleTypeRepository.getNum(); i++ ) {
00070 VehicleType* fzt = vehicleTypeRepository.getObject_byPos ( i );
00071 if ( fzt )
00072 for (int j = 0; j < fzt->weapons.count; j++ )
00073 if ( fzt->weapons.weapon[j].shootable() )
00074 for (int h = 0; h < 8; h++ )
00075 if ( fzt->weapons.weapon[j].targ & ( 1 << h ) )
00076 if ( fzt->weapons.weapon[j].maxdistance > maxshootdist[h] )
00077 maxshootdist[h] = fzt->weapons.weapon[j].maxdistance;
00078 }
00079 }
00080 }
00081
00082 void tsearchreactionfireingunits :: findOffensiveUnits( Vehicle* vehicle, int height, int x1, int y1, int x2, int y2 )
00083 {
00084 x1 -= maxshootdist[height];
00085 y1 -= maxshootdist[height];
00086 x2 += maxshootdist[height];
00087 y2 += maxshootdist[height];
00088
00089 GameMap* gamemap = vehicle->getMap();
00090
00091 if ( x1 < 0 )
00092 x1 = 0;
00093 if ( y1 < 0 )
00094 y1 = 0;
00095 if ( x2 >= gamemap->xsize )
00096 x2 = gamemap->xsize -1;
00097 if ( y2 >= gamemap->ysize )
00098 y2 = gamemap->ysize -1;
00099
00100 for ( int y = y1; y <= y2; y++ )
00101 for ( int x = x1; x <= x2; x++ ) {
00102 Vehicle* eht = gamemap->getField ( x, y )->vehicle;
00103 if ( eht )
00104 if ( eht->color != vehicle->color )
00105 if ( eht->reactionfire.getStatus() >= Vehicle::ReactionFire::ready )
00106
00107 if ( gamemap->player[eht->getOwner()].diplomacy.isHostile( gamemap->actplayer))
00108 if ( attackpossible2u ( eht, vehicle, NULL, vehicle->typ->height ) )
00109 addunit ( eht );
00110
00111 }
00112 if ( gamemap->getField(vehicle->xpos, vehicle->ypos)->vehicle == vehicle )
00113 for ( int i = 0; i < 8; i++ )
00114 if ( fieldvisiblenow ( gamemap->getField ( vehicle->xpos, vehicle->ypos ), i )) {
00115 punitlist ul = unitlist[i];
00116 while ( ul ) {
00117 punitlist next = ul->next;
00118
00119 AttackWeap* atw = attackpossible ( ul->eht, vehicle->xpos, vehicle->ypos );
00120 for ( int j = 0; j < atw->count; ++j )
00121 if ( ul->eht->reactionfire.weaponShots[atw->num[j]] ) {
00122 removeunit ( ul->eht );
00123 break;
00124 }
00125
00126 delete atw;
00127 ul = next;
00128 }
00129 }
00130
00131 for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
00132 if ( gamemap->getPlayer(vehicle).diplomacy.isHostile( player )) {
00133 for ( Player::VehicleList::iterator i = gamemap->getPlayer(vehicle).vehicleList.begin(); i != gamemap->getPlayer(vehicle).vehicleList.end(); ++i) {
00134 if ( fieldvisiblenow( gamemap->getField( (*i)->getPosition() ), player )) {
00135 if ( visibleUnits.find( *i ) == visibleUnits.end() )
00136 visibleUnits[*i] = 1 << player;
00137 else
00138 visibleUnits[*i] |= 1 << player;
00139 }
00140 }
00141 }
00142 }
00143
00144
00145 }
00146
00147
00148 void tsearchreactionfireingunits :: init ( Vehicle* vehicle, const AStar3D::Path& fieldlist )
00149 {
00150 initLimits();
00151
00152 int x1 = maxint;
00153 int y1 = maxint;
00154 int x2 = 0;
00155 int y2 = 0;
00156
00157 for ( AStar3D::Path::const_iterator i = fieldlist.begin(); i != fieldlist.end(); i++) {
00158 if ( i->x > x2 )
00159 x2 = i->x ;
00160 if ( i->y > y2 )
00161 y2 = i->y ;
00162
00163 if ( i->x < x1 )
00164 x1 = i->x ;
00165 if ( i->y < y1 )
00166 y1 = i->y ;
00167 }
00168 findOffensiveUnits ( vehicle, getFirstBit ( vehicle->height ), x1,y1,x2,y2);
00169
00170 }
00171
00172 void tsearchreactionfireingunits :: addunit ( Vehicle* eht )
00173 {
00174 int c = eht->color / 8;
00175 punitlist ul = new tunitlist;
00176 ul->eht = eht;
00177 ul->next= unitlist[c];
00178 unitlist[c] = ul;
00179 }
00180
00181
00182 void tsearchreactionfireingunits :: removeunit ( Vehicle* vehicle )
00183 {
00184 int c = vehicle->color / 8;
00185 punitlist ul = unitlist[c];
00186 punitlist last = NULL;
00187 while ( ul && ul->eht != vehicle ) {
00188 last = ul;
00189 ul = ul->next;
00190 }
00191 if ( ul && ul->eht == vehicle ) {
00192 if ( last )
00193 last->next = ul->next;
00194 else
00195 unitlist[c] = ul->next;
00196
00197 delete ul;
00198 }
00199 }
00200
00201
00202 int tsearchreactionfireingunits :: attack( Vehicle* attacker, Vehicle* target, const Context& context )
00203 {
00204 MapField* fld = target->getMap()->getField( target->getPosition() );
00205
00206
00207 int result = 0;
00208 if ( attacker->reactionfire.canPerformAttack( target )) {
00209 AttackWeap* atw = attackpossible ( attacker, target->xpos, target->ypos );
00210 if ( atw->count ) {
00211
00212 int ad1, ad2, dd1, dd2;
00213
00214 int strength = 0;
00215 int num = -1;
00216 for ( int j = 0; j < atw->count; j++ )
00217 if ( attacker->reactionfire.weaponShots[atw->num[j]] > 0 )
00218 if ( atw->strength[j] > strength ) {
00219 strength = atw->strength[j];
00220 num = j;
00221 }
00222
00223 if ( num >= 0 ) {
00224
00225 int visibility = 0;
00226 if ( context.display ) {
00227 MessagingHub::Instance().statusInformation( "attacking with weapon " + ASCString::toString( atw->num[num] ));
00228
00229 if ( fieldvisiblenow ( gamemap->getField (attacker->xpos, attacker->ypos ), gamemap->getPlayerView())) {
00230 ++visibility;
00231 context.display->cursor_goto( attacker->getPosition() );
00232 int t = ticker;
00233 while ( t + 15 > ticker )
00234 releasetimeslice();
00235 }
00236
00237 if ( fieldvisiblenow ( fld, target, gamemap->getPlayerView() )) {
00238 ++visibility;
00239 context.display->cursor_goto( target->getPosition() );
00240 int t = ticker;
00241 while ( t + 15 > ticker )
00242 releasetimeslice();
00243 }
00244 }
00245
00246 tunitattacksunit battle ( attacker, target, 0, atw->num[num], true );
00247
00248
00249 ad1 = battle.av.damage;
00250 dd1 = battle.dv.damage;
00251
00252 if ( context.display && visibility)
00253 context.display->showBattle( battle );
00254 else
00255 battle.calc();
00256
00257 ad2 = battle.av.damage;
00258 dd2 = battle.dv.damage;
00259
00260 if ( battle.dv.damage >= 100 )
00261 result = 2;
00262 else
00263 result = 1;
00264
00265 battle.setresult( context );
00266
00267 updateFieldInfo();
00268 }
00269 }
00270 delete atw;
00271 }
00272
00273 return result;
00274 }
00275
00276
00277 int tsearchreactionfireingunits :: checkfield ( const MapCoordinate3D& pos, Vehicle* &vehicle, const Context& context )
00278 {
00279
00280 int attacks = 0;
00281 int result = 0;
00282
00283 MapField* fld = gamemap->getField( pos.x, pos.y );
00284
00285 for ( int i = 0; i < 8; i++ ) {
00286 if ( fieldvisiblenow ( fld, i )) {
00287 punitlist ul = unitlist[i];
00288 while ( ul && !result ) {
00289 punitlist next = ul->next;
00290
00291 int r = attack( ul->eht, vehicle, context );
00292 if ( r > 0 )
00293 ++attacks;
00294
00295 if ( r > 1 )
00296 result = 1;
00297
00298 ul = next;
00299 }
00300 }
00301 }
00302
00303 if ( result )
00304 vehicle = NULL;
00305
00306 return attacks;
00307 }
00308
00309
00310 int tsearchreactionfireingunits :: finalCheck ( int currentPlayer, const Context& context )
00311 {
00312 int destroyedUnits = 0;
00313 for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
00314 if ( gamemap->getPlayer(currentPlayer).diplomacy.isHostile( player )) {
00315 list<int> exposedTargets;
00316 for ( Player::VehicleList::iterator exposedTarget = gamemap->getPlayer(currentPlayer).vehicleList.begin(); exposedTarget != gamemap->getPlayer(currentPlayer).vehicleList.end(); ++exposedTarget) {
00317 if ( fieldvisiblenow( gamemap->getField( (*exposedTarget)->getPosition() ), player )) {
00318 if ( visibleUnits.find( *exposedTarget ) == visibleUnits.end() || !(visibleUnits[*exposedTarget] & (1 << player)) ) {
00319 if ( (*exposedTarget)->getMap()->getField( (*exposedTarget)->getPosition() )->unitHere( *exposedTarget ))
00320 exposedTargets.push_back( (*exposedTarget )->networkid );
00321 }
00322 }
00323 }
00324
00325 for ( list<int>::iterator exposedTargetID = exposedTargets.begin(); exposedTargetID != exposedTargets.end(); ++exposedTargetID ) {
00326 Vehicle* exposedTarget = gamemap->getUnit( *exposedTargetID );
00327 if ( exposedTarget ) {
00328 bool destroyed = false;
00329
00330 for ( Player::VehicleList::iterator enemyUnit = gamemap->getPlayer(player).vehicleList.begin(); enemyUnit != gamemap->getPlayer(player).vehicleList.end() && !destroyed; ++enemyUnit) {
00331 if ( (*enemyUnit)->reactionfire.canPerformAttack( exposedTarget )) {
00332 if ( beeline( *enemyUnit, exposedTarget ) <= maxshootdist[ exposedTarget->getPosition().getNumericalHeight()]) {
00333 int r = attack( *enemyUnit, exposedTarget, context );
00334 if ( r > 1 ) {
00335 destroyed = true;
00336 ++destroyedUnits;
00337 }
00338 }
00339 }
00340 }
00341 }
00342 }
00343 }
00344 }
00345 return destroyedUnits;
00346 }
00347
00348
00349
00350 tsearchreactionfireingunits :: ~tsearchreactionfireingunits()
00351 {
00352 for ( int i = 0; i < 8; i++ ) {
00353 punitlist ul = unitlist[i];
00354 while ( ul ) {
00355 punitlist ul2 = ul->next;
00356 delete ul;
00357 ul = ul2;
00358 }
00359 }
00360 }
00361
00362
00363