Advanced Strategic Command
jumpdrivecommand.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 "jumpdrivecommand.h"
23 
24 #include "../vehicle.h"
25 #include "../mapfield.h"
26 #include "../gamemap.h"
27 #include "../viewcalculation.h"
28 #include "../spfst.h"
29 #include "changeunitmovement.h"
30 #include "../mapdisplayinterface.h"
31 #include "action-registry.h"
32 #include "../reactionfire.h"
33 #include "../soundList.h"
34 #include "consumeresource.h"
35 #include "servicecommand.h"
36 #include "unitfieldregistration.h"
37 #include "changeunitproperty.h"
38 
40 {
41  ActionAvailability avail;
42  if ( !unit )
43  return avail.set( ActionAvailability::notAtAll, "No unit selected");
44 
45  if ( !unit->typ->jumpDrive.height )
46  return avail.set( ActionAvailability::notAtAll, "Unit has no jump drive");
47 
48  if ( unit->typ->jumpDrive.movementConsumptionPercentage == 100 ) {
49  if ( unit->hasMoved() )
50  avail.set( ActionAvailability::partially, "Unit has already moved" );
51  } else {
52  int needed = unit-> maxMovement() * unit->typ->jumpDrive.movementConsumptionPercentage / 100;
53  if ( needed > unit->getMovement(false) )
54  avail.set( ActionAvailability::partially, "Unit has not enough movement left, need " + ASCString::toString(needed) + " points" );
55  }
56 
57  if ( unit->attacked && !unit->typ->jumpDrive.jumpAfterAttack )
58  avail.set( ActionAvailability::partially, "Unit has already attacked" );
59 
61  avail.set( ActionAvailability::partially, "Unit has reaction fire enabled" );
62 
63  if ( !(unit->height & unit->typ->jumpDrive.height) )
64  avail.set( ActionAvailability::partially, "Unit needs to be on this height: " + heightToString(unit->typ->jumpDrive.height) );
65 
66  if ( unit->getResource( unit->typ->jumpDrive.consumption ) < unit->typ->jumpDrive.consumption )
67  avail.set( ActionAvailability::partially, "Unit is missing resources. Required: " + unit->typ->jumpDrive.consumption.toString() );
68 
69  return avail;
70 }
71 
72 JumpDriveCommand :: JumpDriveCommand ( Vehicle* unit)
73  : UnitCommand ( unit )
74 {
75 
76 }
77 
78 
80 {
81  MapField* fld = getMap()->getField( dest );
82  if ( beeline( dest, getUnit()->getPosition()) <= getUnit()->typ->jumpDrive.maxDistance )
83  if ( !fld->vehicle && !fld->building )
84  if ( fieldvisiblenow( fld, getUnit()->getOwner() ))
85  if ( getUnit()->typ->jumpDrive.targetterrain.accessible( fld->bdt ) > 0 )
86  return true;
87 
88  return false;
89 }
90 
91 
92 vector<MapCoordinate> JumpDriveCommand::getDestinations()
93 {
94  vector<MapCoordinate> fields;
95 
96  if ( !available( getUnit() ).ready() )
97  return fields;
98 
99  GameMap* gamemap = getMap();
100 
101  for ( int y = 0; y < gamemap->ysize; ++y )
102  for (int x = 0; x < gamemap->xsize; ++x ) {
103  MapCoordinate dest (x,y);
104  if ( fieldReachable( dest))
105  fields.push_back( dest );
106 
107  }
108  return fields;
109 }
110 
112 {
113  if ( fieldReachable( position )) {
114  destination = position;
115  setState( SetUp );
116  }
117 }
118 
119 
121 {
122  if ( getState() != SetUp )
123  return ActionResult(22000);
124 
125  Vehicle* unit = getUnit();
126 
127  if ( !available( unit ).ready() )
128  return ActionResult( 22600 );
129 
130  if ( !fieldReachable( destination ))
131  return ActionResult( 22601 );
132 
133 
134  auto_ptr<ConsumeResource> cr ( new ConsumeResource( unit, unit->typ->jumpDrive.consumption ));
135  ActionResult res = cr->execute( context );
136  if ( !res.successful() )
137  return res;
138  else
139  cr.release();
140 
141  auto_ptr<UnitFieldRegistration> ufr1 ( new UnitFieldRegistration( unit, unit->getPosition(), UnitFieldRegistration::RemoveView ));
142  res = ufr1->execute( context );
143  if ( !res.successful() )
144  return res;
145  else
146  ufr1.release();
147 
148  auto_ptr<UnitFieldRegistration> ufr2 ( new UnitFieldRegistration( unit, unit->getPosition(), UnitFieldRegistration::UnregisterOnField ));
149  res = ufr2->execute( context );
150  if ( !res.successful() )
151  return res;
152  else
153  ufr2.release();
154 
155 
156  MapCoordinate3D dest3D (destination, unit->height );
157 
159  srfu.init( unit , dest3D );
160 
161 
162  auto_ptr<UnitFieldRegistration> ufr3( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::Position3D ));
163  res = ufr3->execute( context );
164  if ( !res.successful() )
165  return res;
166  else
167  ufr3.release();
168 
169  auto_ptr<UnitFieldRegistration> ufr4 ( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::RegisterOnField ));
170  res = ufr4->execute( context );
171  if ( !res.successful() )
172  return res;
173  else
174  ufr4.release();
175 
176 
177  if ( context.display )
179 
180  int newmovement;
181  if ( unit->typ->jumpDrive.movementConsumptionPercentage >= 100 )
182  newmovement = 0;
183  else
184  newmovement = unit->getMovement(false,false) - unit->maxMovement() * unit->typ->jumpDrive.movementConsumptionPercentage / 100 ;
185 
186  auto_ptr<ChangeUnitMovement> cum ( new ChangeUnitMovement( unit, newmovement, false, ChangeUnitMovement::ALLFULL ));
187  res = cum->execute( context );
188  if ( !res.successful() )
189  return res;
190  else
191  cum.release();
192 
193  if ( !unit->typ->jumpDrive.attackAfterJump ) {
194  auto_ptr<ChangeUnitProperty> cup ( new ChangeUnitProperty( unit, ChangeUnitProperty::AttackedFlag, 1 ));
195  res = cup->execute( context );
196  if ( !res.successful() )
197  return res;
198  else
199  cup.release();
200  }
201 
202 
203  auto_ptr<UnitFieldRegistration> ufr5( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::AddView ));
204  res = ufr5->execute( context );
205  if ( !res.successful() )
206  return res;
207  else
208  ufr5.release();
209 
210  computeview( getMap(), 0, false, &context );
211 
212 
213  int unitOwner = unit->getOwner();
214  srfu.checkfield( dest3D, unit, context );
215  srfu.finalCheck( unitOwner, context );
216 
217 
218  if ( context.display )
219  context.display->repaintDisplay();
220 
221  if ( res.successful() )
222  setState( Finished );
223  else
224  setState( Failed );
225 
226  return res;
227 }
228 
229 
230 
231 static const int JumpDriveCommandVersion = 1;
232 
234 {
235  UnitCommand::readData( stream );
236  int version = stream.readInt();
237  if ( version > JumpDriveCommandVersion )
238  throw tinvalidversion ( "JumpDriveCommand", JumpDriveCommandVersion, version );
239  destination.read( stream );
240 }
241 
243 {
244  UnitCommand::writeData( stream );
246  destination.write( stream );
247 }
248 
249 
251 {
252  ASCString c;
253  c.format("unitJump ( map, %d, asc.MapCoordinate( %d, %d ) )", getUnitID(), destination.x, destination.y );
254  return c;
255 
256 }
257 
259 {
261 }
262 
264 {
265  ASCString s = "Jump ";
266 
267  if ( getUnit())
268  s += getUnit()->getName();
269 
270  s += " to " + destination.toString();
271  return s;
272 }
273 
274 namespace
275 {
276  const bool r1 = registerAction<JumpDriveCommand> ( ActionRegistry::JumpDriveCommand );
277 }
278 
the action is not available and no action symbol shall be shown to the user.
struct VehicleType::JumpDrive jumpDrive
void writeData(tnstream &stream) const
Definition: unitcommand.cpp:67
int xsize
the size of the map
Definition: gamemap.h:201
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
int computeview(GameMap *gamemap, int player_fieldcount_mask, bool disableShareView, const Context *context)
completely computes the view
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
int GameActionID
Definition: action.h:35
int getResource(int amount, int resourcetype, bool queryonly, int scope=1, int player=-1)
Definition: vehicle.cpp:328
the command is totally done
Definition: command.h:120
int getUnitID() const
Definition: unitcommand.h:37
Vehicle * vehicle
Definition: mapfield.h:89
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
ASCString heightToString(int bitmappedHeight)
Definition: typen.cpp:396
ASCString toString() const
Definition: typen.cpp:268
bool hasFunction(ContainerFunctions function) const
static SoundList & getInstance()
Definition: soundList.cpp:60
int getOwner() const
returns the number of the player this vehicle/building belongs to
void readData(tnstream &stream)
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
the action would be available, if not some prerequisites are missing which the user could provide ...
GameMap * getMap()
Definition: action.h:92
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
void writeData(tnstream &stream) const
int checkfield(const MapCoordinate3D &pos, Vehicle *&eht, const Context &context)
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
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
virtual void playPositionalSound(const MapCoordinate &pos, Sound *snd)=0
bool fieldvisiblenow(const MapField *pe, Vehicle *veh, int player)
{@
Definition: spfst.cpp:399
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
class Vehicle::ReactionFire reactionfire
void write(tnstream &stream) const
Definition: typen.h:212
static ActionAvailability available(const Vehicle *unit)
Coordinate on the twodimensional map.
Definition: typen.h:202
ASCString getCommandString() const
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 height
bitmapped: on these levels of height the jump drive can be activated
Definition: vehicletype.h:310
void setDestination(const MapCoordinate &position)
void setState(State state)
Definition: command.cpp:44
static const int JumpDriveCommandVersion
ASCString getDescription() const
bool successful() const
vector< MapCoordinate > getDestinations()
virtual int finalCheck(int currentPlayer, const Context &context)
MapDisplayInterface * display
Definition: context.h:39
int ysize
Definition: gamemap.h:201
TerrainBits bdt
the terraintype properties. They determine which units can move over the field. This variable is reca...
Definition: mapfield.h:161
bool hasMoved(void) const
did the unit move this turn
Definition: vehicle.cpp:552
bool fieldReachable(const MapCoordinate &dest)
ActionAvailability & set(Availability avail, const ASCString &msg)
const VehicleType * typ
Definition: vehicle.h:83
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
void readData(tnstream &stream)
Definition: unitcommand.cpp:52
GameActionID getID() const
Status getStatus() const
for each player that can still be attacked one bit is set
Definition: vehicle.h:155
ActionResult go(const Context &context)
loaded units get same change as carrier
void init(Vehicle *eht, const AStar3D::Path &fieldlist)
virtual void repaintDisplay()=0
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
const Vehicle * getUnit() const
Definition: unitcommand.cpp:26
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
MapField * getField(int x, int y)
Definition: gamemap.h:465