Advanced Strategic Command
putobjectcommand.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 "putobjectcommand.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 "action-registry.h"
31 #include "../itemrepository.h"
32 
33 #include "removeobject.h"
34 #include "spawnobject.h"
35 #include "consumeresource.h"
36 #include "changeunitmovement.h"
37 
39 {
40 
41  if ( eht )
42  if (eht->getOwner() == eht->getMap()->actplayer)
43  if ( eht->typ->objectsBuildable.size() || eht->typ->objectsRemovable.size() || eht->typ->objectGroupsBuildable.size() || eht->typ->objectGroupsRemovable.size())
44  if ( !eht->attacked )
45  return true;
46  return false;
47 }
48 
49 
50 PutObjectCommand :: PutObjectCommand ( Vehicle* unit )
51  : UnitCommand ( unit ), object(-1),mode(Build)
52 {
53 
54 }
55 
56 
57 vector<MapCoordinate> PutObjectCommand::getFields()
58 {
59  vector<MapCoordinate> fields;
60  for ( map<MapCoordinate,set<int> > ::iterator i = objectsCreatable.begin(); i != objectsCreatable.end(); ++i )
61  fields.push_back ( i->first );
62 
63  for ( map<MapCoordinate,set<int> > ::iterator i = objectsRemovable.begin(); i != objectsRemovable.end(); ++i )
64  if ( find(fields.begin(), fields.end(), i->first) == fields.end() )
65  fields.push_back ( i->first );
66  return fields;
67 }
68 
70 {
71  return objectsCreatable[pos];
72 }
73 
75 {
76  return objectsRemovable[pos];
77 }
78 
80 {
81  if ( !getUnit() )
82  return ActionResult(201);
83 
84 
85  objectsCreatable.clear();
86  objectsRemovable.clear();
87 
88  circularFieldIterator( getMap(), getUnit()->getPosition(), 1, 1, FieldIterationFunctor( this, &PutObjectCommand::fieldChecker ));
89 
90  if ( objectsRemovable.size() + objectsCreatable.size() ) {
92  return ActionResult(0);
93  } else
94  return ActionResult(21504);
95 }
96 
97 bool PutObjectCommand::checkObject( MapField* fld, ObjectType* objtype, Mode mode )
98 {
99  if ( !objtype || !fld )
100  return false;
101 
102  Vehicle* veh = getUnit();
103 
104  if ( mode == Build ) {
105  if ( objtype->getFieldModification(fld->getWeather()).terrainaccess.accessible( fld->bdt ) > 0
106  && !fld->checkForObject ( objtype )
107  && objtype->techDependency.available(getMap()->player[veh->getOwner()].research) ){
108 // && !getheightdelta ( getFirstBit( actvehicle->height), getFirstBit(objtype->getEffectiveHeight())) ) {
109 
110  if ( veh->getResource(objtype->buildcost, true) == objtype->buildcost && veh->getMovement() >= objtype->build_movecost )
111  return true;
112  }
113  } else {
114  if ( fld->checkForObject ( objtype ) ) {
115 // && !getheightdelta ( getFirstBit( actvehicle->height), getFirstBit(objtype->getEffectiveHeight())) ) {
116  Resources r = objtype->removecost;
117  for ( int i = 0; i <3; ++i )
118  if ( r.resource(i) < 0 )
119  r.resource(i) = 0;
120 
121  if ( veh->getResource(r, true) == r && veh->getMovement() >= objtype->remove_movecost )
122  return true;
123  }
124  }
125  return false;
126 }
127 
128 
129 void PutObjectCommand :: fieldChecker( const MapCoordinate& pos )
130 {
131  MapField* fld = getMap()->getField(pos);
132  if ( !fld )
133  return;
134 
135  if ( fld->vehicle || fld->building )
136  return;
137 
138  if ( fieldvisiblenow( getMap()->getField(pos)) ) {
139 
140  Vehicle* veh = getUnit();
141 
142  for ( int i = 0; i < veh->typ->objectsBuildable.size(); i++ )
143  for ( int j = veh->typ->objectsBuildable[i].from; j <= veh->typ->objectsBuildable[i].to; j++ ) {
144  ObjectType* objType = getMap()->getobjecttype_byid ( j );
145  if ( checkObject( fld, objType, Build ))
146  objectsCreatable[pos].insert( objType->id );
147  }
148 
149 
150  for ( int i = 0; i < veh->typ->objectGroupsBuildable.size(); i++ )
151  for ( int j = veh->typ->objectGroupsBuildable[i].from; j <= veh->typ->objectGroupsBuildable[i].to; j++ )
152  for ( int k = 0; k < objectTypeRepository.getNum(); k++ ) {
153  ObjectType* objtype = objectTypeRepository.getObject_byPos ( k );
154  if ( objtype->groupID == j )
155  if ( checkObject( fld, objtype, Build ))
156  if ( find ( objectsCreatable[pos].begin(), objectsCreatable[pos].end(), objtype->id) == objectsCreatable[pos].end() )
157  objectsCreatable[pos].insert( objtype->id );
158  }
159 
160  for ( int i = 0; i < veh->typ->objectsRemovable.size(); i++ )
161  for ( int j = veh->typ->objectsRemovable[i].from; j <= veh->typ->objectsRemovable[i].to; j++ ) {
162  ObjectType* objType = getMap()->getobjecttype_byid ( j );
163  if ( checkObject( fld, objType, Remove ))
164  objectsRemovable[pos].insert( objType->id );
165  }
166 
167 
168  for ( int i = 0; i < veh->typ->objectGroupsRemovable.size(); i++ )
169  for ( int j = veh->typ->objectGroupsRemovable[i].from; j <= veh->typ->objectGroupsRemovable[i].to; j++ )
170  for ( int k = 0; k < objectTypeRepository.getNum(); k++ ) {
171  ObjectType* objtype = objectTypeRepository.getObject_byPos ( k );
172  if ( objtype->groupID == j )
173  if ( checkObject( fld, objtype, Remove ))
174  if ( find ( objectsRemovable[pos].begin(), objectsRemovable[pos].end(), objtype->id) == objectsRemovable[pos].end() )
175  objectsRemovable[pos].insert( objtype->id );
176  }
177 
178  }
179 }
180 
181 
182 void PutObjectCommand :: setTarget( const MapCoordinate& target, int objectID )
183 {
184 
185 // if ( getState() == Evaluated ) {
186  this->target = target;
187  this->object = objectID;
188 
189  MapField* fld = getMap()->getField(target);
190 
191  if( !fld )
192  throw ActionResult(21002);
193 
194  ObjectType* obj = getMap()->getobjecttype_byid( objectID);
195  if( !obj )
196  throw ActionResult(21501);
197 
198  if ( !fld->checkForObject( obj ))
199  mode = Build;
200  else
201  mode = Remove;
202 
203  setState( SetUp );
204 // }
205 }
206 
208 {
209  MapCoordinate targetPosition;
210 
211  if ( getState() != SetUp )
212  return ActionResult(22000);
213 
214  if ( !avail( getUnit() ) )
215  return ActionResult(21506);
216 
217  searchFields();
218 
219  set<int>* objects;
220  if ( mode == Build ) {
221  objects = &objectsCreatable[target];
222  } else {
223  objects = &objectsRemovable[target];
224  }
225 
226  if ( find( objects->begin(), objects->end(), object ) == objects->end() )
227  return ActionResult( 21507 );
228 
229 
230  ObjectType* obj = getMap()->getobjecttype_byid( object );
231 
232  RecalculateAreaView rav ( getMap(), target, maxViewRange / maxmalq + 1, &context );
233 
234 
235  bool objectAffectsVisibility = obj->basicjamming_plus || obj->viewbonus_plus || obj->viewbonus_abs != -1 || obj->basicjamming_abs != -1;
236  if ( objectAffectsVisibility )
237  rav.removeView();
238 
239  ActionResult res(0);
240  if ( mode == Build )
241  res = (new SpawnObject(getMap(), target, object ))->execute( context );
242  else
243  res = (new RemoveObject(getMap(), target, object ))->execute( context );
244 
245 
246  if ( objectAffectsVisibility )
247  rav.addView();
248 
249  if ( res.successful() )
250  res = (new ConsumeResource( getUnit(), mode==Build ? obj->buildcost : obj->removecost ))->execute(context);
251 
252  if ( res.successful() )
253  res = (new ChangeUnitMovement( getUnit(), mode==Build ? obj->build_movecost : obj->remove_movecost, true ))->execute(context);
254 
255  if ( res.successful() ) {
256  if ( context.display )
257  context.display->repaintDisplay();
258  setState( Finished );
259  } else
260  setState( Failed );
261  return res;
262 
263 }
264 
265 static const int putObjectCommandVersion = 1;
266 
268 {
269  UnitCommand::readData( stream );
270  int version = stream.readInt();
271  if ( version > putObjectCommandVersion )
272  throw tinvalidversion ( "PutObjectCommand", putObjectCommandVersion, version );
273  target.read( stream );
274  object = stream.readInt();
275  mode = (Mode) stream.readInt();
276 }
277 
279 {
280  UnitCommand::writeData( stream );
281  stream.writeInt( putObjectCommandVersion );
282  target.write( stream );
283  stream.writeInt( object );
284  stream.writeInt( mode );
285 }
286 
288 {
289  ASCString c;
290  if ( mode == Build )
291  c.format("unitPutObject ( map, %d, asc.MapCoordinate( %d, %d), %d )", getUnitID(), target.x, target.y, object );
292  else
293  c.format("unitRemoveObject ( map, %d, asc.MapCoordinate( %d, %d), %d )", getUnitID(), target.x, target.y, object );
294  return c;
295 
296 }
297 
299 {
301 }
302 
304 {
305  ASCString s;
306 
307  if ( mode == Build )
308  s = "Put ";
309  else
310  s = "Remove ";
311 
312  const ObjectType* obj = getMap()->getobjecttype_byid( object );
313  if ( obj )
314  s += obj->name;
315  else
316  s += "object";
317 
318  if ( getUnit() ) {
319  s += " with " + getUnit()->getName();
320  }
321  s += " at " + target.toString();
322  return s;
323 }
324 
325 namespace
326 {
327  const bool r1 = registerAction<PutObjectCommand> ( ActionRegistry::PutObjectCommand );
328 }
329 
int viewbonus_plus
units standing on this object will get a bonus to their view
Definition: objecttype.h:94
vector< IntRange > objectsBuildable
the ids of objects this unit can construct
Definition: vehicletype.h:233
const set< int > & getRemovableObjects(const MapCoordinate &pos)
ItemRepositoryLoader< ObjectType > objectTypeRepository("objecttype")
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
int id
the id of the object, used when referencing objects in files
Definition: objecttype.h:35
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
vector< IntRange > objectGroupsRemovable
the group-ids of objects this unit can remove
Definition: vehicletype.h:242
int getOwner() const
returns the number of the player this vehicle/building belongs to
int build_movecost
The movement points that are needed to build this object.
Definition: objecttype.h:113
GameActionID getID() const
State getState() const
Definition: command.h:125
vector< IntRange > objectsRemovable
the ids of objects this unit can remove
Definition: vehicletype.h:236
void read(tnstream &stream)
Definition: typen.h:213
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
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
int basicjamming_abs
basicjamming_abs replaces the current basicjamming of the field by a new one. A value < 0 won't affect...
Definition: objecttype.h:91
int getWeather()
the weather that is on this field
Definition: mapfield.cpp:370
void setTarget(const MapCoordinate &target, int objectID)
static const int putObjectCommandVersion
int remove_movecost
The movement points that are needed to remove this object.
Definition: objecttype.h:116
bool fieldvisiblenow(const MapField *pe, Vehicle *veh, int player)
{@
Definition: spfst.cpp:399
void writeData(tnstream &stream) const
Resources buildcost
The resources required to construct the object with a unit; Note that units usually don't have any en...
Definition: objecttype.h:107
#define maxmalq
Constants that specify the layout of ASC.
Definition: typen.h:429
ActionResult execute(const Context &context)
Definition: action.cpp:41
void write(tnstream &stream) const
Definition: typen.h:212
const set< int > & getCreatableObjects(const MapCoordinate &pos)
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
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
const int maxViewRange
Definition: typen.h:558
const FieldModification & getFieldModification(int weather) const
Definition: objecttype.cpp:72
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
MapDisplayInterface * display
Definition: context.h:39
TechAdapterDependency techDependency
Definition: objecttype.h:142
TerrainBits bdt
the terraintype properties. They determine which units can move over the field. This variable is reca...
Definition: mapfield.h:161
vector< MapCoordinate > getFields()
int groupID
the group ID allows units to specify whole groups of objects to be buildable / removable without spec...
Definition: objecttype.h:41
static bool avail(Vehicle *eht)
int & resource(int type)
Definition: typen.h:105
int viewbonus_abs
units standing on this object will get a bonus to their view
Definition: objecttype.h:96
const VehicleType * typ
Definition: vehicle.h:83
ASCString getDescription() const
bool attacked
did the unit already attack this turn
Definition: vehicle.h:109
Building * building
Definition: mapfield.h:102
vector< IntRange > objectGroupsBuildable
the group-ids of objects this unit can construct
Definition: vehicletype.h:239
void readData(tnstream &stream)
Definition: unitcommand.cpp:52
GameMap * getMap() const
ASCString getCommandString() const
ActionResult go(const Context &context)
Resources are basically the currency of ASC.
Definition: typen.h:97
bool available(const Research &research) const
Definition: research.cpp:412
int basicjamming_plus
this is added to the current basicjamming of the field to form the new jamming.
Definition: objecttype.h:89
ObjectType * getobjecttype_byid(int id)
Definition: gamemap.cpp:1783
Resources removecost
The resources required to remove the object with a unit; Note that units usually don't have any energ...
Definition: objecttype.h:110
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 readData(tnstream &stream)
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
Loki::Functor< void, LOKI_TYPELIST_1(const MapCoordinate &) > FieldIterationFunctor
Definition: mapalgorithms.h:43
ActionResult searchFields()
const Vehicle * getUnit() const
Definition: unitcommand.cpp:26
MapField * getField(int x, int y)
Definition: gamemap.h:465
ASCString name
The name of the object.
Definition: objecttype.h:122