00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "putminecommand.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 #include "../viewcalculation.h"
00033
00034 #include "changeunitmovement.h"
00035 #include "spawnmine.h"
00036 #include "consumeammo.h"
00037 #include "removemine.h"
00038
00039 bool PutMineCommand :: avail ( Vehicle* unit )
00040 {
00041 if ( unit )
00042 if (unit->getOwner() == unit->getMap()->actplayer)
00043 if (unit->typ->hasFunction( ContainerBaseType::PlaceMines ) )
00044 if ( !unit->attacked )
00045 return true;
00046 return false;
00047 }
00048
00049
00050 PutMineCommand :: PutMineCommand ( Vehicle* unit )
00051 : UnitCommand ( unit ), mode(Build)
00052 {
00053 object = cmantitankmine;
00054 putMines = false;
00055 removeMines = false;
00056
00057 weaponNum = -1;
00058
00059 for ( int i = 0; i < unit->typ->weapons.count; i++)
00060 if ((unit->typ->weapons.weapon[i].getScalarWeaponType() == cwminen) && unit->typ->weapons.weapon[i].shootable() && (unit->typ->weapons.weapon[i].sourceheight & unit->height) ) {
00061 if ( !unit->typ->hasFunction( ContainerBaseType::NoMineRemoval ))
00062 removeMines = true;
00063
00064 if (unit->ammo[i] > 0)
00065 putMines = true;
00066
00067 weaponNum = i;
00068 }
00069 }
00070
00071
00072 vector<MapCoordinate> PutMineCommand::getFields()
00073 {
00074 vector<MapCoordinate> fields = objectsRemovable;
00075
00076 for ( map<MapCoordinate,vector<MineTypes> > ::iterator i = objectsCreatable.begin(); i != objectsCreatable.end(); ++i )
00077 if ( find(fields.begin(), fields.end(), i->first) == fields.end() )
00078 fields.push_back ( i->first );
00079 return fields;
00080 }
00081
00082 const vector<MineTypes>& PutMineCommand::getCreatableMines( const MapCoordinate& pos )
00083 {
00084 return objectsCreatable[pos];
00085 }
00086
00087 bool PutMineCommand::getRemovableMines( const MapCoordinate& pos )
00088 {
00089 return find( objectsRemovable.begin(), objectsRemovable.end(), pos) != objectsRemovable.end();
00090 }
00091
00092 ActionResult PutMineCommand::searchFields()
00093 {
00094 if ( !getUnit() )
00095 return ActionResult(201);
00096
00097 if (getUnit()->getMovement() < mineputmovedecrease)
00098 return ActionResult( 119 );
00099
00100
00101 objectsCreatable.clear();
00102 objectsRemovable.clear();
00103
00104 if ( weaponNum >= 0 )
00105 circularFieldIterator( getMap(), getUnit()->getPosition(), getUnit()->typ->weapons.weapon[weaponNum].maxdistance/10, getUnit()->typ->weapons.weapon[weaponNum].mindistance/10, FieldIterationFunctor( this, &PutMineCommand::fieldChecker ));
00106
00107 if ( objectsRemovable.size() + objectsCreatable.size() ) {
00108 setState(Evaluated);
00109 return ActionResult(0);
00110 } else
00111 return ActionResult(21504);
00112 }
00113
00114 void PutMineCommand :: fieldChecker( const MapCoordinate& pos )
00115 {
00116 MapField* fld = getMap()->getField(pos);
00117 if ( !fld )
00118 return;
00119
00120 if ( fld->vehicle || fld->building )
00121 return;
00122
00123 if ( fieldvisiblenow( getMap()->getField(pos)) ) {
00124
00125 if ( removeMines && !fld->mines.empty() && fld->getVisibility( getUnit()->getOwner() ) == visible_all) {
00126 objectsRemovable.push_back( pos );
00127 }
00128
00129 if (putMines && (fld->mines.empty() || fld->mineowner() == getUnit()->getOwner()) && fld->mines.size() < getMap()->getgameparameter ( cgp_maxminesonfield )) {
00130 if ( (fld->bdt & (getTerrainBitType( cbwater ).flip())).any() ) {
00131 objectsCreatable[pos].push_back( cmantipersonnelmine );
00132 objectsCreatable[pos].push_back( cmantitankmine );
00133 }
00134 if ( (fld->typ->art & getTerrainBitType(cbwater2)).any()
00135 || (fld->typ->art & getTerrainBitType(cbwater3)).any() )
00136 objectsCreatable[pos].push_back( cmmooredmine );
00137
00138 if ( (fld->bdt & getTerrainBitType(cbwater0)).any()
00139 || (fld->bdt & getTerrainBitType(cbwater1)).any()
00140 || (fld->bdt & getTerrainBitType(cbwater2)).any()
00141 || (fld->bdt & getTerrainBitType(cbwater3)).any()
00142 || (fld->bdt & getTerrainBitType(cbriver)).any() )
00143 objectsCreatable[pos].push_back( cmfloatmine );
00144
00145 }
00146 }
00147 }
00148
00149
00150 void PutMineCommand :: setCreationTarget( const MapCoordinate& target, MineTypes mineType )
00151 {
00152 MapField* fld = getMap()->getField(target);
00153
00154 if( !fld )
00155 throw ActionResult(21002);
00156
00157 this->target = target;
00158 this->object = mineType;
00159
00160 mode = Build;
00161
00162
00163 setState( SetUp );
00164 }
00165
00166 void PutMineCommand :: setRemovalTarget( const MapCoordinate& target )
00167 {
00168 MapField* fld = getMap()->getField(target);
00169
00170 if( !fld )
00171 throw ActionResult(21002);
00172
00173 this->target = target;
00174 mode = Remove;
00175
00176 setState( SetUp );
00177 }
00178
00179
00180 ActionResult PutMineCommand::go ( const Context& context )
00181 {
00182 MapCoordinate targetPosition;
00183
00184 if ( getState() != SetUp )
00185 return ActionResult(22000);
00186
00187 searchFields();
00188
00189 int strength = getUnit()->typ->weapons.weapon[weaponNum].maxstrength;
00190
00191 ActionResult res(0);
00192 if ( mode == Build ) {
00193 res = (new SpawnMine(getMap(), target, object, getUnit()->getOwner(), MineBasePunch[object-1] * strength / 64 ))->execute( context );
00194
00195 computeview( getMap(), 0, false, &context );
00196
00197 if ( res.successful() )
00198 res = (new ConsumeAmmo( getUnit(), getUnit()->typ->weapons.weapon[weaponNum].getScalarWeaponType(), weaponNum, 1 ))->execute(context);
00199 } else
00200 res = (new RemoveMine(getMap(), target, 0 ))->execute( context );
00201
00202
00203 if ( res.successful() )
00204 res = (new ChangeUnitMovement( getUnit(), mineputmovedecrease, true ))->execute(context);
00205
00206 if ( res.successful() )
00207 setState( Finished );
00208 else
00209 setState( Failed );
00210
00211 if( context.display && fieldvisiblenow( getMap()->getField(target), context.viewingPlayer ))
00212 context.display->displayMap();
00213 return res;
00214
00215 }
00216
00217 static const int putObjectCommandVersion = 1;
00218
00219 void PutMineCommand :: readData ( tnstream& stream )
00220 {
00221 UnitCommand::readData( stream );
00222 int version = stream.readInt();
00223 if ( version > putObjectCommandVersion )
00224 throw tinvalidversion ( "PutMineCommand", putObjectCommandVersion, version );
00225 target.read( stream );
00226 object = (MineTypes) stream.readInt();
00227 mode = (Mode) stream.readInt();
00228 putMines = stream.readInt();
00229 removeMines = stream.readInt();;
00230 weaponNum = stream.readInt();
00231
00232 }
00233
00234 void PutMineCommand :: writeData ( tnstream& stream ) const
00235 {
00236 UnitCommand::writeData( stream );
00237 stream.writeInt( putObjectCommandVersion );
00238 target.write( stream );
00239 stream.writeInt( object );
00240 stream.writeInt( mode );
00241 stream.writeInt( putMines );
00242 stream.writeInt( removeMines );
00243 stream.writeInt( weaponNum );
00244
00245 }
00246
00247 ASCString PutMineCommand :: getCommandString() const
00248 {
00249 ASCString c;
00250 if ( mode == Build )
00251 c.format("unitPutMine ( map, %d, asc.MapCoordinate(%d, %d), %d )", getUnitID(), target.x, target.y, (int)object );
00252 else
00253 c.format("unitRemoveMine ( map, %d, asc.MapCoordinate(%d, %d) )", getUnitID(), target.x, target.y );
00254 return c;
00255
00256 }
00257
00258 GameActionID PutMineCommand::getID() const
00259 {
00260 return ActionRegistry::PutMineCommand;
00261 }
00262
00263 ASCString PutMineCommand::getDescription() const
00264 {
00265 ASCString s = "Put Mine";
00266 if ( getUnit() ) {
00267 s += " by " + getUnit()->getName();
00268 }
00269 s += " on " + target.toString();
00270 return s;
00271 }
00272
00273 namespace
00274 {
00275 const bool r1 = registerAction<PutMineCommand> ( ActionRegistry::PutMineCommand );
00276 }
00277