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

attack.cpp

Go to the documentation of this file.
00001 
00006 /*
00007     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00008     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU General Public License for more details.
00019 
00020     You should have received a copy of the GNU General Public License
00021     along with this program; see the file COPYING. If not, write to the 
00022     Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00023     Boston, MA  02111-1307  USA
00024 */
00025 
00026 
00027 
00028 #include <stdio.h>
00029 #include <math.h>
00030 
00031 #include "typen.h"
00032 #include "buildingtype.h"
00033 #include "vehicletype.h"
00034 #include "attack.h"
00035 #include "spfst.h"
00036 
00037 
00038 
00039 bool  AttackFormula :: checkHemming ( Vehicle*     d_eht,  int     direc )
00040 { 
00041    Vehicle*     s_eht;
00042 
00043    int x = d_eht->xpos;
00044    int y = d_eht->ypos; 
00045    getnextfield(x, y, direc);
00046    tfield* fld = getfield(x,y);
00047 
00048    if ( fld )
00049       s_eht = fld->vehicle;
00050    else 
00051       s_eht = NULL;
00052 
00053    if ( !s_eht )
00054       return false;
00055 
00056    if ( s_eht->height >= chtieffliegend || d_eht->height >= chtieffliegend )
00057       return false;
00058 
00059    return attackpossible2n ( s_eht, d_eht );
00060 } 
00061 
00062 
00063 float AttackFormula :: getHemmingFactor ( int relDir )
00064 {
00065    const float  maxHemmingFactor = 1.4;  // = +140% !
00066    const float hemming[sidenum-1]  = { 4, 11, 16, 11, 4 };
00067    const float maxHemmingSum = 46;
00068    relDir  %= 6;
00069    if ( relDir < 0 )
00070       relDir += sidenum;
00071 
00072    if ( relDir == 5 )
00073       warning("float AttackFormula :: getHemmingFactor - invalid direction" );
00074       
00075    return hemming[relDir]*maxHemmingFactor/maxHemmingSum;
00076 }
00077 
00078 
00079 float AttackFormula :: strength_hemming ( int  ax,  int ay,  Vehicle* d_eht )
00080 {
00081    float hemm = 0;
00082    int attackDir = getdirection(ax,ay,d_eht->xpos,d_eht->ypos);
00083    for ( int i = 0; i < sidenum-1; i++) {
00084 
00085       int direc = i+1 + (attackDir-sidenum/2);
00086       if (direc < 0)
00087          direc += sidenum;
00088 
00089       if (direc >= sidenum)
00090          direc -= sidenum;
00091 
00092       if ( checkHemming (d_eht,direc ))
00093          hemm += getHemmingFactor(i);
00094    }
00095 
00096    return  hemm + 1;
00097 }
00098 
00099 
00100 float AttackFormula :: strength_damage ( int damage )
00101 {
00102    return 1 - (2.0 * float(damage) / 300.0);
00103 }
00104 
00105 float AttackFormula :: strength_experience ( int experience )
00106 {
00107         float e =               (experience < 0)
00108                                 ?       0       
00109                                 :       experience ;
00110    return e/maxunitexperience * 2.875 / actmap->getgameparameter( cgp_experienceDivisorAttack );
00111 }
00112 
00113 float AttackFormula :: defense_experience ( int experience )
00114 {
00115    float e =            (experience < 0)
00116                                 ?       0
00117                                 :       experience ;
00118 
00119    return e/maxunitexperience * 1.15 / actmap->getgameparameter( cgp_experienceDivisorDefense );
00120 }
00121 
00122 float AttackFormula :: strength_attackbonus ( int abonus )
00123 {
00124    float a = abonus;
00125    return a/8;
00126 }
00127 
00128 
00129 float AttackFormula :: defense_defensebonus ( int defensebonus )
00130 {
00131    float d = defensebonus;
00132    return d/8;
00133 }
00134 
00135 
00136 
00137 tfight :: tfight ( void )
00138 {
00139 }
00140 
00141 
00142 void tfight :: calc ( void )
00143 {
00144    int damagefactor = actmap->getgameparameter ( cgp_attackPower );
00145    const float armordivisor = 5;
00146 
00147 
00148    if ( av.strength ) { 
00149       float absstrength = float(av.strength )
00150                           * ( 1 + strength_experience ( av.experience ) + strength_attackbonus ( av.attackbonus ) )
00151                           * strength_damage ( av.damage ) 
00152                           * dv.hemming;
00153 
00154       float absdefense = float(dv.armor / armordivisor )
00155                           * ( 1 + defense_defensebonus ( dv.defensebonus ) + defense_experience ( dv.experience ) );
00156 
00157       int w = int( ceil(dv.damage + absstrength / absdefense * 1000 / damagefactor ));
00158 
00159       if (dv.damage > w ) 
00160          warning("fatal error at attack: \ndecrease of damage d!");
00161 
00162       if (dv.damage == w )
00163          w = dv.damage+1;
00164 
00165       if (w > 100) 
00166          dv.damage = 100; 
00167       else 
00168          dv.damage = w; 
00169 
00170       if ( av.weapcount > 0 )
00171          av.weapcount--;
00172       else
00173          av.weapcount = 0;
00174 
00175 
00176       av.experience++;
00177 
00178 //      if ( dist <= 10 && dv.strength > 0 )
00179 //         av.experience += 1;
00180 
00181       if ( dv.damage >= 100 ) 
00182          av.experience += 1;
00183 
00184 
00185 
00186       if ( av.experience > maxunitexperience )
00187          av.experience = maxunitexperience;
00188 
00189    } 
00190 
00191    if ( dv.strength ) { 
00192       float absstrength = float(dv.strength )
00193                           * ( 1 + strength_experience ( dv.experience ) + strength_attackbonus ( dv.attackbonus ) )
00194                           * strength_damage ( dv.damage ) ;
00195 
00196       float absdefense = float(av.armor / armordivisor)
00197                           * ( 1 + defense_defensebonus ( av.defensebonus )+ defense_experience ( av.experience ));
00198 
00199       int w = int( ceil(av.damage + absstrength / absdefense * 1000 / damagefactor ));
00200 
00201       if (av.damage > w ) 
00202          warning("fatal error at attack: \ndecrease of damage a!");
00203 
00204       if (w > 100) 
00205          av.damage = 100; 
00206       else 
00207          av.damage = w; 
00208 
00209 
00210       if ( dv.weapcount > 0 )
00211          dv.weapcount--;
00212       else
00213          dv.weapcount = 0;
00214 
00215       if ( av.damage >= 100 ) {
00216          dv.experience += 2;
00217          if ( dv.experience > maxunitexperience )
00218             dv.experience = maxunitexperience;
00219 
00220       } else
00221         if ( dv.experience < maxunitexperience )
00222            dv.experience++;
00223    } 
00224 
00225    if ( av.kamikaze ) 
00226       av.damage = 100;
00227 
00228 }
00229 
00230 
00231 
00232 tunitattacksunit :: tunitattacksunit ( Vehicle* &attackingunit, Vehicle* &attackedunit, bool respond, int weapon, bool reactionfire )
00233 {
00234    this->reactionfire = reactionfire;
00235    setup ( attackingunit, attackedunit, respond, weapon );
00236 }
00237 
00238 void tunitattacksunit :: setup ( Vehicle* &attackingunit, Vehicle* &attackedunit, bool respond, int weapon )
00239 {
00240    _attackingunit = attackingunit;
00241    _attackedunit  = attackedunit;
00242 
00243    _pattackingunit = &attackingunit;
00244    _pattackedunit  = &attackedunit;
00245 
00246    dist = beeline ( attackingunit->xpos, attackingunit->ypos, attackedunit->xpos, attackedunit->ypos );
00247    int _weapon;
00248 
00249    if ( weapon == -1 ) {
00250       pattackweap atw = attackpossible( attackingunit, attackedunit->xpos, attackedunit->ypos );
00251       int n = -1;
00252       int s = 0;
00253       for ( int i = 0; i < atw->count; i++ )
00254          if ( atw->strength[i] > s ) {
00255             s = atw->strength[i];
00256             n = i;
00257          }
00258 
00259       _weapon = atw->num[n];
00260 
00261       delete atw;
00262 
00263    } else
00264       _weapon  = weapon;
00265 
00266    const SingleWeapon* weap = attackingunit->getWeapon(_weapon);
00267 
00268 
00269    int targetWeather = attackedunit->getMap()->getField( attackedunit->getPosition() )->getweather();
00270 
00271    av.strength = int ( ceil( attackingunit->weapstrength[_weapon]
00272                         * WeapDist::getWeaponStrength(weap, targetWeather, dist, attackingunit->height, attackedunit->height )
00273                         * attackingunit->typ->weapons.weapon[_weapon].targetingAccuracy[attackedunit->typ->movemalustyp] / 100 ));
00274    av.armor  = attackingunit->getArmor();
00275    av.damage     = attackingunit->damage;
00276    av.experience  = attackingunit->experience;
00277    av.hemming    = 1;
00278    av.weapnum    = _weapon;
00279    av.weapcount  = attackingunit->ammo [ _weapon ];
00280    av.color      = attackingunit->getOwner();
00281    av.initiative = attackingunit->typ->initiative;
00282    av.kamikaze   = attackingunit->typ->hasFunction( ContainerBaseType::KamikazeOnly  );
00283    av.height = attackingunit->height;
00284    av.weapontype = attackingunit->typ->weapons.weapon[ _weapon ].getScalarWeaponType();
00285 
00286    tfield* field = getfield ( attackingunit->xpos, attackingunit->ypos );
00287 
00288    if ( attackingunit->height <= chfahrend ) {
00289       // if ( dist <= maxmalq )
00290          av.attackbonus  = field->getattackbonus();
00291       //else
00292       //   av.attackbonus = 0;
00293       av.defensebonus = field->getdefensebonus();
00294    } else {
00295       av.attackbonus = 0;
00296       av.defensebonus = 0;
00297    }
00298 
00299 
00300    dv.weapnum = -1;
00301    if ( dist <= maxmalq  &&  respond  && !av.kamikaze  && fieldvisiblenow( field, attackedunit->getOwner()) ) {
00302       AttackWeap atw;
00303       attackpossible2n ( attackedunit, attackingunit, &atw );
00304       int n = -1;
00305       int s = 0;
00306       for ( int i = 0; i < atw.count; i++ )
00307          if ( atw.strength[i] > s ) {
00308             s = atw.strength[i];
00309             n = i;
00310          }
00311 
00312       if ( n < 0 )
00313          respond = 0;
00314       else
00315          dv.weapnum = atw.num [ n ];
00316 
00317    } else
00318       respond = 0;
00319 
00320    if ( attackedunit->typ->hasFunction( ContainerBaseType::KamikazeOnly  ))
00321       respond = 0;
00322 
00323    if ( respond ) {
00324       weap = attackedunit->getWeapon( dv.weapnum );
00325 
00326 
00327       int attackerWeather = attackingunit->getMap()->getField( attackingunit->getPosition() )->getweather();
00328 
00329       dv.strength  = int ( ceil( attackedunit->weapstrength[ dv.weapnum ]
00330                            * WeapDist::getWeaponStrength(weap, attackerWeather, dist, attackedunit->height, attackingunit->height )
00331                            * attackedunit->typ->weapons.weapon[ dv.weapnum ].targetingAccuracy[attackingunit->typ->movemalustyp] / 100 ));
00332       field = getfield ( attackedunit->xpos, attackedunit->ypos );
00333       dv.attackbonus  = field->getattackbonus();
00334       _respond = 1;
00335 
00336       dv.weapcount   = attackedunit->ammo [ dv.weapnum ];
00337       dv.weapontype = attackedunit->typ->weapons.weapon[ dv.weapnum ].getScalarWeaponType();
00338 
00339    } else {
00340       dv.strength = 0;
00341       dv.attackbonus = 0;
00342       _respond = 0;
00343    }
00344 
00345 
00346    dv.armor = attackedunit->getArmor();
00347    dv.damage    = attackedunit->damage;
00348    dv.experience = attackedunit->experience;
00349    if ( dist <= maxmalq && attackingunit->height < chtieffliegend )
00350       dv.hemming = strength_hemming ( attackingunit->xpos, attackingunit->ypos, attackedunit );
00351    else
00352       dv.hemming = 1;
00353 
00354 
00355    if ( attackedunit->height <= chfahrend )
00356       dv.defensebonus = getfield ( attackedunit->xpos, attackedunit->ypos ) -> getdefensebonus();
00357    else
00358       dv.defensebonus = 0;
00359 
00360    dv.color      = attackedunit->getOwner();
00361    dv.initiative = attackedunit->typ->initiative;
00362    dv.kamikaze = 0;
00363    dv.height = attackedunit->height;
00364 }
00365 
00366 
00367 
00368 void tunitattacksunit :: setresult ( void )
00369 {
00370    _attackingunit->experience = av.experience;
00371    _attackingunit->ammo[ av.weapnum ] = av.weapcount;
00372 
00373    _attackingunit->postAttack( reactionfire );
00374 
00375    _attackingunit->reactionfire.weaponShots[ av.weapnum]--;
00376    _attackingunit->reactionfire.nonattackableUnits.push_back ( _attackedunit->networkid );
00377 
00378    _attackedunit->damage    = dv.damage;
00379    _attackingunit->damage    = av.damage;
00380 
00381    if ( _respond ) {
00382       _attackedunit->experience = dv.experience;
00383       _attackedunit->ammo[ dv.weapnum ] = dv.weapcount;
00384    }
00385 
00386    /* If the attacking vehicle was destroyed, remove it */
00387    if ( _attackingunit->damage >= 100 ) {
00388      delete *_pattackingunit;
00389      *_pattackingunit = NULL;
00390    }
00391 
00392    /* If the attacked vehicle was destroyed, remove it */
00393    if ( _attackedunit->damage >= 100 ) {
00394      delete *_pattackedunit;
00395      *_pattackedunit = NULL;
00396    }
00397    actmap->time.set ( actmap->time.turn(), actmap->time.move()+1);
00398 }
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 tunitattacksbuilding :: tunitattacksbuilding ( Vehicle* attackingunit, int x, int y, int weapon )
00408 {
00409    setup ( attackingunit, x, y, weapon );
00410 }
00411 
00412 
00413 void tunitattacksbuilding :: setup ( Vehicle* attackingunit, int x, int y, int weapon )
00414 {
00415    _attackingunit = attackingunit;
00416    _x = x;
00417    _y = y;
00418    _attackedbuilding  = getfield ( x, y ) -> building;
00419 
00420    dist = beeline ( attackingunit->xpos, attackingunit->ypos, x, y );
00421    int _weapon;
00422 
00423    if ( weapon == -1 ) {
00424       pattackweap atw = attackpossible( attackingunit, x, y );
00425       int n = -1;
00426       int s = 0;
00427       for ( int i = 0; i < atw->count; i++ )
00428          if ( atw->strength[i] > s ) {
00429             s = atw->strength[i];
00430             n = i;
00431          }
00432 
00433       _weapon = atw->num[n];
00434 
00435       delete atw;
00436    } else
00437       _weapon  = weapon;
00438 
00439    const SingleWeapon *weap = &attackingunit->typ->weapons.weapon[_weapon];
00440 
00441    int targetWeather = getfield(x,y)->getweather();
00442 
00443    av.strength  = int (ceil( attackingunit->weapstrength[_weapon]
00444                         * WeapDist::getWeaponStrength(weap, targetWeather, dist, attackingunit->height, _attackedbuilding->typ->buildingheight )
00445                         * attackingunit->typ->weapons.weapon[_weapon].targetingAccuracy[cmm_building] / 100 ));
00446 
00447    av.armor = attackingunit->getArmor();
00448    av.damage    = attackingunit->damage;
00449    av.experience = attackingunit->experience;
00450    av.hemming    = 1;
00451    av.weapnum    = _weapon;
00452    av.weapcount  = attackingunit->ammo [ _weapon ];
00453    av.weapontype = attackingunit->typ->weapons.weapon[ _weapon ].getScalarWeaponType();
00454    av.color      = attackingunit->getOwner();
00455    av.initiative = attackingunit->typ->initiative;
00456    av.kamikaze   = attackingunit->typ->hasFunction( ContainerBaseType::KamikazeOnly  );
00457    av.height = attackingunit->height;
00458 
00459    tfield* field = getfield ( attackingunit->xpos, attackingunit->ypos );
00460 
00461    if ( attackingunit->height <= chfahrend ) {
00462       av.defensebonus = field->getdefensebonus();
00463       // if ( dist <= maxmalq )
00464          av.attackbonus  = field->getattackbonus();
00465       //else
00466       //   av.attackbonus = 0;
00467    } else {
00468       av.defensebonus = 0;
00469       av.attackbonus  = 0;
00470    }
00471 
00472 
00473    dv.strength = 0;
00474    dv.attackbonus = 0;
00475 
00476 
00477    dv.armor = _attackedbuilding->getArmor();
00478    dv.damage    = _attackedbuilding->damage;
00479    dv.experience = 0;
00480    dv.hemming    = 1;
00481    dv.weapnum = -1;
00482 
00483    dv.defensebonus = 0; // getfield ( x, y ) -> getdefensebonus();
00484    dv.color      = _attackedbuilding->getOwner();
00485    dv.initiative = 0;
00486    dv.kamikaze = 0;
00487    dv.height = _attackedbuilding->typ->buildingheight;
00488 }
00489 
00490 
00491 void tunitattacksbuilding :: setresult ( void )
00492 {
00493    // _attackingunit->experience = av.experience;
00494    _attackingunit->ammo[ av.weapnum ] = av.weapcount;
00495 
00496    _attackingunit->postAttack( false );
00497 
00498    _attackingunit->damage    = av.damage;
00499    _attackedbuilding->damage    = dv.damage;
00500 
00501    /* Remove the attacking unit if it was destroyed */
00502    if ( _attackingunit->damage >= 100 ) {
00503       delete _attackingunit;
00504       _attackingunit = NULL;
00505    }
00506 
00507 
00508    /* Remove attacked building if it was destroyed */
00509    if ( _attackedbuilding->damage >= 100 ) {
00510      delete _attackedbuilding ;
00511      _attackedbuilding = NULL;
00512    }
00513 
00514    actmap->time.set ( actmap->time.turn(), actmap->time.move()+1);
00515 }
00516 
00517 
00518 
00519 tmineattacksunit :: tmineattacksunit ( tfield* mineposition, int minenum, Vehicle* &attackedunit )
00520 {
00521    setup ( mineposition, minenum, attackedunit );
00522 }
00523 
00524 void tmineattacksunit :: setup ( tfield* mineposition, int minenum, Vehicle* &attackedunit )
00525 {
00526    if ( mineposition->mines.empty() )
00527       errorMessage(" tmineattacksunit :: setup \n no mine to attack !\n" );
00528 
00529    if ( attackedunit->height >= chtieffliegend )
00530       errorMessage(" tmineattacksunit :: setup \n mine attacks flying unit!\n" );
00531 
00532    dist = 10;
00533 
00534    _mineposition = mineposition;
00535    _attackedunit = attackedunit;
00536    _pattackedunit = &attackedunit;
00537 
00538 
00539    _minenum = minenum;
00540 
00541    if ( minenum == -1 ) {
00542       int cnt = 1;
00543       av.strength = 0;
00544       for ( tfield::MineContainer::iterator m = mineposition->mines.begin(); m != mineposition->mines.end(); m++ )
00545          if ( m->attacksunit ( attackedunit )) {
00546             int strength = m->strength;
00547             if ( m->type == cmantipersonnelmine   &&  (attackedunit->typ->movemalustyp ==  cmm_trooper ) )
00548                strength *= 2;
00549 
00550             for ( int j = 1; j < cnt; j++ )
00551                strength = strength * 2 / 3;
00552 
00553             av.strength += strength;
00554             cnt++;
00555          }
00556    } else {
00557       Mine& m = mineposition->getMine ( minenum );
00558       av.strength = m.strength;
00559       if ( m.type  == cmantipersonnelmine   &&  (attackedunit->typ->movemalustyp ==  cmm_trooper ) )
00560          av.strength *= 2;
00561    }
00562 
00563    av.armor = 1;
00564    av.damage = 0;
00565    av.experience = 0;
00566    av.defensebonus = 0;
00567    av.hemming    = 1;
00568    av.weapnum = 0;
00569    av.weapcount = 1;
00570    av.color = 8;
00571    av.initiative = 256;
00572    av.attackbonus = 8;
00573    av.kamikaze = 0;
00574    av.height = 0;
00575    av.weapontype = cwminen;
00576 
00577    dv.strength = 0;
00578    dv.armor = attackedunit->getArmor();
00579    dv.damage    = attackedunit->damage;
00580    dv.experience = attackedunit->experience;
00581    dv.defensebonus = 0;
00582    dv.hemming    = 1;
00583    dv.weapnum = 0;
00584    dv.weapcount = 0;
00585    dv.color = attackedunit->getOwner();
00586    dv.initiative = attackedunit->typ->initiative;
00587    dv.attackbonus = 0;
00588    dv.kamikaze = 0;
00589    dv.height = attackedunit->height;
00590 }
00591 
00592 
00593 void tmineattacksunit :: setresult ( void )
00594 {
00595    if ( _minenum == -1 ) {
00596       for ( tfield::MineContainer::iterator m = _mineposition->mines.begin(); m != _mineposition->mines.end(); )
00597          if ( m->attacksunit ( _attackedunit ))
00598             m = _mineposition->mines.erase ( m );
00599          else
00600             m++;
00601    } else
00602       _mineposition->removemine ( _minenum );
00603 
00604    _attackedunit->damage = dv.damage;
00605 
00606    /* Remove the mined vehicle if it was destroyed */
00607    if ( _attackedunit->damage >= 100 ) {
00608      delete *_pattackedunit;
00609      *_pattackedunit = NULL;
00610    }
00611 
00612 }
00613 
00614 
00615 Mine* tmineattacksunit :: getFirstMine()
00616 {
00617    if ( _mineposition && _mineposition->mines.size() )
00618       return &( * _mineposition->mines.begin() );
00619    else
00620       return NULL;
00621 }
00622 
00623 
00624 
00625 tunitattacksobject :: tunitattacksobject ( Vehicle* attackingunit, int obj_x, int obj_y, int weapon )
00626 {
00627    setup ( attackingunit, obj_x, obj_y, weapon );
00628 }
00629 
00630 void tunitattacksobject :: setup ( Vehicle* attackingunit, int obj_x, int obj_y, int weapon )
00631 {
00632 
00633    _x = obj_x;
00634    _y = obj_y;
00635 
00636    targetField = getfield ( obj_x, obj_y );
00637 
00638    _attackingunit = attackingunit;
00639 
00640    dist = beeline ( attackingunit->xpos, attackingunit->ypos, obj_x, obj_y );
00641 
00642    for ( tfield::ObjectContainer::reverse_iterator o = targetField->objects.rbegin(); o != targetField->objects.rend(); o++ )
00643       if ( o->typ->armor > 0 ) {
00644          _obji = &(*o);
00645          break;
00646       }
00647 
00648    int _weapon;
00649 
00650    if ( weapon == -1 ) {
00651 
00652       pattackweap atw = attackpossible( attackingunit, obj_x, obj_y );
00653       int n = -1;
00654       int s = 0;
00655       for ( int i = 0; i < atw->count; i++ )
00656          if ( atw->strength[i] > s ) {
00657             s = atw->strength[i];
00658             n = i;
00659          }
00660 
00661       _weapon = atw->num[n];
00662 
00663       delete atw;
00664 
00665    } else
00666       _weapon  = weapon;
00667 
00668    const SingleWeapon *weap = &attackingunit->typ->weapons.weapon[weapon];
00669    av.strength  = int ( ceil( attackingunit->weapstrength[weapon]
00670                         * WeapDist::getWeaponStrength(weap, targetField->getweather(), dist, attackingunit->height, _obji->typ->getEffectiveHeight() )
00671                         * attackingunit->typ->weapons.weapon[_weapon].targetingAccuracy[cmm_building] / 100 ));
00672 
00673    av.armor = attackingunit->getArmor();
00674    av.damage    = attackingunit->damage;
00675    av.experience = attackingunit->experience;
00676    av.weapnum    = _weapon;
00677    av.weapcount   = attackingunit->ammo [ _weapon ];
00678    av.kamikaze   = attackingunit->typ->hasFunction( ContainerBaseType::KamikazeOnly  );
00679    av.height = attackingunit->height;
00680    av.weapontype = attackingunit->typ->weapons.weapon[ _weapon ].getScalarWeaponType();
00681 
00682    tfield* field2 = getfield ( attackingunit->xpos, attackingunit->ypos );
00683 
00684    if ( attackingunit->height <= chfahrend ) {
00685       av.defensebonus = field2->getdefensebonus();
00686       // if ( dist <= maxmalq )
00687          av.attackbonus  = field2->getattackbonus();
00688       //else
00689       //   av.attackbonus = 0;
00690    } else {
00691       av.defensebonus = 0;
00692       av.attackbonus  = 0;
00693    }
00694 
00695 
00696    dv.strength = 0;
00697    dv.attackbonus = 0;
00698 
00699    dv.armor = _obji->typ->armor;
00700    dv.damage    = _obji->damage;
00701    dv.experience = 0;
00702 
00703    dv.defensebonus = 0; // field  -> getdefensebonus();
00704    dv.hemming    = 1;
00705    dv.color = 8 ;
00706    dv.kamikaze = 0;
00707    dv.height = 0;
00708 }
00709 
00710 
00711 void tunitattacksobject :: setresult ( void )
00712 {
00713    // _attackingunit->experience = av.experience;
00714    _attackingunit->ammo[ av.weapnum ] = av.weapcount;
00715 
00716    _attackingunit->postAttack( false );
00717 
00718    _obji->damage    = dv.damage;
00719    _attackingunit->damage    = av.damage;
00720 
00721    /* Remove the object if it was destroyed */
00722    if ( _obji->damage >= 100 ) {
00723      getfield ( _x, _y )-> removeobject ( _obji->typ );
00724    }
00725 
00726    /* Remove the attacking unit if it was destroyed */
00727    if ( _attackingunit->damage >= 100 ) {
00728       delete _attackingunit;
00729       _attackingunit = NULL;
00730    }
00731 
00732 
00733    actmap->time.set ( actmap->time.turn(), actmap->time.move()+1);
00734 
00735 }
00736 
00737 
00738 
00739 
00740 
00741 
00742 pattackweap  attackpossible( const Vehicle*     angreifer, int x, int y)
00743 {
00744   pattackweap atw = new AttackWeap;
00745 
00746   memset(atw, 0, sizeof(*atw));
00747 
00748 
00749    if ((x < 0) || (y < 0) || (x >= actmap->xsize) || (y >= actmap->ysize))
00750       return atw;
00751    if (angreifer == NULL)
00752       return atw;
00753    if (angreifer->typ->weapons.count == 0)
00754       return atw;
00755 
00756    tfield* efield = getfield(x,y);
00757 
00758    if ( efield->vehicle ) {
00759       if (fieldvisiblenow(efield, angreifer->color/8))
00760          attackpossible2n ( angreifer, efield->vehicle, atw );
00761    }
00762    else
00763       if (efield->building != NULL) {
00764          if ( actmap->getPlayer(angreifer).diplomacy.isHostile( efield->building->getOwner() ) || efield->building->color == 8*8 )
00765             for (int i = 0; i < angreifer->typ->weapons.count ; i++)
00766                if (angreifer->typ->weapons.weapon[i].shootable() )
00767                   if (angreifer->typ->weapons.weapon[i].offensive() )
00768                      if ( angreifer->typ->weapons.weapon[i].targetingAccuracy[cmm_building] > 0 ) {
00769                         int tm = efield->building->typ->buildingheight;
00770                         if (tm & angreifer->typ->weapons.weapon[i].targ) {
00771                            if (fieldvisiblenow(efield, angreifer->color/8)) {
00772                               int d = beeline(angreifer->xpos,angreifer->ypos,x,y);
00773                               if (d <= angreifer->typ->weapons.weapon[i].maxdistance)
00774                                  if (d >= angreifer->typ->weapons.weapon[i].mindistance) {
00775                                     if (angreifer->height & angreifer->typ->weapons.weapon[i].sourceheight)
00776                                        if ( angreifer->typ->weapons.weapon[i].efficiency[6 + getheightdelta ( log2( angreifer->height), log2(tm))] )
00777                                           if (angreifer->ammo[i] > 0) {
00778                                              atw->strength[atw->count ] = angreifer->weapstrength[i];
00779                                              atw->typ[atw->count ] = 1 << angreifer->typ->weapons.weapon[i].getScalarWeaponType() ;
00780                                              atw->num[atw->count ] = i;
00781                                              atw->target = AttackWeap::building;
00782                                              atw->count++;
00783                                           }
00784 
00785                                  }
00786                            }
00787                         }
00788                      }
00789       }
00790 
00791    if ( efield->objects.size() ) {
00792       int n = 0;
00793       for ( tfield::ObjectContainer::iterator j = efield->objects.begin(); j != efield->objects.end(); j++ )
00794          if ( j->typ->armor > 0 )
00795             n++;
00796 
00797       if ( n > 0 )
00798          if ((efield->vehicle == NULL) && ( efield->building == NULL)) {
00799             bool found = false;
00800             for ( tfield::ObjectContainer::reverse_iterator j = efield->objects.rbegin(); j != efield->objects.rend(); ++j ) {
00801                for ( int i = 0; i <= angreifer->typ->weapons.count - 1; i++)
00802                   if (angreifer->typ->weapons.weapon[i].shootable() )
00803                      if ( angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwcannonn ||
00804                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwlasern ||
00805                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwcruisemissile ||
00806                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwlargemissilen ||
00807                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwsmallmissilen ||
00808                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwtorpedon ||
00809                           angreifer->typ->weapons.weapon[i].getScalarWeaponType() == cwbombn ) {
00810                         if ( angreifer->typ->weapons.weapon[i].targetingAccuracy[cmm_building] )
00811                               if (fieldvisiblenow(efield, angreifer->color/8)) {
00812                                  int d = beeline(angreifer->xpos,angreifer->ypos,x,y);
00813                                  if (d <= angreifer->typ->weapons.weapon[i].maxdistance)
00814                                     if (d >= angreifer->typ->weapons.weapon[i].mindistance) {
00815                                        if (angreifer->height & angreifer->typ->weapons.weapon[i].sourceheight )
00816                                           if ( angreifer->typ->weapons.weapon[i].targ & j->typ->getEffectiveHeight() )
00817                                              if ( angreifer->typ->weapons.weapon[i].efficiency[6 + getheightdelta ( log2( angreifer->height), log2(j->typ->getEffectiveHeight()))] )
00818                                                 if (angreifer->ammo[i] > 0) {
00819                                                    atw->strength[atw->count ] = angreifer->weapstrength[i];
00820                                                    atw->num[atw->count ] = i;
00821                                                    atw->typ[atw->count ] = 1 << angreifer->typ->weapons.weapon[i].getScalarWeaponType();
00822                                                    atw->target = AttackWeap::object;
00823                                                    atw->count++;
00824                                                    found = true;
00825                                                 }
00826 
00827                                     }
00828                               }
00829 
00830                      }
00831                if ( found )
00832                   return atw;
00833             }
00834 
00835          }
00836    }
00837 
00838    return atw;
00839 }
00840 
00841 
00842 bool attackpossible2u( const Vehicle* attacker, const Vehicle* target, pattackweap atw, int targetheight )
00843 {
00844    if ( targetheight == -1 )
00845       targetheight = target->height;
00846 
00847    const Vehicle* angreifer = attacker;
00848    const Vehicle* verteidiger = target;
00849    int result = false;
00850    if ( atw )
00851       atw->count = 0;
00852 
00853    if ( !angreifer )
00854      return false ;
00855 
00856    if ( !verteidiger )
00857      return false ;
00858 
00859    if (angreifer->typ->weapons.count == 0)
00860      return false ;
00861 
00862    if ( actmap->player[angreifer->getOwner()].diplomacy.isHostile( verteidiger->getOwner() )  )
00863       for ( int i = 0; i < angreifer->typ->weapons.count ; i++)
00864          for ( int h = 0; h < 8; h++ )
00865             if ( targetheight & (1<<h))
00866                if (angreifer->typ->weapons.weapon[i].shootable() )
00867                   if (angreifer->typ->weapons.weapon[i].offensive() )
00868                      if ( (1<<h) & angreifer->typ->weapons.weapon[i].targ )
00869                         if (angreifer->height & angreifer->typ->weapons.weapon[i].sourceheight )
00870                            if ( angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp] > 0 )
00871                               if ( angreifer->typ->weapons.weapon[i].efficiency[6 + getheightdelta ( log2( angreifer->height), h)] )
00872                                  if (angreifer->ammo[i] > 0) {
00873                                     result = true;
00874                                     if ( atw ) {
00875                                        atw->strength[atw->count] = angreifer->weapstrength[i] * angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp] / 100;
00876                                        atw->num[atw->count ] = i;
00877                                        atw->typ[atw->count ] = 1 << angreifer->typ->weapons.weapon[i].getScalarWeaponType();
00878                                        atw->target = AttackWeap::vehicle;
00879                                        atw->count++;
00880                                     }
00881                                  }
00882 
00883    return result;
00884 }
00885 
00886 
00887 
00888 bool attackpossible28( const Vehicle* attacker, const Vehicle* target, pattackweap atw, int targetHeight )
00889 {
00890    const Vehicle* angreifer = attacker;
00891    const Vehicle* verteidiger = target;
00892 
00893    if ( targetHeight < 0 )
00894       targetHeight = target->height;
00895    
00896    int result = false;
00897    if ( atw )
00898       atw->count = 0;
00899 
00900    if (angreifer == NULL)
00901      return false ;
00902 
00903    if (verteidiger == NULL)
00904      return false ;
00905 
00906    if (angreifer->typ->weapons.count == 0)
00907      return false ;
00908 
00909 //   if ( actmap->player[angreifer->getOwner()].diplomacy.isHostile( verteidiger->getOwner() )  )
00910       for ( int i = 0; i < angreifer->typ->weapons.count ; i++)
00911          if (angreifer->typ->weapons.weapon[i].shootable() )
00912             if (angreifer->typ->weapons.weapon[i].offensive() )
00913                if (targetHeight & angreifer->typ->weapons.weapon[i].targ )
00914                   if (minmalq <= angreifer->typ->weapons.weapon[i].maxdistance)
00915                      if (minmalq >= angreifer->typ->weapons.weapon[i].mindistance)
00916                         if (angreifer->height & angreifer->typ->weapons.weapon[i].sourceheight )
00917                            if ( angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp ] > 0)
00918                               if ( angreifer->typ->weapons.weapon[i].efficiency[6 + getheightdelta ( log2( angreifer->height), log2(targetHeight))] )
00919                                  if (angreifer->ammo[i] > 0) {
00920                                     result =  true;
00921                                     if ( atw ) {
00922                                        atw->strength[atw->count] = angreifer->weapstrength[i] * angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp] / 100;
00923                                        atw->num[atw->count ] = i;
00924                                        atw->typ[atw->count ] = 1 << angreifer->typ->weapons.weapon[i].getScalarWeaponType();
00925                                        atw->target = AttackWeap::vehicle;
00926                                        atw->count++;
00927                                     }
00928                                  }
00929 
00930    return result;
00931 }
00932 
00933 
00934 bool attackpossible2n( const Vehicle* attacker, const Vehicle* target, pattackweap atw )
00935 {
00936    const Vehicle* angreifer = attacker;
00937    const Vehicle* verteidiger = target;
00938 
00939    int result = false;
00940    if ( atw )
00941       atw->count = 0;
00942 
00943    if (angreifer == NULL)
00944      return false ;
00945 
00946    if (verteidiger == NULL)
00947      return false ;
00948 
00949    if (angreifer->typ->weapons.count == 0)
00950      return false ;
00951 
00952    int dist = beeline ( angreifer, verteidiger );
00953    if ( actmap->player[angreifer->getOwner()].diplomacy.isHostile( verteidiger->getOwner() ) )
00954       if ( !angreifer->attacked )
00955          if ( !angreifer->typ->wait || !angreifer->hasMoved() || angreifer->reactionfire.getStatus() == Vehicle::ReactionFire::ready)
00956             for ( int i = 0; i < angreifer->typ->weapons.count ; i++)
00957                if (angreifer->typ->weapons.weapon[i].shootable() )
00958                   if (angreifer->typ->weapons.weapon[i].offensive() )
00959                      if (verteidiger->height & angreifer->typ->weapons.weapon[i].targ )
00960                         if (dist <= angreifer->typ->weapons.weapon[i].maxdistance)
00961                            if (dist >= angreifer->typ->weapons.weapon[i].mindistance)
00962                               if (angreifer->height & angreifer->typ->weapons.weapon[i].sourceheight )
00963                                  if ( angreifer->typ->weapons.weapon[i].efficiency[6 + getheightdelta ( log2( angreifer->height), log2(verteidiger->height))] )
00964                                     if ( angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp ] > 0)
00965                                        if (angreifer->ammo[i] > 0) {
00966                                           result = true;
00967                                           if ( atw ) {
00968                                              atw->strength[atw->count] = angreifer->weapstrength[i] * angreifer->typ->weapons.weapon[i].targetingAccuracy[ verteidiger->typ->movemalustyp ] / 100;
00969                                              atw->num[atw->count ] = i;
00970                                              atw->typ[atw->count ] = 1 << angreifer->typ->weapons.weapon[i].getScalarWeaponType();
00971                                              atw->target = AttackWeap::vehicle;
00972                                              atw->count++;
00973                                           }
00974                                        }
00975 
00976 
00977    return result;
00978 }
00979 
00980 bool vehicleplattfahrbar( const Vehicle*     vehicle,
00981                            const tfield*        field)
00982 {
00983    return false;
00984 /*
00985    if (vehicle == NULL)
00986       return ( false );
00987    if (field == NULL)
00988       return ( false );
00989    if (field->vehicle == NULL)
00990       return ( false );
00991 
00992    if ((vehicle->color != field->vehicle->color) &&
00993       (vehicle->height == chfahrend) &&
00994       (field->vehicle->height == chfahrend) && 
00995       (field->vehicle->functions & cftrooper) && 
00996       (vehicle->weight() >= fusstruppenplattfahrgewichtsfaktor * field->vehicle->weight()))
00997       return ( true ); 
00998    return ( false );
00999 */
01000 } 
01001 
01002 
01003 float WeapDist::getWeaponStrength ( const SingleWeapon* weap, int weather, int dist, int attacker_height, int defender_height, int reldiff  )
01004 {
01005 /*
01006   int         translat[31]  = { 6, 255, 1, 3, 2, 4, 0, 5, 255, 255, 6, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
01007                                  255, 255, 255, 255, 255, 255};
01008 */
01009 
01010    if ( !weap )
01011       return 0;
01012 
01013    int scalar = weap->getScalarWeaponType();
01014    if ( scalar >= 31 || scalar < 0 )
01015       return 0;
01016 
01017    if ( scalar == 1 )     // mine
01018       return 1;
01019 
01020       /*
01021    int typ = translat[ scalar ];
01022    if ( typ == 255 ) {
01023       displaymessage("tweapdist::getweapstrength: invalid type ", 1 );
01024       return 1;
01025    }
01026    */
01027 
01028 
01029    if ( weap->maxdistance == 0 )
01030       return 0;
01031 
01032    if ( weap->minstrength == 0 )
01033       return 0;
01034 
01035    if ( reldiff == -1) {
01036       if ( dist < weap->mindistance || dist > weap->maxdistance ) {
01037          warning("tweapdist::getweapstrength: invalid range: \n min = " + ASCString::toString(weap->mindistance ) + " ; max = " + ASCString::toString( weap->maxdistance ) + " ; req = " + ASCString::toString( dist));
01038          return 0;
01039       }
01040 
01041       if ( weap->maxdistance - weap->mindistance != 0 )
01042          reldiff = 255 * (dist - weap->mindistance) / ( weap->maxdistance - weap->mindistance) ;
01043       else
01044          reldiff = 0;
01045    }
01046 
01047 //   int minstrength = 255 - 255 * weap->minstrength / weap->maxstrength;
01048 
01049 //   int relstrength = 255 - ( 255 - data[typ][reldiff] ) * minstrength / ( 255 - data[typ][255] );
01050 
01051    float relpos = float(reldiff) / 255.0;
01052 
01053 /*   if ( weap->maxstrength && weap->minstrength )
01054       relpos /= float(weap->maxstrength) / float(weap->minstrength);
01055 
01056    return 1.0 - relpos;*/
01057 
01058 
01059    float relstrength = weap->maxstrength - relpos * ( weap->maxstrength - weap->minstrength );
01060 
01061    float weatherFactor = 1;
01062    int heightEff = 100;
01063    if ( attacker_height != -1 && defender_height != -1 ) {
01064       int hd = getheightdelta ( log2 ( attacker_height ), log2 ( defender_height ));
01065       heightEff = weap->efficiency[6+hd];
01066 
01067       if ( attacker_height >= chtieffliegend && weather != 0 && defender_height != -1) {
01068          int weatherRelevantHeightDelta = min( abs( getheightdelta ( log2 ( attacker_height ), log2 ( defender_height ))), 3);
01069          if ( weather == 1 || weather == 3  )
01070             weatherFactor = 1 - 0.07*weatherRelevantHeightDelta;
01071          else
01072             if ( weather == 2 || weather == 4 || weather == 5 )
01073                weatherFactor = 1 - 0.2 * weatherRelevantHeightDelta;
01074       }
01075 
01076       if ( attacker_height == chsatellit )
01077          weatherFactor = 1 - (1-weatherFactor)/2;
01078    }
01079 
01080 
01081    return relstrength * heightEff * weatherFactor / float(weap->maxstrength * 100) ;
01082 
01083 /*   if ( attacker_height != -1 && defender_height!= -1 ) {
01084       int hd = getheightdelta ( log2 ( attacker_height ), log2 ( defender_height ));
01085       return relstrength * weap->efficiency[6+hd] / 100 ;
01086    } else
01087       return relstrength ;
01088       */
01089 }
01090 
01091 

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