00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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;
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
00179
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
00290 av.attackbonus = field->getattackbonus();
00291
00292
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
00387 if ( _attackingunit->damage >= 100 ) {
00388 delete *_pattackingunit;
00389 *_pattackingunit = NULL;
00390 }
00391
00392
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
00464 av.attackbonus = field->getattackbonus();
00465
00466
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;
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
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
00502 if ( _attackingunit->damage >= 100 ) {
00503 delete _attackingunit;
00504 _attackingunit = NULL;
00505 }
00506
00507
00508
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
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
00687 av.attackbonus = field2->getattackbonus();
00688
00689
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;
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
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
00722 if ( _obji->damage >= 100 ) {
00723 getfield ( _x, _y )-> removeobject ( _obji->typ );
00724 }
00725
00726
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
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
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
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
01007
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 )
01018 return 1;
01019
01020
01021
01022
01023
01024
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
01048
01049
01050
01051 float relpos = float(reldiff) / 255.0;
01052
01053
01054
01055
01056
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
01084
01085
01086
01087
01088
01089 }
01090
01091