00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "putobjectcommand.h"
00023
00024 #include "../vehicle.h"
00025 #include "../mapfield.h"
00026 #include "../gamemap.h"
00027 #include "../viewcalculation.h"
00028 #include "../spfst.h"
00029 #include "../mapdisplayinterface.h"
00030 #include "action-registry.h"
00031 #include "../itemrepository.h"
00032
00033 #include "removeobject.h"
00034 #include "spawnobject.h"
00035 #include "consumeresource.h"
00036 #include "changeunitmovement.h"
00037
00038 bool PutObjectCommand :: avail ( Vehicle* eht )
00039 {
00040
00041 if ( eht )
00042 if (eht->getOwner() == eht->getMap()->actplayer)
00043 if ( eht->typ->objectsBuildable.size() || eht->typ->objectsRemovable.size() || eht->typ->objectGroupsBuildable.size() || eht->typ->objectGroupsRemovable.size())
00044 if ( !eht->attacked )
00045 return true;
00046 return false;
00047 }
00048
00049
00050 PutObjectCommand :: PutObjectCommand ( Vehicle* unit )
00051 : UnitCommand ( unit ), object(-1),mode(Build)
00052 {
00053
00054 }
00055
00056
00057 vector<MapCoordinate> PutObjectCommand::getFields()
00058 {
00059 vector<MapCoordinate> fields;
00060 for ( map<MapCoordinate,vector<int> > ::iterator i = objectsCreatable.begin(); i != objectsCreatable.end(); ++i )
00061 fields.push_back ( i->first );
00062
00063 for ( map<MapCoordinate,vector<int> > ::iterator i = objectsRemovable.begin(); i != objectsRemovable.end(); ++i )
00064 if ( find(fields.begin(), fields.end(), i->first) == fields.end() )
00065 fields.push_back ( i->first );
00066 return fields;
00067 }
00068
00069 const vector<int>& PutObjectCommand::getCreatableObjects( const MapCoordinate& pos )
00070 {
00071 return objectsCreatable[pos];
00072 }
00073
00074 const vector<int>& PutObjectCommand::getRemovableObjects( const MapCoordinate& pos )
00075 {
00076 return objectsRemovable[pos];
00077 }
00078
00079 ActionResult PutObjectCommand::searchFields()
00080 {
00081 if ( !getUnit() )
00082 return ActionResult(201);
00083
00084
00085 objectsCreatable.clear();
00086 objectsRemovable.clear();
00087
00088 circularFieldIterator( getMap(), getUnit()->getPosition(), 1, 1, FieldIterationFunctor( this, &PutObjectCommand::fieldChecker ));
00089
00090 if ( objectsRemovable.size() + objectsCreatable.size() ) {
00091 setState(Evaluated);
00092 return ActionResult(0);
00093 } else
00094 return ActionResult(21504);
00095 }
00096
00097 bool PutObjectCommand::checkObject( MapField* fld, ObjectType* objtype, Mode mode )
00098 {
00099 if ( !objtype || !fld )
00100 return false;
00101
00102 Vehicle* veh = getUnit();
00103
00104 if ( mode == Build ) {
00105 if ( objtype->getFieldModification(fld->getWeather()).terrainaccess.accessible( fld->bdt ) > 0
00106 && !fld->checkForObject ( objtype )
00107 && objtype->techDependency.available(getMap()->player[veh->getOwner()].research) ){
00108
00109
00110 if ( veh->getResource(objtype->buildcost, true) == objtype->buildcost && veh->getMovement() >= objtype->build_movecost )
00111 return true;
00112 }
00113 } else {
00114 if ( fld->checkForObject ( objtype ) ) {
00115
00116 Resources r = objtype->removecost;
00117 for ( int i = 0; i <3; ++i )
00118 if ( r.resource(i) < 0 )
00119 r.resource(i) = 0;
00120
00121 if ( veh->getResource(r, true) == r && veh->getMovement() >= objtype->remove_movecost )
00122 return true;
00123 }
00124 }
00125 return false;
00126 }
00127
00128
00129 void PutObjectCommand :: fieldChecker( const MapCoordinate& pos )
00130 {
00131 MapField* fld = getMap()->getField(pos);
00132 if ( !fld )
00133 return;
00134
00135 if ( fld->vehicle || fld->building )
00136 return;
00137
00138 if ( fieldvisiblenow( getMap()->getField(pos)) ) {
00139
00140 Vehicle* veh = getUnit();
00141
00142 for ( int i = 0; i < veh->typ->objectsBuildable.size(); i++ )
00143 for ( int j = veh->typ->objectsBuildable[i].from; j <= veh->typ->objectsBuildable[i].to; j++ )
00144 if ( checkObject( fld, getMap()->getobjecttype_byid ( j ), Build ))
00145 objectsCreatable[pos].push_back( j );
00146
00147
00148 for ( int i = 0; i < veh->typ->objectGroupsBuildable.size(); i++ )
00149 for ( int j = veh->typ->objectGroupsBuildable[i].from; j <= veh->typ->objectGroupsBuildable[i].to; j++ )
00150 for ( int k = 0; k < objectTypeRepository.getNum(); k++ ) {
00151 ObjectType* objtype = objectTypeRepository.getObject_byPos ( k );
00152 if ( objtype->groupID == j )
00153 if ( checkObject( fld, objtype, Build ))
00154 if ( find ( objectsCreatable[pos].begin(), objectsCreatable[pos].end(), objtype->id) == objectsCreatable[pos].end() )
00155 objectsCreatable[pos].push_back( objtype->id );
00156 }
00157
00158 for ( int i = 0; i < veh->typ->objectsRemovable.size(); i++ )
00159 for ( int j = veh->typ->objectsRemovable[i].from; j <= veh->typ->objectsRemovable[i].to; j++ )
00160 if ( checkObject( fld, getMap()->getobjecttype_byid ( j ), Remove ))
00161 objectsRemovable[pos].push_back( j );
00162
00163
00164 for ( int i = 0; i < veh->typ->objectGroupsRemovable.size(); i++ )
00165 for ( int j = veh->typ->objectGroupsRemovable[i].from; j <= veh->typ->objectGroupsRemovable[i].to; j++ )
00166 for ( int k = 0; k < objectTypeRepository.getNum(); k++ ) {
00167 ObjectType* objtype = objectTypeRepository.getObject_byPos ( k );
00168 if ( objtype->groupID == j )
00169 if ( checkObject( fld, objtype, Remove ))
00170 if ( find ( objectsRemovable[pos].begin(), objectsRemovable[pos].end(), objtype->id) == objectsRemovable[pos].end() )
00171 objectsRemovable[pos].push_back( objtype->id );
00172 }
00173
00174 }
00175 }
00176
00177
00178 void PutObjectCommand :: setTarget( const MapCoordinate& target, int objectID )
00179 {
00180
00181
00182 this->target = target;
00183 this->object = objectID;
00184
00185 MapField* fld = getMap()->getField(target);
00186
00187 if( !fld )
00188 throw ActionResult(21002);
00189
00190 ObjectType* obj = getMap()->getobjecttype_byid( objectID);
00191 if( !obj )
00192 throw ActionResult(21501);
00193
00194 if ( !fld->checkForObject( obj ))
00195 mode = Build;
00196 else
00197 mode = Remove;
00198
00199 setState( SetUp );
00200
00201 }
00202
00203 ActionResult PutObjectCommand::go ( const Context& context )
00204 {
00205 MapCoordinate targetPosition;
00206
00207 if ( getState() != SetUp )
00208 return ActionResult(22000);
00209
00210 if ( !avail( getUnit() ) )
00211 return ActionResult(21506);
00212
00213 searchFields();
00214
00215 vector<int>* objects;
00216 if ( mode == Build ) {
00217 objects = &objectsCreatable[target];
00218 } else {
00219 objects = &objectsRemovable[target];
00220 }
00221
00222 if ( find( objects->begin(), objects->end(), object ) == objects->end() )
00223 return ActionResult( 21507 );
00224
00225
00226 ObjectType* obj = getMap()->getobjecttype_byid( object );
00227
00228 RecalculateAreaView rav ( getMap(), target, maxViewRange / maxmalq + 1, &context );
00229
00230
00231 bool objectAffectsVisibility = obj->basicjamming_plus || obj->viewbonus_plus || obj->viewbonus_abs != -1 || obj->basicjamming_abs != -1;
00232 if ( objectAffectsVisibility )
00233 rav.removeView();
00234
00235 ActionResult res(0);
00236 if ( mode == Build )
00237 res = (new SpawnObject(getMap(), target, object ))->execute( context );
00238 else
00239 res = (new RemoveObject(getMap(), target, object ))->execute( context );
00240
00241
00242 if ( objectAffectsVisibility )
00243 rav.addView();
00244
00245 if ( res.successful() )
00246 res = (new ConsumeResource( getUnit(), mode==Build ? obj->buildcost : obj->removecost ))->execute(context);
00247
00248 if ( res.successful() )
00249 res = (new ChangeUnitMovement( getUnit(), mode==Build ? obj->build_movecost : obj->remove_movecost, true ))->execute(context);
00250
00251 if ( res.successful() ) {
00252 if ( context.display )
00253 context.display->repaintDisplay();
00254 setState( Finished );
00255 } else
00256 setState( Failed );
00257 return res;
00258
00259 }
00260
00261 static const int putObjectCommandVersion = 1;
00262
00263 void PutObjectCommand :: readData ( tnstream& stream )
00264 {
00265 UnitCommand::readData( stream );
00266 int version = stream.readInt();
00267 if ( version > putObjectCommandVersion )
00268 throw tinvalidversion ( "PutObjectCommand", putObjectCommandVersion, version );
00269 target.read( stream );
00270 object = stream.readInt();
00271 mode = (Mode) stream.readInt();
00272 }
00273
00274 void PutObjectCommand :: writeData ( tnstream& stream ) const
00275 {
00276 UnitCommand::writeData( stream );
00277 stream.writeInt( putObjectCommandVersion );
00278 target.write( stream );
00279 stream.writeInt( object );
00280 stream.writeInt( mode );
00281 }
00282
00283 ASCString PutObjectCommand :: getCommandString() const
00284 {
00285 ASCString c;
00286 if ( mode == Build )
00287 c.format("unitPutObject ( map, %d, asc.MapCoordinate( %d, %d), %d )", getUnitID(), target.x, target.y, object );
00288 else
00289 c.format("unitRemoveObject ( map, %d, asc.MapCoordinate( %d, %d), %d )", getUnitID(), target.x, target.y, object );
00290 return c;
00291
00292 }
00293
00294 GameActionID PutObjectCommand::getID() const
00295 {
00296 return ActionRegistry::PutObjectCommand;
00297 }
00298
00299 ASCString PutObjectCommand::getDescription() const
00300 {
00301 ASCString s;
00302
00303 if ( mode == Build )
00304 s = "Put ";
00305 else
00306 s = "Remove ";
00307
00308 const ObjectType* obj = getMap()->getobjecttype_byid( object );
00309 if ( obj )
00310 s += obj->name;
00311 else
00312 s += "object";
00313
00314 if ( getUnit() ) {
00315 s += " with " + getUnit()->getName();
00316 }
00317 s += " at " + target.toString();
00318 return s;
00319 }
00320
00321 namespace
00322 {
00323 const bool r1 = registerAction<PutObjectCommand> ( ActionRegistry::PutObjectCommand );
00324 }
00325