Advanced Strategic Command
attackcommand.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Advanced Strategic Command; http://www.asc-hq.de
3  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  Boston, MA 02111-1307 USA
19 */
20 
21 
22 #include "attackcommand.h"
23 
24 #include "../vehicle.h"
25 #include "../mapfield.h"
26 #include "../gamemap.h"
27 #include "../viewcalculation.h"
28 #include "../spfst.h"
29 #include "../mapdisplayinterface.h"
30 #include "vehicleattack.h"
31 #include "action-registry.h"
32 
33 
35 {
36  if ( eht )
37  if ( eht->attacked == false )
38  if ( eht->weapexist() )
39  if (eht->typ->wait == false || !eht->hasMoved() )
40  return true;
41  return false;
42 }
43 
44 
45 AttackCommand :: AttackCommand ( Vehicle* unit )
46  : UnitCommand ( unit ), targetUnitID(-1), weapon(-1), kamikaze(false)
47 {
48 
49 }
50 
52 {
53  if ( !getUnit() )
54  return ActionResult(201);
55 
56  Vehicle* unit = getUnit();
57 
58  int weaponCount = 0;
59  int shootableWeaponCount = 0;
60  for ( int w = 0; w < getUnit()->typ->weapons.count; w++ )
61  if ( unit->typ->weapons.weapon[w].shootable() ) {
62  weaponCount++;
63  if ( unit->typ->weapons.weapon[w].sourceheight & unit->height )
64  shootableWeaponCount++;
65  }
66 
67  if ( weaponCount == 0 )
68  return ActionResult(214);
69 
70  if ( shootableWeaponCount == 0 )
71  return ActionResult(213);
72 
73 
74 
75  if (fieldvisiblenow( getMap()->getField( unit->getPosition() ), getMap()->actplayer ) == false)
76  return ActionResult(1);
77 
78  if (unit->attacked)
79  return ActionResult(202);
80 
81 
82  if ( unit->typ->weapons.count == 0)
83  return ActionResult(204);
84 
85  if ( unit->typ->wait && getUnit()->hasMoved() && unit->reactionfire.getStatus() != Vehicle::ReactionFire::ready )
86  return ActionResult(215);
87 
88 
89  attackableUnits.clear();
90  attackableUnitsKamikaze.clear();
91  attackableBuildings.clear();
92  attackableObjects.clear();
93 
94 
95  int d = 0;
96  int maxdist = 0;
97  int mindist = 20000;
98  for ( int a = 0; a < unit->typ->weapons.count; a++)
99  if ( unit->ammo[a] > 0) {
100  d++;
101  maxdist = max( maxdist, unit->typ->weapons.weapon[a].maxdistance / maxmalq );
102  mindist = min ( mindist, (unit->typ->weapons.weapon[a].mindistance + maxmalq - 1) / maxmalq);
103  }
104 
105 
106  if (d == 0)
107  return ActionResult(204);
108 
109  circularFieldIterator( getMap(), unit->getPosition(), maxdist, mindist, FieldIterationFunctor( this, &AttackCommand::fieldChecker ));
110 
111  if ( attackableUnits.size() + attackableBuildings.size() + attackableObjects.size() + attackableUnitsKamikaze.size() ) {
113  return ActionResult(0);
114  } else
115  return ActionResult(206);
116 }
117 
118 void AttackCommand :: fieldChecker( const MapCoordinate& pos )
119 {
120  if ( fieldvisiblenow( getMap()->getField(pos)) ) {
121  if ( !kamikaze ) {
122  AttackWeap* atw = attackpossible( getUnit(), pos.x, pos.y );
123  if (atw->count > 0) {
124  switch ( atw->target ) {
125  case AttackWeap::vehicle: attackableUnits[pos] = *atw ;
126  break;
127  case AttackWeap::building: attackableBuildings[pos] = *atw;
128  break;
129  case AttackWeap::object: attackableObjects[pos] = *atw;
130  break;
131  default:;
132  } /* endswitch */
133  }
134  delete atw;
135  } else {
136  MapField* fld = getMap()->getField(pos);
137  if (fieldvisiblenow( fld )) {
138  Vehicle* eht = fld->vehicle;
139  if (eht != NULL)
140  if (((getUnit()->height >= chtieffliegend) && (eht->height <= getUnit()->height) && (eht->height >= chschwimmend))
141  || ((getUnit()->height == chfahrend) && (eht->height == chfahrend))
142  || ((getUnit()->height == chschwimmend) && (eht->height == chschwimmend))
143  || ((getUnit()->height == chgetaucht) && (eht->height >= chgetaucht) && (eht->height <= chschwimmend))) {
144  attackableUnitsKamikaze.push_back ( pos );
145  }
146  }
147  }
148  }
149 }
150 
151 
152 void AttackCommand :: setTarget( const MapCoordinate& target, int weapon )
153 {
154 
155  // if ( getState() == Evaluated ) {
156  this->weapon = weapon;
157  this->target = target;
158  MapField* fld = getMap()->getField( target );
159  if ( fld->vehicle )
160  targetUnitID = fld->vehicle->networkid;
161  else
162  targetBuilding = target;
163 
164  setState( SetUp );
165  // }
166 }
167 
169 {
170  MapCoordinate targetPosition;
171 
172  if ( getState() != SetUp )
173  return ActionResult(22000);
174 
175  searchTargets();
176 
177  AttackWeap* atw = NULL;
178 
179  if ( targetUnitID > 0 ) {
180  Vehicle* veh = getMap()->getUnit( targetUnitID );
181  if ( !veh )
182  return ActionResult(21001);
183 
184  targetPosition = veh->getPosition();
185  if ( attackableUnits.find(targetPosition) == attackableUnits.end() )
186  return ActionResult(208);
187 
188  atw = &attackableUnits[targetPosition];
189  } else
190  if ( targetBuilding.valid() && getMap()->getField(targetBuilding)->building ) {
191  if ( attackableBuildings.find(targetBuilding) == attackableBuildings.end() )
192  return ActionResult(217);
193  atw = &attackableBuildings[targetBuilding];
194  targetPosition = targetBuilding;
195  } else {
196  if ( attackableObjects.find(targetBuilding) == attackableObjects.end() )
197  return ActionResult(217);
198  atw = &attackableObjects[target];
199  targetPosition = target;
200  }
201 
202 
203  if ( !atw )
204  return ActionResult(217);
205 
206  ActionResult res = (new VehicleAttackAction(getMap(), getUnitID(), targetPosition, weapon ))->execute( context );
207  if ( res.successful() )
208  setState( Finished );
209  else
210  setState( Failed );
211  return res;
212 
213 }
214 
215 static const int attackCommandVersion = 2;
216 
218 {
219  UnitCommand::readData( stream );
220  int version = stream.readInt();
221  if ( version > attackCommandVersion )
222  throw tinvalidversion ( "AttackCommand", attackCommandVersion, version );
223  target.read( stream );
224  targetUnitID = stream.readInt();
225  targetBuilding.read( stream );
226  weapon = stream.readInt();
227  if ( version >= 2 )
228  kamikaze = stream.readInt();
229  else
230  kamikaze = false;
231 }
232 
233 void AttackCommand :: writeData ( tnstream& stream ) const
234 {
235  UnitCommand::writeData( stream );
236  stream.writeInt( attackCommandVersion );
237  target.write( stream );
238  stream.writeInt( targetUnitID );
239  targetBuilding.write( stream );
240  stream.writeInt( weapon );
241  stream.writeInt( kamikaze );
242 }
243 
245  ASCString c;
246  c.format("unitAttack ( map, %d, asc.MapCoordinate(%d, %d), %d )", getUnitID(), target.x, target.y, weapon );
247  return c;
248 
249 }
250 
252 {
254 }
255 
257 {
258  ASCString s = "Attacking ";
259  s += " " + target.toString();
260  if ( getUnit() ) {
261  s += " with " + getUnit()->getName();
262  }
263  return s;
264 }
265 
266 namespace {
267  const bool r1 = registerAction<AttackCommand> ( ActionRegistry::AttackCommand );
268 }
269 
bool weapexist() const
Is the unit able to shoot ?
Definition: vehicle.cpp:796
bool wait
If the unit cannot attack in the same turn after it has moved, it has to wait.
Definition: vehicletype.h:197
enum AttackWeap::Target target
void writeData(tnstream &stream) const
Definition: unitcommand.cpp:67
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
GameActionID getID() const
#define chschwimmend
Definition: typen.h:412
int GameActionID
Definition: action.h:35
the command is totally done
Definition: command.h:120
int getUnitID() const
Definition: unitcommand.h:37
Vehicle * vehicle
Definition: mapfield.h:89
Structure to store the weapons which a unit can use to perform an attack.
Definition: attack.h:291
bool valid() const
Definition: typen.h:221
void writeData(tnstream &stream) const
int ammo[16]
Definition: vehicle.h:87
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
UnitWeapon weapons
The weapons.
Definition: vehicletype.h:248
int sourceheight
the weapon can be shot from these levels of height (bitmapped)
Definition: vehicletype.h:108
bool shootable(void) const
State getState() const
Definition: command.h:125
void read(tnstream &stream)
Definition: typen.h:213
MapCoordinate3D getPosition() const
returns the units position
Definition: vehicle.cpp:1552
GameMap * getMap()
Definition: action.h:92
SingleWeapon weapon[16]
Definition: vehicletype.h:170
ASCString toString(bool coordinates=false) const
Definition: typen.cpp:304
The interface for all kinds of IO stream.
a single field of the map
Definition: mapfield.h:26
ASCString & format(const charT *pFormat,...)
Definition: ascstring.cpp:78
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
int height
the current level of height ( BITMAPPED ! )
Definition: vehicle.h:118
ActionResult go(const Context &context)
bool fieldvisiblenow(const MapField *pe, Vehicle *veh, int player)
{@
Definition: spfst.cpp:399
class Vehicle::ReactionFire reactionfire
#define maxmalq
Constants that specify the layout of ASC.
Definition: typen.h:429
int mindistance
the minimal distance the weapon can shoot
Definition: vehicletype.h:114
ActionResult execute(const Context &context)
Definition: action.cpp:41
void write(tnstream &stream) const
Definition: typen.h:212
void readData(tnstream &stream)
#define chtieffliegend
Definition: typen.h:414
Coordinate on the twodimensional map.
Definition: typen.h:202
void circularFieldIterator(GameMap *gamemap, const MapCoordinate &center, int startDist, int stopDist, FieldIterationFunctor functor)
ASCString getName() const
returns the units name or, if it does not exist, the unit type's name or description ...
Definition: vehicle.cpp:1569
ASCString getDescription() const
static const int attackCommandVersion
static bool avail(Vehicle *eht)
int maxdistance
the maximum distance the weapon can shoot
Definition: vehicletype.h:111
void setState(State state)
Definition: command.cpp:44
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
bool successful() const
#define chfahrend
Definition: typen.h:413
Vehicle * getUnit(int x, int y, int nwid)
Definition: gamemap.cpp:1215
bool hasMoved(void) const
did the unit move this turn
Definition: vehicle.cpp:552
int count
Definition: attack.h:294
const VehicleType * typ
Definition: vehicle.h:83
bool attacked
did the unit already attack this turn
Definition: vehicle.h:109
Building * building
Definition: mapfield.h:102
void readData(tnstream &stream)
Definition: unitcommand.cpp:52
AttackWeap * attackpossible(const Vehicle *attacker, int x, int y)
Is attacker able to attack anything in field x/y ?
Definition: attack.cpp:842
ASCString getCommandString() const
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
ActionResult searchTargets()
#define chgetaucht
Definition: typen.h:411
void setTarget(const MapCoordinate &target, int weapon=-1)
int networkid
a unique identification of the unit that is used everywhere in ASC (and not only the network protocol...
Definition: vehicle.h:140
Loki::Functor< void, LOKI_TYPELIST_1(const MapCoordinate &) > FieldIterationFunctor
Definition: mapalgorithms.h:43
const Vehicle * getUnit() const
Definition: unitcommand.cpp:26
MapField * getField(int x, int y)
Definition: gamemap.h:465