Advanced Strategic Command
vehicle.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  vehicle.cpp - description
3  -------------------
4  begin : Fri Sep 29 2000
5  copyright : (C) 2000 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <algorithm>
19 #include <math.h>
20 #include "research.h"
21 #include "vehicletype.h"
22 #include "vehicle.h"
23 #include "buildingtype.h"
24 #include "viewcalculation.h"
25 #include "errors.h"
26 #include "graphicset.h"
27 #include "errors.h"
28 #include "gameoptions.h"
29 #include "spfst.h"
30 #include "itemrepository.h"
31 #include "graphics/blitter.h"
32 
33 #include "actions/context.h"
36 #include "actions/spawnobject.h"
38 
39 #include "attack.h"
40 
42  0, 0.5, 0,
43  0.5, 0, 1 };
44 
45 
46 #ifndef UNITVERSIONLIMIT
47 # define UNITVERSIONLIMIT 0x7fffffff
48 #endif
49 
50 
51 
52 Vehicle :: Vehicle ( )
53  : ContainerBase ( NULL, NULL, 0 ), repairEfficiency ( repairEfficiencyVehicle ), typ ( NULL ), reactionfire ( this )
54 {
55 }
56 
57 Vehicle :: Vehicle ( const Vehicle& v )
58  : ContainerBase ( NULL, NULL, 0 ), repairEfficiency ( repairEfficiencyVehicle ), typ ( NULL ), reactionfire ( this )
59 {
60 }
61 
62 
63 Vehicle :: Vehicle ( const VehicleType* t, GameMap* actmap, int player )
64  : ContainerBase ( t, actmap, player ), repairEfficiency ( repairEfficiencyVehicle ), typ ( t ), reactionfire ( this )
65 {
66  viewOnMap = false;
67 
68  if ( player > 8 )
69  fatalError ( "Vehicle :: Vehicle ; invalid player ");
70 
71  init();
72 
73  gamemap->player[player].vehicleList.push_back ( this );
74 
77 }
78 
79 Vehicle :: Vehicle ( const VehicleType* t, GameMap* actmap, int player, int networkID )
80  : ContainerBase ( t, actmap, player ), repairEfficiency ( repairEfficiencyVehicle ), typ ( t ), reactionfire ( this )
81 {
82  viewOnMap = false;
83 
84  if ( player > 8 )
85  fatalError ( "Vehicle :: Vehicle ; invalid player ");
86 
87  init();
88 
89  gamemap->player[player].vehicleList.push_back ( this );
90  if ( networkID == -1 ) {
92  } else
93  if ( networkID >= 0 ) {
94  networkid = networkID;
95  }
96 
97  if ( networkID >= 0 )
99 }
100 
101 
103 {
104  for ( int i = 0; i < 8; i++ ) {
105  delete aiparam[i];
106  aiparam[i] = NULL;
107  }
108 
109 
110 
111  if ( viewOnMap && gamemap && gamemap->state != GameMap::Destruction ) {
112  removeview();
113  viewOnMap = false;
114  }
115 
116  if ( gamemap ) {
117  int c = color/8;
118 
119  Player::VehicleList::iterator i = find ( gamemap->player[c].vehicleList.begin(), gamemap->player[c].vehicleList.end(), this );
120  if ( i != gamemap->player[c].vehicleList.end() )
121  gamemap->player[c].vehicleList.erase ( i );
122 
124  }
125 
126  MapField* fld = gamemap->getField( xpos, ypos);
127  if ( fld && fld->vehicle == this )
128  fld->vehicle = NULL;
129 
130  if ( fld && fld->secondvehicle == this )
131  fld->secondvehicle = NULL;
132 
133 
134  if ( getCarrier() )
135  getCarrier()->removeUnitFromCargo( this, true );
136 }
137 
138 
139 
140 
141 void Vehicle :: init ( void )
142 {
143  xpos = -1;
144  ypos = -1;
145 
146  for ( int i = 0; i < 16; i++ ) {
147  weapstrength[i] = 0;
148  ammo[i] = 0;
149  }
150 
151  damage = 0;
152 
153  experience_offensive = 0;
154  experience_defensive = 0;
155 
156  attacked = false;
157 
158  if ( typ ) {
159  height = 1 << getFirstBit( typ->height );
160 
161  // These are the preferred levels of height
162  if (typ->height & chfahrend )
163  height = chfahrend;
164  else
165  if (typ->height & chschwimmend )
167 
168  for ( int m = 0; m < typ->weapons.count ; m++)
170 
172  } else {
173  height = 0;
174 
175  setMovement ( 0, 0 );
176  }
177 
178  direction = 0;
179  xpos = -1;
180  ypos = -1;
181  connection = 0;
182  networkid = -1;
183 
186  else
188 
189  generatoractive = 0;
190 
191  cleanRemove = false;
192 
193  for ( int a = 0; a < 8 ; a++ )
194  aiparam[a] = NULL;
195 }
196 
197 
198 bool Vehicle :: canRepair( const ContainerBase* item ) const
199 {
202  (item == this && typ->autorepairrate ) ;
203 }
204 
206 static const int repairExperienceDecrease = 20;
207 
208 
209 int Vehicle::getRepairExperienceValue( int oldDamage, int newDamage, bool offensive, int roundToResolution )
210 {
211  /*
212  This is an alternative Strategy that removes as much experience points as are necessary to achieve the desired decrease of attack bonus
213  int decreasePercentage = (oldDamage - newDamage) * repairExperienceDecrease / 100;
214 
215 
216  AttackFormula af( getMap() );
217 
218 
219  int experience;
220  if ( offensive )
221  experience = experience_offensive;
222  else
223  experience = experience_defensive;
224  int oldExperience = experience;
225 
226  float origPower = af.strength_experience( experience );
227  while ( experience > 0 && af.strength_experience( experience ) >= origPower* ( 100 - decreasePercentage)/100)
228  experience--;
229 
230  return oldExperience - experience;
231  */
232 
233  int exp;
234  if ( offensive )
235  exp = experience_offensive;
236  else
237  exp = experience_defensive;
238 
239  int decreasePercentage = (oldDamage - newDamage) * repairExperienceDecrease / 100;
240 
241  int newexp = exp - (exp * decreasePercentage/100);
242  newexp = (newexp / roundToResolution) * roundToResolution;
243 
244  if ( newexp < 0 )
245  newexp = 0;
246  if ( newexp > exp )
247  newexp = exp;
248 
249  return newexp;
250 }
251 
252 
254 {
255  return experience_offensive / experienceResolution;
256 }
257 
259 {
260  return experience_defensive / experienceResolution;
261 }
262 
264 {
265  return experience_offensive;
266 }
267 
269 {
270  return experience_defensive;
271 }
272 
273 
275 {
276  experience_offensive = experience * experienceResolution;
277 }
278 
280 {
281  experience_defensive = experience * experienceResolution;
282 
283 }
284 
286 {
287  experience_offensive = experience;
288 }
289 
291 {
292  experience_defensive = experience;
293 
294 }
295 
296 
297 int Vehicle :: putResource ( int amount, int resourcetype, bool queryonly, int scope, int player )
298 {
299  // if units start using/storing resources that will not be stored in the unit itself, the replays will fail !
300 
301  if ( amount < 0 ) {
302  return -getResource( -amount, resourcetype, queryonly, scope, player );
303  } else {
304  if ( resourcetype == 0 ) // no energy storable
305  return 0;
306 
307  if ( player < 0 )
308  player = getMap()->actplayer;
309 
310  if ( player != getOwner() && !(getMap()->getPlayer(getOwner()).diplomacy.getState(player) >= PEACE) )
311  return 0;
312 
313  int spaceAvail = getStorageCapacity().resource( resourcetype ) - tank.resource(resourcetype);
314  if ( spaceAvail < 0 )
315  spaceAvail = 0;
316 
317  int tostore = min ( spaceAvail, amount);
318  if ( !queryonly ) {
319  tank.resource(resourcetype) += tostore;
320  // if ( tostore > 0 )
321  // resourceChanged();
322  }
323 
324  return tostore;
325  }
326 }
327 
328 int Vehicle :: getResource ( int amount, int resourcetype, bool queryonly, int scope, int player )
329 {
330  // if units start using/storing resources that will not be stored in the unit itself, the replays will fail !
331 
332  if ( amount < 0 ) {
333  return -putResource( -amount, resourcetype, queryonly, scope, player );
334  } else {
335  if ( resourcetype == 0 && !getGeneratorStatus() )
336  return 0;
337 
338  if ( player < 0 )
339  player = getMap()->actplayer;
340 
341  if ( player != getOwner() && (getMap()->getPlayer(getOwner()).diplomacy.getState(player) < PEACE) && !queryonly)
342  return 0;
343 
344 
345  int toget = min ( tank.resource(resourcetype), amount);
346  if ( !queryonly ) {
347  tank.resource(resourcetype) -= toget;
348  // if ( toget > 0 )
349  // resourceChanged();
350  }
351 
352  return toget;
353  }
354 }
355 
356 int Vehicle :: getAvailableResource ( int amount, int resourcetype, int scope ) const
357 {
358  // if units start using/storing resources that will not be stored in the unit itself, the replays will fail !
359 
360  if ( resourcetype == 0 && !getGeneratorStatus() )
361  return 0;
362 
363  int toget = min ( tank.resource(resourcetype), amount);
364  return toget;
365 }
366 
367 
369 {
370  Resources got;
371  for ( int r = 0; r < 3; ++r )
372  got.resource(r) = getAvailableResource( res.resource(r), r);
373 
374  return got;
375 }
376 
377 
379 {
380  return tank;
381 }
382 
383 
384 
385 void Vehicle :: setGeneratorStatus ( bool status )
386 {
388  generatoractive = status;
389  } else
390  generatoractive = 0;
391 }
392 
393 
394 
395 int Vehicle::weight( void ) const
396 {
397  return typ->weight + cargoWeight();
398 }
399 
400 int Vehicle::size ( void )
401 {
402  return typ->weight;
403 }
404 
405 void Vehicle::transform ( const VehicleType* type )
406 {
407  if ( !type )
408  return;
409 
410  typ = type;
411 
412  tank = getStorageCapacity();
413  tank.energy = 0;
414 
415  generatoractive = 0;
416 
417  for ( int m = 0; m < typ->weapons.count ; m++) {
418  ammo[m] = typ->weapons.weapon[m].count;
420  }
421 }
422 
423 void Vehicle :: postRepair ( int oldDamage, bool autoRepair )
424 {
425  experience_offensive = getRepairExperienceValue( oldDamage, damage, true, autoRepair ? 1 : experienceResolution );
426  if ( experience_offensive < 0 )
427  experience_offensive = 0;
428 
429  experience_defensive = getRepairExperienceValue( oldDamage, damage, false, autoRepair ? 1 : experienceResolution );;
430  if ( experience_defensive < 0 )
431  experience_defensive = 0;
432 }
433 
434 
436 {
437  // changing unit height to the height with the maximumem movement, to reduce the inaccuracies due to rounding
438 
439  if ( getCarrier() ) {
440  int mx = -1;
441  int newHeight = height;
442  for ( int h = 0; h < 8; h++ )
443  if ( typ->height & ( 1 << h))
444  if ( typ->movement[h] > mx ) {
445  mx = typ->movement[h];
446  newHeight = 1 << h;
447  }
448 
449  if ( newHeight != height ) {
450  height = newHeight;
451  }
452  }
453  resetMovement();
454 
455 }
456 
457 
458 void Vehicle :: endRound ( void )
459 {
462  int endiff = getStorageCapacity().energy - tank.energy;
463  if ( tank.fuel < endiff * generatortruckefficiency )
464  endiff = tank.fuel / generatortruckefficiency;
465 
466  tank.energy += endiff;
467  tank.fuel -= endiff * generatortruckefficiency ;
468  }
469 }
470 
472 {
475 }
476 
477 
479 {
481 
482  if ( typ->autorepairrate > 0 )
483  if ( damage )
485 
487 
488  if ( !gamemap->getField(getPosition())->unitHere(this)) {
489  int mx = -1;
490  for ( int h = 0; h < 8; h++ )
491  if ( typ->height & ( 1 << h))
492  if ( typ->movement[h] > mx ) {
493  mx = typ->movement[h];
494  height = 1 << h;
495  }
496  }
497 
498  for ( int w = 0; w < typ->weapons.count; w++ )
499  if ( typ->weapons.weapon[w].gettype() & cwlaserb ) {
500  int cnt = 0;
501  while ( cnt < typ->weapons.weapon[w].laserRechargeRate && ammo[w] < typ->weapons.weapon[w].count ) {
502  for ( int r = 0; r < 3; r++ )
503  if ( typ->weapons.weapon[w].laserRechargeCost.resource(r) < 0 )
504  fatalError (" negative Laser recharge cost !");
507  ammo[w] += 1;
508  }
509  ++cnt;
510  }
511  }
512 
513  resetMovement();
514  attacked = false;
515 
516 }
517 
519 {
521  setMovement ( move, 0 );
522 }
523 
524 
525 
526 
527 void Vehicle :: setMovement ( int newmove, double cargoDivisor )
528 {
529 
530  if ( cargoDivisor < 0 )
531  cargoDivisor = typ->cargoMovementDivisor;
532 
533  if ( newmove < 0 )
534  newmove = 0;
535 
536  if ( cargoDivisor > 0 && typ)
537  if ( typ->movement[ getFirstBit ( height ) ] ) {
538  double diff = _movement - newmove;
539  double perc = diff / typ->movement[ getFirstBit ( height ) ] ;
540  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
541  if ( *i ) {
542  double lperc = perc;
543  if ( cargoDivisor && cargoNestingDepth() == 0 )
544  lperc /= cargoDivisor;
545 
546  (*i)->decreaseMovement ( max( 1, int( ceil( lperc * double( (*i)->typ->movement[ getFirstBit ( (*i)->height)] )))));
547  }
548  }
549  _movement = newmove;
550 }
551 
552 bool Vehicle::hasMoved ( void ) const
553 {
554  return _movement != typ->movement[ getFirstBit ( height )];
555 }
556 
557 
558 int Vehicle :: getMovement ( bool checkFuel, bool checkRF ) const
559 {
560  if ( checkRF && !reactionfire.canMove() )
561  return 0;
562 
563  if ( typ->fuelConsumption && checkFuel ) {
564  if ( tank.fuel * minmalq / typ->fuelConsumption < _movement )
565  return tank.fuel * minmalq / typ->fuelConsumption;
566  else
567  return _movement;
568  } else
569  return _movement;
570 }
571 
572 void Vehicle :: decreaseMovement ( int amount )
573 {
574  int newMovement = _movement - amount;
575  if ( newMovement < 0 )
576  newMovement = 0;
577  if ( newMovement > typ->movement[getFirstBit(height)] )
578  newMovement = typ->movement[getFirstBit(height)];
579  setMovement ( newMovement );
580 }
581 
582 bool Vehicle::movementLeft() const
583 {
584  int mv = getMovement();
585  if ( mv <= 0 )
586  return false;
587  if ( mv >= 10 )
588  return true;
589 
591  WindMovement wm ( this );
592  for ( int i = 0; i < 6; i++ )
593  if ( 10 - wm.getDist( i ) <= mv )
594  return true;
595  }
596  return false;
597 }
598 
599 bool Vehicle :: canMove ( void ) const
600 {
601  // if ( attacked && !(typ->functions & cf_moveafterattack))
602  // return false;
603 
604  if ( movementLeft() && reactionfire.canMove() ) {
605  MapField* fld = gamemap->getField ( getPosition() );
606  if ( fld->unitHere ( this ) ) {
608  return true;
609  } else {
610  ContainerBase* cnt = fld->getContainer();
611  if ( cnt )
612  for ( Cargo::const_iterator i = cnt->getCargo().begin(); i != cnt->getCargo().end(); ++i )
613  if ( *i == this )
614  if ( cnt->vehicleUnloadable( typ ) > 0 || cnt->vehicleDocking( this, true ) > 0 )
615  return true;
616  }
617  }
618  return false;
619 }
620 
621 bool Vehicle::spawnMoveObjects( const MapCoordinate& start, const MapCoordinate& dest, const Context& context )
622 {
623  if ( start == dest )
624  return false;
625 
626  bool result = false;
627 
628  if ( typ->objectLayedByMovement.size() && (height == chfahrend || height == chschwimmend)) {
629  int dir = getdirection( start, dest );
630 
631  MapField* startField = gamemap->getField(start);
632  MapField* destField = gamemap->getField(dest);
633 
634  for ( int i = 0; i < typ->objectLayedByMovement.size(); i++ )
635  for ( int id = typ->objectLayedByMovement[i].from; id <= typ->objectLayedByMovement[i].to; ++id ) {
636  ObjectType* object = objectTypeRepository.getObject_byID( id );
637  if ( object ) {
638  (new SpawnObject( getMap(), start, id, 1 << dir ))->execute( context );
639  if ( startField->checkForObject ( object ))
640  result = true;
641  }
642  }
643 
644  dir = (dir + sidenum/2) % sidenum;
645 
646  for ( int i = 0; i < typ->objectLayedByMovement.size(); i++ )
647  for ( int id = typ->objectLayedByMovement[i].from; id <= typ->objectLayedByMovement[i].to; ++id ) {
648  ObjectType* object = objectTypeRepository.getObject_byID( id );
649  if ( object ) {
650  (new SpawnObject( getMap(), dest, id, 1 << dir ))->execute( context );
651  if ( destField->checkForObject ( object ))
652  result = true;
653  }
654  }
655  }
656 
657  return result;
658 }
659 
660 
661 Vehicle::ReactionFire::ReactionFire ( Vehicle* _unit ) : unit ( _unit )
662 {
663  weaponShots.resize(unit->typ->weapons.count);
664  resetShotCount();
665 }
666 
667 
669 {
670  // the size could have changed because a unit was saved to disk with 1 weapon system, the type modified to 2 and the unit loaded again
671  if ( weaponShots.size() < unit->typ->weapons.count ) {
672  size_t oldsize = weaponShots.size();
673  weaponShots.resize( unit->typ->weapons.count );
674  for ( size_t i = oldsize; i < unit->typ->weapons.count; ++i )
675  weaponShots[i] = unit->typ->weapons.weapon[i].reactionFireShots;
676  }
677 }
678 
679 
680 
681 void Vehicle::ReactionFire::resetShotCount()
682 {
683  assertOrThrow( unit->typ->weapons.count <= weaponShots.size() );
684  for ( int i = 0; i < unit->typ->weapons.count; ++i )
685  weaponShots[i] = unit->typ->weapons.weapon[i].reactionFireShots;
686 }
687 
688 
690 {
691  if ( unit->typ->hasFunction( ContainerBaseType::NoReactionfire ) )
692  return -216;
693 
694  #ifdef karteneditor
695  status = ready;
696  #else
697  if ( status == off ) {
698  int weaponCount = 0;
699  int shootableWeaponCount = 0;
700  for ( int w = 0; w < unit->typ->weapons.count; w++ )
701  if ( unit->typ->weapons.weapon[w].shootable() ) {
702  weaponCount++;
703  if ( unit->typ->weapons.weapon[w].sourceheight & unit->height )
704  shootableWeaponCount++;
705  }
706 
707  if ( weaponCount == 0 )
708  return -214;
709 
710  if ( shootableWeaponCount == 0 )
711  return -213;
712 
713  if ( unit->typ->wait ) {
714  // if ( unit->hasMoved())
715  // status = init1a;
716  // else
717  status = init2;
718  } else {
719  status = init2;
720  }
721  }
722  #endif
723  return 0;
724 }
725 
727 {
728  if ( status != off ) {
729  if ( status != init1a && status != init2 && !unit->typ->hasFunction(ContainerBaseType::MoveWithReactionFire) ) {
730  unit->setMovement ( 0, 0 );
731  }
732  status = off;
733  }
734 }
735 
737 {
738  resetShotCount();
739 }
740 
741 
743 {
744  if ( status != off ) {
745  if ( status == init1a )
746  status = init1b;
747  else
748  if ( status == init2 || status == init1b )
749  status = ready;
750  }
751  nonattackableUnits.clear();
752 }
753 
755 {
756  if ( unit->typ->hasFunction( ContainerBaseType::MoveWithReactionFire ))
757  return true;
758  if ( status == off )
759  return true;
760  return false;
761 }
762 
764 {
765  if ( !unit->getCarrier() )
766  if ( unit->getMap()->getPlayer(unit).diplomacy.isHostile( target->getOwner() ))
767  if ( getStatus() >= ready )
768  if ( find ( nonattackableUnits.begin(), nonattackableUnits.end(), target->networkid) == nonattackableUnits.end() )
769  // if ( enemiesAttackable & ( 1 << target->getOwner() ))
770  return true;
771 
772  return false;
773 }
774 
775 
776 
778 {
779  if ( !reactionfire.canMove() )
780  return NULL;
781 
782  if ( height == 0 )
783  height = this->height;
784 
785  for ( int i = 0; i < typ->heightChangeMethodNum; i++ )
786  if ( typ->heightChangeMethod[i].startHeight & height )
787  if ( ( dir > 0 && typ->heightChangeMethod[i].heightDelta > 0) || ( dir < 0 && typ->heightChangeMethod[i].heightDelta < 0))
788  if ( (1 << (getFirstBit(height) + typ->heightChangeMethod[i].heightDelta)) & typ->height )
789  return &typ->heightChangeMethod[i];
790 
791  return NULL;
792 }
793 
794 
795 
797 {
798  if ( typ->weapons.count > 0)
799  for ( int b = 0; b < typ->weapons.count ; b++)
800  if ( typ->weapons.weapon[b].shootable() )
801  if ( typ->weapons.weapon[b].offensive() )
802  if ( ammo[b] )
803  return 1;
804  return 0;
805 }
806 
807 
808 void Vehicle :: setnewposition ( int x , int y )
809 {
810  xpos = x;
811  ypos = y;
812  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
813  if ( *i )
814  (*i)->setnewposition ( x , y );
815 }
816 
818 {
819  setnewposition ( mc.x, mc.y );
820 }
821 
822 void Vehicle :: setnewposition ( const MapCoordinate& mc, const Context& context )
823 {
824  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
825  if ( *i )
826  (*i)->setnewposition ( mc, context );
827  (new UnitFieldRegistration( this, MapCoordinate3D(mc,0), UnitFieldRegistration::Position ))->execute( context );
828 }
829 
831 {
832  if ( getCarrier() )
834  else {
835  if ( getPosition().valid() ) {
836  MapField* fld = getMap()->getField(getPosition());
837  if ( fld->vehicle == this )
838  fld->vehicle = NULL;
839  }
840  }
841 }
842 
843 void Vehicle::convert ( int col, bool recursive )
844 {
845  if ( col > 8)
846  fatalError("convertvehicle: \n invalid target player ");
847 
848  registerForNewOwner( col );
849 
850  if ( recursive )
851  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
852  if ( *i )
853  (*i)->convert( col );
854 }
855 
856 
858 {
859  int oldcol = getOwner();
860 
861  Player::VehicleList::iterator i = find ( gamemap->player[oldcol].vehicleList.begin(), gamemap->player[oldcol].vehicleList.end(), this );
862  if ( i != gamemap->player[oldcol].vehicleList.end())
863  gamemap->player[oldcol].vehicleList.erase ( i );
864 
865  gamemap->player[player].vehicleList.push_back( this );
866 
867  color = player*8;
868 
869  // emit signal
870  conquered();
871  anyContainerConquered(this);
872 }
873 
874 
875 bool Vehicle :: vehicleconstructable ( const VehicleType* tnk, int x, int y )
876 {
878  !tnk->techDependency.available ( gamemap->player[getOwner()].research))
879  return 0;
880 
882  return 0;
883 
884  if( (tnk->height & height ) || (( tnk->height & (chfahrend | chschwimmend)) && (height & (chfahrend | chschwimmend)))) {
885  int hgt = height;
886  if ( !(tnk->height & height))
887  hgt = 1 << getFirstBit(tnk->height);
888  if ( terrainaccessible2( gamemap->getField(x,y), tnk->terrainaccess, hgt ) > 0 )
890  int dist = beeline (x, y, xpos, ypos);
891  if ( dist <= maxmalq * typ->unitConstructionMaxDistance && dist >= maxmalq * typ->unitConstructionMinDistance )
892  return 1;
893  }
894 
895  }
896  return 0;
897 }
898 
899 
901 {
902  Resources r;
904  r.fuel = tnk->productionCost.energy;
905  return r;
906 }
907 
908 /*
909 bool Vehicle :: buildingconstructable ( const BuildingType* building, bool checkResources )
910 {
911  if ( !building )
912  return 0;
913 
914 
915  if ( gamemap->getgameparameter(cgp_forbid_building_construction) )
916  return 0;
917 
918  if ( !building->techDependency.available ( gamemap->player[getOwner()].research))
919  return 0;
920 
921 
922  int mf = gamemap->getgameparameter ( cgp_building_material_factor );
923  int ff = gamemap->getgameparameter ( cgp_building_fuel_factor );
924 
925  if ( !mf )
926  mf = 100;
927  if ( !ff )
928  ff = 100;
929 
930  int hd = getheightdelta ( getFirstBit ( height ), getFirstBit ( building->height ));
931 
932  if ( hd != 0 ) // && !(hd ==-1 && (height == chschwimmend || height == chfahrend)) ??? what was that ??
933  return 0;
934 
935 
936  if ( (building->productionCost.material * mf / 100 <= tank.material && building->productionCost.fuel * ff / 100 <= tank.fuel) || !checkResources ) {
937  if ( typ->hasFunction( ContainerBaseType::ConstructBuildings) )
938  for ( int i = 0; i < typ->buildingsBuildable.size(); i++ )
939  if ( typ->buildingsBuildable[i].from <= building->id &&
940  typ->buildingsBuildable[i].to >= building->id )
941  return true;
942  }
943 
944  return false;
945 }
946 
947 */
948 
949 int Vehicle :: searchstackforfreeweight ( Vehicle* searchedInnerVehicle )
950 {
951  if ( searchedInnerVehicle == this ) {
952  return typ->maxLoadableWeight - cargoWeight();
953  } else {
954  int currentFreeWeight = typ->maxLoadableWeight - cargoWeight();
955  int innerFreeWeight = -1;
956  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
957  if ( *i ) {
958  int w = (*i)->searchstackforfreeweight ( searchedInnerVehicle );
959  if ( w >= 0 )
960  innerFreeWeight = w;
961  }
962 
963  if ( innerFreeWeight != -1 )
964  return min ( currentFreeWeight, innerFreeWeight );
965  else
966  return -1;
967  }
968 }
969 
970 
972 {
973  MapField* fld = gamemap->getField ( xpos, ypos );
974  if ( fld->vehicle )
975  return fld->vehicle->searchstackforfreeweight ( this );
976  else
977  if ( fld->building ) {
978  for ( Cargo::const_iterator i = fld->building->getCargo().begin(); i != fld->building->getCargo().end(); ++i )
979  if ( *i ) {
980  int w3 = (*i)->searchstackforfreeweight ( this );
981  if ( w3 >= 0 )
982  return w3;
983  }
984  }
985 
986  return -2;
987 }
988 
989 
991 {
992  if ( viewOnMap )
993  fatalError ("void Vehicle :: addview - the vehicle is already viewing the map");
994 
995  viewOnMap = true;
997  bes.init( this, +1 );
998  bes.startsearch();
999 }
1000 
1002 {
1003  viewOnMap = false;
1004 }
1005 
1007 {
1008  if ( !viewOnMap )
1009  fatalError ("void Vehicle :: removeview - the vehicle is not viewing the map");
1010 
1011  tcomputevehicleview bes ( gamemap );
1012  bes.init( this, -1 );
1013  bes.startsearch();
1014 
1015  viewOnMap = false;
1016 }
1017 
1018 
1019 void Vehicle :: postAttack( bool reactionFire, const Context& context )
1020 {
1021  if ( !reactionFire ) {
1023  int decrease = maxMovement() * attackmovecost / 100;
1024  if ( decrease )
1025  (new ChangeUnitMovement( this, decrease, true ))->execute( context );
1026  } else {
1027  GameAction* a = new ChangeUnitMovement( this, 0 );
1028  a->execute( context );
1029  }
1030 
1032  a->execute( context );
1033  }
1034 }
1035 
1036 void Vehicle :: postAttack( bool reactionFire )
1037 {
1038  if ( !reactionFire )
1039  attacked = true;
1040 
1043  else
1045  setMovement ( 0 );
1046 }
1047 
1048 
1050 {
1051  attacked = true;
1052  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
1053  if ( *i )
1054  (*i)->setAttacked();
1055 }
1056 
1057 void Vehicle::setAttacked( bool recursive, const Context& context )
1058 {
1060  a->execute( context );
1061 
1062  if ( recursive )
1063  for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
1064  if ( *i )
1065  (*i)->setAttacked( true, context );
1066 }
1067 
1068 
1069 int Vehicle::maxMovement ( void ) const
1070 {
1071  return typ->movement[getFirstBit(height)];
1072 }
1073 
1074 
1075 void Vehicle :: fillMagically( bool ammunition, bool resources )
1076 {
1077  if ( resources )
1078  tank = getStorageCapacity();
1079 
1080  if ( ammunition )
1081  for ( int m = 0; m < typ->weapons.count ; m++) {
1082  ammo[m] = typ->weapons.weapon[m].count;
1084  }
1085 }
1086 
1087 
1088 
1089 
1090 #define cem_experience 0x1
1091 #define cem_damage 0x2
1092 #define cem_fuel 0x4
1093 #define cem_ammunition 0x8
1094 #define cem_weapstrength 0x10
1095 #define cem_loading 0x20
1096 #define cem_attacked 0x40
1097 #define cem_height 0x80
1098 #define cem_movement 0x100
1099 #define cem_direction 0x200
1100 #define cem_material 0x400
1101 #define cem_energy 0x800
1102 #define cem_class 0x1000
1103 #define cem_networkid 0x2000
1104 #define cem_name 0x4000
1105 #define cem_armor 0x8000
1106 #define cem_reactionfire 0x10000
1107 #define cem_reactionfire2 0x20000
1108 #define cem_poweron 0x40000
1109 #define cem_weapstrength2 0x80000
1110 #define cem_ammunition2 0x100000
1111 #define cem_energyUsed 0x200000
1112 #define cem_position 0x400000
1113 #define cem_aiparam 0x800000
1114 #define cem_version 0x1000000
1115 
1116 
1117 
1118 
1119 const int vehicleVersion = 11;
1120 
1121 void Vehicle::write ( tnstream& stream, bool includeLoadedUnits ) const
1122 {
1123  stream.writeWord ( 0 );
1124  stream.writeInt( min( vehicleVersion, UNITVERSIONLIMIT ) );
1125  stream.writeInt( typ->id );
1126 
1127  stream.writeUint8 ( color );
1128 
1129  int bm = cem_version;
1130 
1131  if ( damage )
1132  bm |= cem_damage;
1133 
1134  bm |= cem_energy;
1135  bm |= cem_fuel;
1136  bm |= cem_material;
1137 
1138  if ( typ->weapons.count )
1139  for (int m = 0; m < typ->weapons.count ; m++) {
1140  if ( ammo[m] < typ->weapons.weapon[m].count )
1141  bm |= cem_ammunition2;
1142  if ( weapstrength[m] != typ->weapons.weapon[m].maxstrength )
1143  bm |= cem_weapstrength2;
1144  }
1145 
1146  if ( includeLoadedUnits )
1147  for ( Cargo::const_iterator i = cargo.begin(); i != cargo.end(); ++i )
1148  if ( *i )
1149  bm |= cem_loading;
1150 
1151  if ( attacked )
1152  bm |= cem_attacked;
1153  if ( height != chfahrend )
1154  bm |= cem_height;
1155 
1156 // if ( _movement < typ->movement[getFirstBit(height)] )
1157  bm |= cem_movement;
1158 
1159  if ( direction )
1160  bm |= cem_direction;
1161 
1162 
1163  if ( networkid )
1164  bm |= cem_networkid;
1165 
1166  if ( !name.empty() )
1167  bm |= cem_name;
1168 
1169  if ( reactionfire.status )
1170  bm |= cem_reactionfire;
1171 
1172  if ( generatoractive )
1173  bm |= cem_poweron;
1174 
1175  if ( xpos != 0 || ypos != 0 )
1176  bm |= cem_position;
1177 
1178  for ( int i = 0; i < 8; i++ )
1179  if ( aiparam[i] )
1180  bm |= cem_aiparam;
1181 
1182 
1183 
1184  stream.writeInt( bm );
1185 
1186  stream.writeInt( min( vehicleVersion, UNITVERSIONLIMIT ) );
1187 
1188  if ( bm & cem_damage )
1189  stream.writeUint8 ( damage );
1190 
1191  if ( bm & cem_fuel )
1192  stream.writeInt ( tank.fuel );
1193 
1194  if ( bm & cem_ammunition2 )
1195  for ( int j= 0; j < 16; j++ )
1196  stream.writeInt ( ammo[j] );
1197 
1198  if ( bm & cem_weapstrength2 )
1199  for ( int j = 0; j < 16; j++ )
1200  stream.writeInt ( weapstrength[j] );
1201 
1202  if ( bm & cem_loading ) {
1203  int c=0;
1204  for ( Cargo::const_iterator i = cargo.begin(); i != cargo.end(); ++i )
1205  if ( *i )
1206  ++c;
1207 
1208  if ( UNITVERSIONLIMIT > 3 )
1209  stream.writeInt ( c );
1210  else
1211  stream.writeUint8 ( c );
1212 
1213  for ( Cargo::const_iterator i = cargo.begin(); i != cargo.end(); ++i )
1214  if ( *i )
1215  (*i)->write ( stream );
1216  }
1217 
1218  if ( bm & cem_height )
1219  stream.writeUint8 ( height );
1220 
1221  if ( bm & cem_movement )
1222  stream.writeInt ( _movement );
1223 
1224  if ( bm & cem_direction )
1225  stream.writeUint8 ( direction );
1226 
1227  if ( bm & cem_material )
1228  stream.writeInt ( tank.material );
1229 
1230  if ( bm & cem_energy )
1231  stream.writeInt ( tank.energy );
1232 
1233  if ( bm & cem_networkid )
1234  stream.writeInt ( networkid );
1235 
1236  if ( bm & cem_attacked )
1237  stream.writeUint8 ( attacked );
1238 
1239  if ( bm & cem_name )
1240  stream.writeString ( name );
1241 
1242  if ( bm & cem_reactionfire )
1243  stream.writeUint8 ( reactionfire.status );
1244 
1245  if ( bm & cem_poweron )
1246  stream.writeInt ( generatoractive );
1247 
1248  if ( bm & cem_position ) {
1249  stream.writeInt ( xpos );
1250  stream.writeInt ( ypos );
1251  }
1252 
1253  if ( bm & cem_aiparam ) {
1254  stream.writeInt( 0x23451234 );
1255  for ( int i = 0; i < 8; i++ )
1256  stream.writeInt ( aiparam[i] != NULL );
1257 
1258  for ( int i = 0; i < 8; i++ )
1259  if ( aiparam[i] )
1260  aiparam[i]->write ( stream );
1261 
1262  stream.writeInt( 0x23451234 );
1263  }
1264 
1267 
1268  if ( UNITVERSIONLIMIT >= 5 ) {
1269  stream.writeInt( internalUnitProduction.size() );
1270  for ( int i = 0; i < internalUnitProduction.size(); ++i )
1271  stream.writeInt( internalUnitProduction[i]->id );
1272  }
1273 
1274  if ( UNITVERSIONLIMIT >= 6 ) {
1275  stream.writeInt( maxresearchpoints );
1276  stream.writeInt( researchpoints );
1277  plus.write( stream );
1278  maxplus.write( stream );
1279  // actstorage.write( stream );
1280  bi_resourceplus.write( stream );
1281  }
1282 
1283  stream.writeInt( view );
1284 
1285  stream.writeString( privateName );
1286 
1287  stream.writeInt( experience_defensive );
1288  stream.writeInt( experience_offensive );
1289 }
1290 
1291 void Vehicle::read ( tnstream& stream )
1292 {
1293  int _id = stream.readWord ();
1294  if ( _id == 0 ) {
1295  stream.readInt(); // version
1296  _id = stream.readInt();
1297  }
1298 
1299  stream.readUint8 (); // color
1300  if ( _id != typ->id )
1301  fatalError ( "Vehicle::read - trying to read a unit of different type" );
1302 
1303  readData ( stream );
1304 }
1305 
1306 void Vehicle::readData ( tnstream& stream )
1307 {
1308 
1309  int bm = stream.readInt();
1310 
1311  int version = 0;
1312  if ( bm & cem_version )
1313  version = stream.readInt();
1314 
1315  if ( bm & cem_experience ) {
1316  experience_offensive = stream.readUint8();
1317 
1318  if ( version < 10 )
1319  experience_offensive *= experienceResolution;
1320 
1321  } else
1322  experience_offensive = 0;
1323 
1324  if ( bm & cem_damage )
1325  damage = stream.readUint8();
1326  else
1327  damage = 0;
1328 
1329  if ( bm & cem_fuel ) {
1330  tank.fuel = stream.readInt();
1331  if ( tank.fuel > getStorageCapacity().fuel )
1332  tank.fuel = getStorageCapacity().fuel;
1333  } else
1334  tank.fuel = getStorageCapacity().fuel;
1335 
1336  if ( bm & cem_ammunition ) {
1337  for ( int i = 0; i < 8; i++ )
1338  ammo[i] = stream.readWord();
1339  } else
1340  if ( bm & cem_ammunition2 ) {
1341  for ( int i = 0; i < 16; i++ ) {
1342  ammo[i] = stream.readInt();
1343  if ( ammo[i] > typ->weapons.weapon[i].count )
1344  ammo[i] = typ->weapons.weapon[i].count;
1345  if ( ammo[i] < 0 )
1346  ammo[i] = 0;
1347  }
1348 
1349  } else
1350  for (int i=0; i < typ->weapons.count ;i++ )
1351  ammo[i] = typ->weapons.weapon[i].count;
1352 
1353 
1354  if ( bm & cem_weapstrength ) {
1355  for ( int i = 0; i < 8; i++ )
1356  weapstrength[i] = stream.readWord();
1357 
1358  } else
1359  if ( bm & cem_weapstrength2 ) {
1360  for ( int i = 0; i < 16; i++ )
1361  weapstrength[i] = stream.readInt();
1362  } else
1363  for (int i=0; i < typ->weapons.count ;i++ )
1365 
1366  if ( bm & cem_loading ) {
1367  int c;
1368  if ( version <= 3 )
1369  c = stream.readUint8();
1370  else
1371  c = stream.readInt();
1372 
1373  if ( c ) {
1374  for (int k = 0; k < c; k++) {
1375  Vehicle* v = Vehicle::newFromStream ( gamemap, stream );
1376  addToCargo(v);
1378  /* there are two reasons that a unit with enabled RF is put into a transport, although the unit cannot move with RF:
1379  - the unitType was changed after the unit was moved into the transport
1380  - RF was enable with the mapeditor
1381  In order for the user to have any change to get the unit out again, we disable RF here */
1382  v->reactionfire.disable();
1383  }
1384  }
1385  }
1386 
1387  if ( bm & cem_height )
1388  height = stream.readUint8();
1389  else
1390  height = chfahrend;
1391 
1392  if ( ! (height & typ->height) )
1393  height = 1 << getFirstBit ( typ->height );
1394 
1395  if ( bm & cem_movement ) {
1396  int m;
1397  if ( version <= 6 )
1398  m = stream.readUint8();
1399  else
1400  m = stream.readInt();
1401 
1402  setMovement ( min( m,typ->movement [ getFirstBit ( height ) ]), 0 );
1403  } else
1404  setMovement ( typ->movement [ getFirstBit ( height ) ], 0 );
1405 
1406  if ( bm & cem_direction )
1407  direction = stream.readUint8();
1408  else
1409  direction = 0;
1410 
1411  if ( bm & cem_material ){
1412  tank.material = min( stream.readInt(), getStorageCapacity().material);
1413  } else
1415 
1416  if ( bm & cem_energy ) {
1417  tank.energy = min ( stream.readInt(), getStorageCapacity().energy);
1418  if ( tank.energy < 0 )
1419  tank.energy = 0;
1420  } else
1421  tank.energy = getStorageCapacity().energy;
1422 
1423  if ( bm & cem_class )
1424  stream.readUint8(); // was: class
1425 
1426  if ( bm & cem_armor )
1427  stream.readWord(); // was: armor
1428 
1429  if ( bm & cem_networkid )
1430  networkid = stream.readInt();
1431  else
1432  networkid = 0;
1433 
1434  if ( bm & cem_attacked )
1435  attacked = stream.readUint8();
1436  else
1437  attacked = false;
1438 
1439  if ( bm & cem_name )
1440  name = stream.readString ( );
1441 
1442  int reactionfirestatus = 0;
1443  if ( bm & cem_reactionfire )
1444  reactionfirestatus = stream.readUint8();
1445 
1446  int reactionfireenemiesAttackable = 0;
1447  if ( bm & cem_reactionfire2 )
1448  reactionfireenemiesAttackable = stream.readUint8();
1449 
1450  if ( reactionfirestatus >= 8 && reactionfireenemiesAttackable <= 4 ) { // for transition from the old reactionfire system ( < ASC1.2.0 ) to the new one ( >= ASC1.2.0 )
1451  reactionfire.status = ReactionFire::Status ( reactionfireenemiesAttackable );
1452  setMovement ( typ->movement [ getFirstBit ( height ) ], 0 );
1453  } else
1454  reactionfire.status = ReactionFire::Status ( reactionfirestatus );
1455 
1456 
1459 
1460 
1461  if ( bm & cem_poweron )
1462  generatoractive = stream.readInt();
1463  else
1464  generatoractive = 0;
1465 
1466  if ( bm & cem_energyUsed )
1467  stream.readInt ();
1468 
1469  if ( bm & cem_position ) {
1470  int x = stream.readInt ( );
1471  int y = stream.readInt ( );
1472  setnewposition ( x, y );
1473  } else
1474  setnewposition ( 0, 0 );
1475 
1476  if ( bm & cem_aiparam ) {
1477  int magic = stream.readInt();
1478  if ( magic != 0x23451234 )
1479  throw ASCmsgException ( "Vehicle::read() - inconsistent data stream" );
1480  for ( int i = 0; i < 8; i++ ) {
1481  if ( aiparam[i] ) {
1482  delete aiparam[i];
1483  aiparam[i] = NULL;
1484  }
1485  if ( stream.readInt() )
1486  aiparam[i] = new AiParameter ( this );
1487  }
1488 
1489  for ( int i = 0; i < 8; i++ )
1490  if ( aiparam[i] )
1491  aiparam[i]->read ( stream );
1492 
1493  magic = stream.readInt();
1494  if ( magic != 0x23451234 )
1495  throw ASCmsgException ( "Vehicle::read() - inconsistent data stream" );
1496  }
1497 
1498  for ( int m = 0; m < typ->weapons.count ; m++)
1499  if ( typ->weapons.weapon[m].getScalarWeaponType() >= 0 )
1501  else
1502  weapstrength[m] = 0;
1503 
1504  if ( version >= 1 ) {
1507  }
1508  if ( version >= 2 )
1510 
1511  internalUnitProduction.clear();
1512  if ( version >= 5 ) {
1513  int pcount = stream.readInt();
1514  for ( int i = 0; i< pcount; ++i ) {
1515  int id = stream.readInt();
1516  internalUnitProduction.push_back ( gamemap->getvehicletype_byid ( id ) );
1517  if ( !internalUnitProduction[i] )
1518  throw InvalidID ( "unit", id );
1519  }
1520  }
1521 
1522  if ( version >= 6 ) {
1523  maxresearchpoints = stream.readInt();
1524  researchpoints = stream.readInt();
1525  plus.read( stream );
1526  maxplus.read( stream );
1527  bi_resourceplus.read( stream );
1528  }
1529 
1530  if ( version >= 7 )
1531  view = stream.readInt();
1532  else
1533  view = typ->view;
1534 
1535  if ( version >= 8 )
1536  privateName = stream.readString();
1537  else
1538  privateName = "";
1539 
1540 
1541  if ( version >= 9 ) {
1542  experience_defensive = stream.readInt();
1543  if ( version == 9 )
1544  experience_defensive *= experienceResolution;
1545  } else
1546  experience_defensive = experience_offensive;
1547 
1548  if ( version >= 11 )
1549  experience_offensive = stream.readInt();
1550 }
1551 
1553 {
1554  return MapCoordinate3D ( xpos, ypos, height );
1555 }
1556 
1558 {
1559  if ( gamemap->getField(xpos,ypos)->unitHere(this) )
1560  return MapCoordinate3D ( xpos, ypos, height );
1561  else {
1562  MapCoordinate3D pos;
1563  pos.setnum ( xpos, ypos, -1 );
1564  return pos;
1565  }
1566 }
1567 
1568 
1570 {
1571  if ( name.empty() )
1572  return typ->getName();
1573  else
1574  return name;
1575 }
1576 
1577 
1578 int Vehicle::getAmmo( int type, int num ) const
1579 {
1580  int got = 0;
1581  int weap = 0;
1582  while ( weap < typ->weapons.count && got < num ) {
1583  if ( typ->weapons.weapon[weap].getScalarWeaponType() == type ) {
1584  int toget = min( num - got, ammo[weap]);
1585  got += toget;
1586  }
1587  ++weap;
1588  }
1589 
1590  return got;
1591 }
1592 
1593 int Vehicle::getAmmo( int type, int num, bool queryOnly )
1594 {
1595  if ( num < 0 )
1596  return -putAmmo( type, -num, queryOnly );
1597 
1598  int got = 0;
1599 
1600 
1601  // pass 1: only weapons with refuel
1602  int weap = 0;
1603  while ( weap < typ->weapons.count && got < num ) {
1604  if ( typ->weapons.weapon[weap].getScalarWeaponType() == type && typ->weapons.weapon[weap].canRefuel() ) {
1605  int toget = min( num - got, ammo[weap]);
1606  if ( !queryOnly )
1607  ammo[weap] -= toget;
1608  got += toget;
1609  }
1610  ++weap;
1611  }
1612 
1613 
1614  // pass 2: all the others
1615  weap = 0;
1616  while ( weap < typ->weapons.count && got < num ) {
1617  if ( typ->weapons.weapon[weap].getScalarWeaponType() == type && !typ->weapons.weapon[weap].canRefuel()) {
1618  int toget = min( num - got, ammo[weap]);
1619  if ( !queryOnly )
1620  ammo[weap] -= toget;
1621  got += toget;
1622  }
1623  ++weap;
1624  }
1625  // if ( got && !queryOnly )
1626  // ammoChanged();
1627  return got;
1628 }
1629 
1630 int Vehicle::putAmmo( int type, int num, bool queryOnly )
1631 {
1632  if ( num < 0 )
1633  return -getAmmo( type, -num, queryOnly );
1634 
1635  int put = 0;
1636  int weap = 0;
1637  while ( weap < typ->weapons.count && put < num ) {
1638  if ( typ->weapons.weapon[weap].getScalarWeaponType() == type && typ->weapons.weapon[weap].shootable() ) {
1639  int toput = min( num - put, typ->weapons.weapon[weap].count - ammo[weap]);
1640  if ( !queryOnly )
1641  ammo[weap] += toput;
1642  put += toput;
1643  }
1644  ++weap;
1645  }
1646 
1647  weap = 0;
1648  while ( weap < typ->weapons.count && put < num ) {
1649  if ( typ->weapons.weapon[weap].getScalarWeaponType() == type ) {
1650  int toput = min( num - put, typ->weapons.weapon[weap].count - ammo[weap]);
1651  if ( !queryOnly )
1652  ammo[weap] += toput;
1653  put += toput;
1654  }
1655  ++weap;
1656  }
1657 
1658  // if ( put && !queryOnly )
1659  // ammoChanged();
1660  return put;
1661 }
1662 
1663 
1664 int Vehicle::maxAmmo( int type ) const
1665 {
1666  int ammo = 0;
1667  for ( int i = 0; i < typ->weapons.count; ++i )
1668  if ( typ->weapons.weapon[i].getScalarWeaponType() == type )
1669  ammo += typ->weapons.weapon[i].count;
1670  return ammo;
1671 
1672 }
1673 
1674 
1676 {
1677  return typ->armor;
1678 }
1679 
1680 
1681 void Vehicle::paint ( Surface& s, SPoint pos, int shadowDist ) const
1682 {
1683  #ifdef sgmain
1684  bool secondUnit = gamemap->getField ( getPosition() )->secondvehicle == this;
1685  bool shaded = (!canMove() && !secondUnit) && maxMovement() && ( color == gamemap->actplayer*8) && (attacked || !typ->weapons.count || CGameOptions::Instance()->units_gray_after_move );
1686  #else
1687  bool shaded = 0;
1688  #endif
1689 
1690  int dir = direction;
1692  dir = 0;
1693 
1694  paintField( typ->getImage(), s, pos, dir, shaded, shadowDist );
1695 }
1696 
1697 void Vehicle::paint ( Surface& s, SPoint pos, bool shaded, int shadowDist ) const
1698 {
1699  int dir = direction;
1701  dir = 0;
1702 
1703  paintField( typ->getImage(), s, pos, dir, shaded, shadowDist );
1704 }
1705 
1707 {
1709  paint( s, SPoint(0,0), false, 0 );
1710  return s;
1711 }
1712 
1713 
1714 vector<MapCoordinate> Vehicle::getCoveredFields()
1715 {
1716  vector<MapCoordinate> fields;
1717  fields.push_back( getPosition() );
1718  return fields;
1719 }
1720 
1721 
1723 {
1724  return sizeof(*this);
1725 }
1726 
1727 
1728 Vehicle* Vehicle::newFromStream ( GameMap* gamemap, tnstream& stream, int forceNetworkID )
1729 {
1730  int id = stream.readWord ();
1731  if ( id == 0 ) {
1732  stream.readInt(); // version
1733  id = stream.readInt();
1734  }
1735 
1736  VehicleType* fzt = gamemap->getvehicletype_byid ( id );
1737  if ( !fzt )
1738  throw InvalidID ( "vehicle", id );
1739 
1740  int color = stream.readUint8 ();
1741 
1742  // a forced networkID of -2 will prevent any ID from being assigned and the unit not being registered in the ID cache
1743  Vehicle* v = new Vehicle ( fzt, gamemap, color/8, -2 );
1744 
1745  v->readData ( stream );
1746 
1747  if ( forceNetworkID > 0 )
1748  v->networkid = forceNetworkID;
1749 
1750  if( gamemap->getUnit( v->networkid, false ))
1751  v->networkid = gamemap->idManager.getNewNetworkID();
1752  gamemap->idManager.registerUnitNetworkID(v);
1753 
1754  return v;
1755 }
1756 
1760 const SingleWeapon* Vehicle::getWeapon( unsigned weaponNum ) const
1761 {
1762  if ( weaponNum <= typ->weapons.count )
1763  return &typ->weapons.weapon[weaponNum];
1764  else
1765  return NULL;
1766 }
1767 
1768 
1769 
1771 {
1772  ASCString s = "The unit " + veh->getName();
1773  s += " (position: "+ veh->getPosition().toString() + ") ";
1774  return s;
1775 }
1776 
1777 
1778 
1779 const int UnitHooveringLogic::FuelConsumption = 50;
1780 
1782 {
1783  if ( veh->height < chtieffliegend || veh->height > chhochfliegend )
1784  return 0;
1785 
1786  if ( veh->maxMovement() )
1787  return veh->getMovement(false, false ) * FuelConsumption * veh->typ->fuelConsumption / (100 * minmalq ) ;
1788  else
1789  return (veh->getMap()->weather.windSpeed * maxwindspeed / 256 ) * veh->typ->fuelConsumption / ( minmalq * 64 );
1790 }
1791 
1792 
1793 int UnitHooveringLogic::getEndurance ( const VehicleType* veh, int height, int resourceModel )
1794 {
1795  assert( height < 8 );
1796 
1797  if ( ! (veh->height & (chtieffliegend | chfliegend | chhochfliegend )))
1798  return -1;
1799 
1800  if ( !veh->fuelConsumption )
1801  return -1;
1802 
1803  int maxmove;
1804  if ( height == -1 )
1805  maxmove = max( max( veh->movement[4], veh->movement[5]), veh->movement[6] );
1806  else
1807  maxmove = veh->movement[height];
1808 
1809  int fields = minmalq * veh->getStorageCapacity(resourceModel).fuel * 100 / (veh->fuelConsumption * FuelConsumption );
1810  if ( maxmove )
1811  return (fields / maxmove );
1812  else
1813  return 0;
1814 }
1815 
1817 {
1818  if ( veh->height < chtieffliegend || veh->height > chhochfliegend || veh->typ->fuelConsumption <= 0)
1819  return -1;
1820 
1821  if ( veh->getCarrier() )
1822  return -1;
1823 
1824  int fuelUsage = calcFuelUsage( veh );
1825  if ( fuelUsage > veh->getTank().fuel )
1826  return 0;
1827 
1828 
1829  int fields = (veh->getTank().fuel - fuelUsage) * 100 / (veh->typ->fuelConsumption * FuelConsumption );
1830  if ( veh->maxMovement() )
1831  return 1 + (fields * minmalq / veh->maxMovement() );
1832  else
1833  return 1;
1834 }
void write(tnstream &stream, bool includeLoadedUnits=true) const
Definition: vehicle.cpp:1121
ASCString getUnitReference(Vehicle *veh)
Definition: vehicle.cpp:1770
void endAnyTurn(void)
hook that is called when any player (including owner) ends turn
Definition: vehicle.cpp:471
int fuel
Definition: typen.h:101
bool weapexist() const
Is the unit able to shoot ?
Definition: vehicle.cpp:796
int getMemoryFootprint() const
Definition: vehicle.cpp:1722
int getExperience_offensive_raw() const
Definition: vehicle.cpp:263
The (base-) classes which are thrown as exceptions.
ItemRepositoryLoader< ObjectType > objectTypeRepository("objecttype")
ReactionFire(Vehicle *_unit)
Definition: vehicle.cpp:661
#define cem_direction
Definition: vehicle.cpp:1099
void paintField(const Surface &src, Surface &dest, SPoint pos, int dir, bool shaded, int shadowDist=-1) const
displays an image of this container on the surface.
int getExperience_defensive() const
Definition: vehicle.cpp:258
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
void fillMagically(bool ammo=true, bool resources=true)
fills a unit with all resources it can carry This function should only be called in the mapeditor ! ...
Definition: vehicle.cpp:1075
map accessing and usage routines used by ASC and the mapeditor
void beginTurn()
hook that called when the turn for a player starts
Definition: vehicle.cpp:435
bool units_gray_after_move
are units that cannot move but shoot displayed in gray ?
Definition: gameoptions.h:72
int size(void)
Returns the size of a unit. A size is equal to the weight of the unit without any cargo or carried re...
Definition: vehicle.cpp:400
int maxMovement() const
the maximum distance that the unit can drive in a single turn on the current level of height ...
Definition: vehicle.cpp:1069
#define chschwimmend
Definition: typen.h:412
void transform(const VehicleType *type)
to be used with EXTREME caution, and only in the mapeditor !!
Definition: vehicle.cpp:405
int getResource(int amount, int resourcetype, bool queryonly, int scope=1, int player=-1)
Definition: vehicle.cpp:328
int damage
Damage. 0 is no damage, when damage reaches 100 the container is destroyed.
static int calcFuelUsage(const Vehicle *veh)
Definition: vehicle.cpp:1781
int getArmor() const
Definition: vehicle.cpp:1675
Vehicle * vehicle
Definition: mapfield.h:89
#define cem_damage
Definition: vehicle.cpp:1091
bool getGeneratorStatus() const
Definition: vehicle.h:323
int getNewNetworkID()
returns a new and unique ID
Definition: gamemap.cpp:1139
int energy
Definition: typen.h:99
ASCString name
a name given by the user or the map creator
void setnewposition(int x, int y)
checks whether the unit can construct a building of the given type.
Definition: vehicle.cpp:808
int repairItem(ContainerBase *item, int newDamage=0, bool autoRepair=false)
void move(Vehicle *veh, const MapCoordinate &dest)
AiParameter * aiparam[8]
Definition: vehicle.h:182
ASCString toString(bool coordinates=false) const
Definition: typen.cpp:314
int ammo[16]
Definition: vehicle.h:87
TechAdapterDependency techDependency
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
#define assertOrThrow(expr)
Definition: errors.h:69
int terrainaccessible2(const MapField *field, const Vehicle *vehicle, int uheight)
Checks if the unit can drive on the field.
Definition: spfst.cpp:79
int maxAmmo(int type) const
Definition: vehicle.cpp:1664
double cargoMovementDivisor
if a transport moves the movement for the units inside a transport is decreased by 1/n of the tranpor...
Definition: vehicletype.h:194
#define cem_class
Definition: vehicle.cpp:1102
int getFirstBit(int zahl)
Count the number of zero bits on the LSB side of "zahl".
Definition: misc.cpp:45
UnitWeapon weapons
The weapons.
Definition: vehicletype.h:248
static const Uint32 transparent
Definition: surface.h:65
Resources getStorageCapacity() const
returns the local storage capacity for the given resource, which depends on the resource mode of the ...
bool shootable(void) const
bool hasFunction(ContainerFunctions function) const
bool canRefuel(void) const
bool canMove() const
Definition: vehicle.cpp:754
void setMovement(int newmove, double cargoDivisor=-1)
sets a new distance that the unit can move
Definition: vehicle.cpp:527
int getOwner() const
returns the number of the player this vehicle/building belongs to
int weight(void) const
weight of unit including cargo
Definition: vehicle.cpp:395
#define cwlaserb
Definition: vehicletype.h:85
bool unitHere(const Vehicle *veh)
checks if the unit is standing on this field. Since units are being cloned for some checks...
Definition: mapfield.cpp:311
#define cem_networkid
Definition: vehicle.cpp:1103
int getAmmo(int type, int num, bool queryOnly)
Definition: vehicle.cpp:1593
int getExperience_defensive_raw() const
Definition: vehicle.cpp:268
#define cem_weapstrength2
Definition: vehicle.cpp:1109
vector< int > weaponShots
Definition: vehicle.h:165
const Surface & getImage() const
Definition: vehicletype.h:325
static sigc::signal< void, ContainerBase * > anyContainerConquered
void setExperience_defensive(int experience)
Definition: vehicle.cpp:279
void init(const Vehicle *eht, int _mode)
virtual int readWord(void)
Reads a 16 bit unsigned Integer. In the stream little-endian byte order is used and a translation is ...
Definition: basestrm.cpp:291
void resetview()
resets the internal view state, so that addview() can be executed again
Definition: vehicle.cpp:1001
int count
amount of ammunition the unit having this weapon can carry
Definition: vehicletype.h:117
MapCoordinate3D getPosition() const
returns the units position
Definition: vehicle.cpp:1552
static Surface createSurface(int width, int height, SDLmm::Color color=255)
Definition: surface.cpp:387
A system that provides a set of images for vehicles, buildings, etc.
int gettype(void) const
Definition: vehicletype.h:158
#define chhochfliegend
Definition: typen.h:416
Resources laserRechargeCost
the resources that recharging the laser for a single shot requires
Definition: vehicletype.h:143
SingleWeapon weapon[16]
Definition: vehicletype.h:170
void read(tnstream &stream)
Definition: typen.cpp:195
ContainerBase * getContainer()
returns a pointer to the ContainerBase of the field or NULL if there is none
Definition: mapfield.cpp:331
void setGeneratorStatus(bool status)
sets the status of the unit's energy generator
Definition: vehicle.cpp:385
ASCString getName() const
The interface for all kinds of IO stream.
Resources getTank() const
returns the resources that the unit is carrying
Definition: vehicle.cpp:378
a single field of the map
Definition: mapfield.h:26
if(!yyg->yy_init)
Definition: scanner.cpp:695
#define UNITVERSIONLIMIT
Definition: vehicle.cpp:47
#define cem_height
Definition: vehicle.cpp:1097
struct GameMap::Weather weather
#define cem_weapstrength
Definition: vehicle.cpp:1094
virtual Uint8 readUint8(void)
Reads a 8 bit unsigned Integer.
Definition: basestrm.cpp:305
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
const VehicleType::HeightChangeMethod * getHeightChange(int dir, int height=0) const
returns the method for changing the height in the specified direction, or none if there is none...
Definition: vehicle.cpp:777
virtual Surface getImage() const
returns an image for the Container.
Definition: vehicle.cpp:1706
Production internalUnitProduction
Definition: containerbase.h:99
vector< int > movement
the distance a unit can travel each round. One value for each of the 8 levels of height ...
Definition: vehicletype.h:203
int view
the visibility range
#define cem_ammunition
Definition: vehicle.cpp:1093
#define cem_experience
Definition: vehicle.cpp:1090
int height
the current level of height ( BITMAPPED ! )
Definition: vehicle.h:118
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
virtual void writeString(const string &pc, bool binary=true)
writes the C++ String pc to the stream.
Definition: basestrm.cpp:545
const int sidenum
the number of sides that a field has; is now fixed at 6;
Definition: typen.h:438
const int vehicleVersion
Definition: vehicle.cpp:1119
vector< MapCoordinate > getCoveredFields()
Definition: vehicle.cpp:1714
#define fieldsizey
Definition: typen.h:441
const int magic
Definition: stack.cpp:36
int getScalarWeaponType(void) const
The class describing properties that are common to all vehicles of a certain kind.
Definition: vehicletype.h:177
int unitConstructionMinDistance
the minimal distance (measured in number of fields) in which units can be externally constructed ...
Definition: vehicletype.h:257
class Vehicle::ReactionFire reactionfire
#define maxmalq
Constants that specify the layout of ASC.
Definition: typen.h:429
MapCoordinate3D getPosition3D() const
returns the units position; if inside building then Height is -1
Definition: vehicle.cpp:1557
void read(tnstream &stream)
replaces the parameters of the unit by the ones form the stream.
Definition: vehicle.cpp:1291
int terrainaccessible(const MapField *field, const Vehicle *vehicle, int uheight)
Checks if the unit can drive on the field.
Definition: spfst.cpp:70
static int getEndurance(const Vehicle *veh)
calculates the time until the unit crashes because of lack of fuel
Definition: vehicle.cpp:1816
int vehicleUnloadable(const VehicleType *vehicleType, int carrierHeight=-1) const
checks the unloading of a unit type
void read(tnstream &stream)
Definition: gamemap.cpp:2054
VehicleList vehicleList
a list of all units
Definition: player.h:135
virtual int getResource(int amount, int resourcetype, bool queryonly, int scope=1, int player=-1)=0
ActionResult execute(const Context &context)
Definition: action.cpp:41
int getAvailableResource(int amount, int resourcetype, int scope=1) const
Definition: vehicle.cpp:356
#define cem_fuel
Definition: vehicle.cpp:1092
int enable()
enables the reaction fire or returns an error code ( result < 0 = -errorNr )
Definition: vehicle.cpp:689
int putResource(int amount, int resourcetype, bool queryonly, int scope=1, int player=-1)
scope: 0 = local 1 = resource network 2 = global in all buildings 3 = map wide pool( used only intern...
Definition: vehicle.cpp:297
const int resourceTypeNum
The number of different resources that ASC uses.
Definition: typen.h:77
void write(tnstream &stream) const
Definition: typen.cpp:201
void setExperience_offensive(int experience)
Definition: vehicle.cpp:274
#define chtieffliegend
Definition: typen.h:414
An object that can be placed on fields. Roads, pipelines and ditches are examples of objects...
Definition: objecttype.h:30
Coordinate on the twodimensional map.
Definition: typen.h:202
ASCString getName() const
returns the units name or, if it does not exist, the unit type's name or description ...
Definition: vehicle.cpp:1569
int getRepairExperienceValue(int oldDamage, int newDamage, bool offensive, int rountToResolution)
Definition: vehicle.cpp:209
void postAttack(bool reactionFire, const Context &context)
callback that is called after the unit has attacked
Definition: vehicle.cpp:1019
virtual void writeUint8(Uint8 c)
Writes a 8 bit unsigned Integer.
Definition: basestrm.cpp:380
Interface for all the fighting routines of ASC.
void paint(Surface &s, SPoint pos, int shadowDist=-1) const
displays the unit at position spos on s
Definition: vehicle.cpp:1681
void endOwnTurn(void)
hook that is called when a player ends his turn
Definition: vehicle.cpp:478
The interface for the buildingtype class.
void decreaseMovement(int movement)
reduces the movement by the given amount.
Definition: vehicle.cpp:572
void setnum(int _x, int _y, int numericalz)
Definition: typen.h:250
#define cem_energy
Definition: vehicle.cpp:1101
void unregisterUnitNetworkID(Vehicle *veh)
Definition: gamemap.cpp:1131
bool canRepair(const ContainerBase *item) const
can the unit repair anything? This does not necessarily mean that the unit can repair other units...
Definition: vehicle.cpp:198
int unitConstructionMoveCostPercentage
if this unit constructs another unit externally (for example a turret), it costs this much of its mov...
Definition: vehicletype.h:254
void removeview()
removes the units view to the map.
Definition: vehicle.cpp:1006
virtual void startsearch(void)
Resources maxplus
the maximum amount of Resources that the building can produce each turn in the ASC resource mode ; se...
const int attackmovecost
Constants that define the behaviour of units and buildings.
Definition: typen.h:479
A single weapon of a #Vehicletype.
Definition: vehicletype.h:100
int material
Definition: typen.h:100
bool vehicleconstructable(const VehicleType *tnk, int x, int y)
checks whether the unit can construct a vehicle of the given type at the given position.
Definition: vehicle.cpp:875
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
#define cem_energyUsed
Definition: vehicle.cpp:1111
VehicleType * getvehicletype_byid(int id)
Definition: gamemap.cpp:1794
#define fieldsizex
Definition: typen.h:440
void setAttacked()
the the unit and all cargo to attacked = true
Definition: vehicle.cpp:1049
int autorepairrate
the damage this unit can repair itself automatically each turn.
Definition: vehicletype.h:251
void readClassContainer(C &c, tnstream &stream)
Definition: basestrm.h:752
#define chfahrend
Definition: typen.h:413
SDLmm::SPoint SPoint
Definition: surface.h:27
Vehicle * getUnit(int x, int y, int nwid)
Definition: gamemap.cpp:1215
Player player[9]
Definition: gamemap.h:253
Resources plus
the Resources that are produced each turn
static CGameOptions * Instance()
returns the only Instance
Definition: gameoptions.cpp:38
GameMap * gamemap
the map that this container is placed on
Definition: containerbase.h:52
#define cem_reactionfire
Definition: vehicle.cpp:1106
int weight
the weight of the unit, without fuel or other cargo
Definition: vehicletype.h:218
static Vehicle * newFromStream(GameMap *gamemap, tnstream &stream, int forceNetworkID=-1)
generates a new unit, loads its parameters from the stream (where they have been previously written w...
Definition: vehicle.cpp:1728
All parameters the AI stores persistently about a unit.
const int generatortruckefficiency
the amount of fuel that a generator vehicle needs to produce one unit of energy
Definition: typen.h:504
int putAmmo(int type, int num, bool queryOnly)
Definition: vehicle.cpp:1630
#define cem_armor
Definition: vehicle.cpp:1105
Resources getStorageCapacity(int mode) const
returns the Storage capacity of the unit
virtual void endOwnTurn(void)
hook that is called when a player ends his turn
caches some calculations for the effects that wind has on the movement of units
vector< HeightChangeMethod > heightChangeMethod
Definition: vehicletype.h:294
int freeWeight()
returns the free weight that can be used for cargo
Definition: vehicle.cpp:971
#define cem_reactionfire2
Definition: vehicle.cpp:1107
vector< int > nonattackableUnits
Definition: vehicle.h:166
virtual ASCString readString(bool includeCR=false)
Reads and returns a string.
Definition: basestrm.cpp:535
int getgameparameter(GameParameter num) const
Definition: gamemap.cpp:1047
int height
the levels of height which this unit can enter
bool canMove(void) const
can the unit move from its current position (does not check neighbouring fields)
Definition: vehicle.cpp:599
bool hasMoved(void) const
did the unit move this turn
Definition: vehicle.cpp:552
class GameMap::IDManager idManager
int connection
if events are triggered by this unit (if it is lost for example), this will set connection != 0 ...
Definition: vehicle.h:133
Resources bi_resourceplus
the maximum amount of Resources that the building can produce each turn in the BI resource mode ; see...
void registerUnitNetworkID(Vehicle *veh)
Definition: gamemap.cpp:1124
int color
The owner of the container.
#define cem_name
Definition: vehicle.cpp:1104
int fuelConsumption
the fuel consumption to move a single field
Definition: vehicletype.h:200
int & resource(int type)
Definition: typen.h:105
int xpos
the position on the map
Definition: vehicle.h:124
int heightChangeMethodNum
Definition: vehicletype.h:281
Definition: player.h:53
ContainerBase * getCarrier() const
if this is a unit and it is inside a building or transport, returns the transport. NULL otherwise.
Resources getExternalVehicleConstructionCost(const VehicleType *tnk) const
Definition: vehicle.cpp:900
void endRound(void)
hook that is called the next round begins ( active player switching from player8 to player1 ) ...
Definition: vehicle.cpp:458
void setExperience_offensive_raw(int experience)
Definition: vehicle.cpp:285
#define cem_loading
Definition: vehicle.cpp:1095
static const int experienceResolution
Definition: vehicle.h:96
void convert(int player, bool recursive=true)
converts the unit so it is owned by 'player'.
Definition: vehicle.cpp:843
void addToCargo(Vehicle *veh, int position=-1)
adds the unit to the cargo
const VehicleType * typ
Definition: vehicle.h:83
virtual void endAnyTurn(void)
hook that is called when any player (including owner) ends turn
~Vehicle()
Definition: vehicle.cpp:102
Uint8 direction
the direction in which the unit is facing
Definition: vehicle.h:121
#define cem_poweron
Definition: vehicle.cpp:1108
bool attacked
did the unit already attack this turn
Definition: vehicle.h:109
Coordinate on the map including height.
Definition: typen.h:238
Building * building
Definition: mapfield.h:102
virtual void endRound(void)
hook that is called the next round begins ( active player switching from player8 to player1 ) ...
bool offensive(void) const
int cargoWeight() const
weight of all loaded units
virtual void writeWord(int w)
Writes a 16 bit unsigned Integer. In the stream little-endian byte order is used and a translation is...
Definition: basestrm.cpp:369
ASCString privateName
a name given by the user which is only visible to him and his allies.
Vehicle * secondvehicle
two units and the same field are only allowed temporary during movement
Definition: mapfield.h:92
const ContainerBaseType * baseType
the type descriping all non-instance specific properties of the container
Definition: containerbase.h:80
sigc::signal< void > conquered
GameMap * actmap
Definition: spfst.cpp:64
bool canPerformAttack(Vehicle *target)
Definition: vehicle.cpp:763
GameMap * getMap() const
vector< IntRange > objectLayedByMovement
the IDs of objects that are automatically layed by moving the movement
Definition: vehicletype.h:245
void writeClassContainer(const C &c, tnstream &stream)
Definition: basestrm.h:742
enum GameMap::State state
The parent class of Vehicle and Building; The name Container originates from Battle Isle...
Definition: containerbase.h:40
const T & max(const T &a, const T &b, const T &c)
Definition: misc.h:97
const T & min(const T &a, const T &b, const T &c)
Definition: misc.h:80
Status getStatus() const
for each player that can still be attacked one bit is set
Definition: vehicle.h:155
void setExperience_defensive_raw(int experience)
Definition: vehicle.cpp:290
int maxstrength
strength of the weapon when fired over the minimal distance
Definition: vehicletype.h:120
A GameAction is an modification of something on a map.
Definition: action.h:45
Resources are basically the currency of ASC.
Definition: typen.h:97
bool available(const Research &research) const
Definition: research.cpp:412
int researchpoints
the current amount of research that the building conducts every turn
bool removeUnitFromCargo(Vehicle *veh, bool recursive=false)
removes the given unit from the container.
const Cargo & getCargo() const
void resetMovement(void)
resets a units movement. This is called at the beginning of each turn.
Definition: vehicle.cpp:518
#define cem_attacked
Definition: vehicle.cpp:1096
int vehicleDocking(const Vehicle *vehicle, bool out) const
returns the levels of height on which this unit can be transfered by docking; or 0 if no unloading is...
int minFieldRepairDamage
if the unit is repaired in the field (that is, not inside a transport or building), it can only be repaired up to this level 0 would result in a complete repair being possible, 20 that it can only be restored to 20% damage (80% health).
Object * checkForObject(const ObjectType *o)
checks if there are objects from the given type on the field and returns them
Definition: mapfield.cpp:648
void endOwnTurn()
hook that is called when a turn ends
Definition: vehicle.cpp:742
int ypos
Definition: vehicle.h:124
int maxLoadableWeight
the maximum total weight of all loaded units
void fatalError(const ASCString &string)
int getdirection(const MapCoordinate &start, const MapCoordinate &dest)
Everything related to research.
TerrainAccess terrainaccess
the terrain this unit can move to
Definition: vehicletype.h:221
#define cem_material
Definition: vehicle.cpp:1100
const float repairEfficiencyVehicle[resourceTypeNum *resourceTypeNum]
Definition: vehicle.cpp:41
const SingleWeapon * getWeapon(unsigned weaponNum) const
Returns the SingleWeapon corresponding to the weaponNum for this vehicle.
Definition: vehicle.cpp:1760
#define cem_ammunition2
Definition: vehicle.cpp:1110
#define chfliegend
Definition: typen.h:415
#define cem_position
Definition: vehicle.cpp:1112
int networkid
a unique identification of the unit that is used everywhere in ASC (and not only the network protocol...
Definition: vehicle.h:140
void registerForNewOwner(int player)
this is a low level functions that changes the registration in the map. It's called by convert(int...
Definition: vehicle.cpp:857
void write(tnstream &stream)
Definition: gamemap.cpp:2035
virtual void postRepair(int oldDamage, bool autoRepair)
is called after a repair is performed. Vehicles use this to reduce their experience.
Definition: vehicle.cpp:423
int getMovement(bool checkFuel=true, bool checkRF=true) const
returns the movement points the unit has left for this turn. CheckFuel should almost always be true...
Definition: vehicle.cpp:558
int weapstrength[16]
Definition: vehicle.h:90
bool spawnMoveObjects(const MapCoordinate &start, const MapCoordinate &dest, const Context &context)
add the objects like tracks or broken ice
Definition: vehicle.cpp:621
#define minmalq
Definition: typen.h:430
void addview()
adds the units view to the map.
Definition: vehicle.cpp:990
static const int repairExperienceDecrease
the percentage of experience that is removed when repairing a fully damaged unit
Definition: vehicle.cpp:206
int cargoNestingDepth()
returns the nesting depth of the cargo. The unit standing on the field is 0, its cargo is 1...
#define cem_aiparam
Definition: vehicle.cpp:1113
void unregisterPosition()
unregisters the unit at its current position (e.g. from a map field, or inside a transport) ...
Definition: vehicle.cpp:830
const int maxwindspeed
Wind with its maximum strength of 255 is moving this distance per turn.
Definition: typen.h:501
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
#define cem_version
Definition: vehicle.cpp:1114
MapField * getField(int x, int y)
Definition: gamemap.h:465
int getExperience_offensive() const
Definition: vehicle.cpp:253
#define cem_movement
Definition: vehicle.cpp:1098