putobjectcommand.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 "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 //            && !getheightdelta ( getFirstBit( actvehicle->height), getFirstBit(objtype->getEffectiveHeight())) ) {
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 //          &&  !getheightdelta ( getFirstBit( actvehicle->height), getFirstBit(objtype->getEffectiveHeight())) ) {
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 //  if ( getState() == Evaluated ) {
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 

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