putminecommand.cpp

Go to the documentation of this file.
00001 /*
00002      This file is part of Advanced Strategic Command; http://www.asc-hq.de
00003      Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00004 
00005      This program is free software; you can redistribute it and/or modify
00006      it under the terms of the GNU General Public License as published by
00007      the Free Software Foundation; either version 2 of the License, or
00008      (at your option) any later version.
00009 
00010      This program is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013      GNU General Public License for more details.
00014 
00015      You should have received a copy of the GNU General Public License
00016      along with this program; see the file COPYING. If not, write to the
00017      Free Software Foundation, Inc., 59 Temple Place, Suite 330,
00018      Boston, MA  02111-1307  USA
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 

Generated on Mon May 21 01:26:36 2012 for Advanced Strategic Command by  doxygen 1.5.1