destructcontainer.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 "destructcontainer.h"
00023 #include "spawnobject.h"
00024 #include "action-registry.h"
00025 
00026 #include "../vehicle.h"
00027 #include "../gamemap.h"
00028 #include "../viewcalculation.h"
00029      
00030 DestructContainer::DestructContainer( ContainerBase* container, bool suppressWreckage )
00031    : ContainerAction( container ), fieldRegistration( NONE ), unitBuffer(NULL), hostingCarrier(0), cargoSlot(-1), hadViewOnMap(true)
00032 {
00033    building = container->isBuilding();
00034    this->suppressWreckage = suppressWreckage;
00035 }
00036       
00037       
00038 ASCString DestructContainer::getDescription() const
00039 {
00040    return "Destruct container"; // with ID " + ASCString::toString(unitID);
00041 }
00042       
00043 
00044 static const int destructContainerStreamVersion = 5;
00045       
00046 void DestructContainer::readData ( tnstream& stream ) 
00047 {
00048    int version = stream.readInt();
00049    if ( version < 1 || version > destructContainerStreamVersion )
00050       throw tinvalidversion ( "DestructUnit", destructContainerStreamVersion, version );
00051    
00052    ContainerAction::readData( stream );
00053    building = stream.readInt();
00054    
00055    if ( stream.readInt() ) {
00056       unitBuffer = new MemoryStreamStorage();
00057       unitBuffer->readfromstream( &stream );  
00058    } else
00059       unitBuffer = NULL;
00060 
00061    if ( version >= 2 )
00062       fieldRegistration = (FieldRegistration) stream.readInt();
00063    
00064    if ( version >= 3 ) {
00065       hostingCarrier = stream.readInt();
00066       cargoSlot = stream.readInt();
00067    }
00068    
00069    if ( version >= 4 )
00070       suppressWreckage = stream.readInt();
00071    else
00072       suppressWreckage = false;
00073    
00074    if ( version >= 5 )
00075       hadViewOnMap = stream.readInt();
00076    else
00077       hadViewOnMap = true;
00078 };
00079       
00080       
00081 void DestructContainer::writeData ( tnstream& stream ) const
00082 {
00083    stream.writeInt( destructContainerStreamVersion );
00084    
00085    ContainerAction::writeData( stream );
00086    stream.writeInt( building );
00087    if ( unitBuffer ) {
00088       stream.writeInt( 1 );
00089       unitBuffer->writetostream( &stream );
00090    } else
00091       stream.writeInt( 0 );
00092 
00093    stream.writeInt( (int)fieldRegistration );
00094    stream.writeInt( hostingCarrier );
00095    stream.writeInt( cargoSlot );
00096    stream.writeInt( suppressWreckage );
00097    stream.writeInt( hadViewOnMap );
00098 };
00099 
00100 
00101 GameActionID DestructContainer::getID() const
00102 {
00103    return ActionRegistry::DestructContainer;
00104 }
00105 
00106 ActionResult DestructContainer::runAction( const Context& context )
00107 {
00108    ContainerBase* container = getContainer();
00109 
00110    unitBuffer = new MemoryStreamStorage();
00111    MemoryStream memstream( unitBuffer, tnstream::writing );
00112    container->write( memstream );
00113    
00114    Vehicle* veh = dynamic_cast<Vehicle*>(container);
00115    if ( veh ) {
00116       MapField* fld = getMap()->getField(veh->getPosition());
00117 
00118       if ( fld->vehicle == veh )
00119          fieldRegistration = FIRST;
00120       else if ( fld->secondvehicle == veh )
00121          fieldRegistration = SECOND;
00122       else if ( veh->getCarrier() ) {
00123          fieldRegistration = CARRIER;
00124          hostingCarrier = veh->getCarrier()->getIdentification();
00125          const ContainerBase::Cargo& cargo = veh->getCarrier()->getCargo();
00126          ContainerBase::Cargo::const_iterator pos = find( cargo.begin(), cargo.end(), veh );
00127          if ( pos == cargo.end() )
00128             throw ActionResult( 22200, veh->getCarrier() );
00129          cargoSlot = pos - cargo.begin();
00130       }
00131       
00132       if ( !veh->typ->wreckageObject.empty() && getMap()->state != GameMap::Destruction && !suppressWreckage ) {
00133          if ( fieldRegistration == FIRST || fieldRegistration == SECOND ) {
00134             for ( vector<int>::const_iterator i = veh->typ->wreckageObject.begin(); i != veh->typ->wreckageObject.end(); ++i ) {
00135                ObjectType* obj = getMap()->getobjecttype_byid( *i );
00136                if ( obj ) {
00137                   GameAction* o = new SpawnObject( getMap(), veh->getPosition(), *i, veh->direction );
00138                   o->execute( context ); 
00139                }
00140             }
00141          }
00142       }
00143    }
00144       
00145    Building* bld = dynamic_cast<Building*>(container);
00146    
00147    if ( bld && !suppressWreckage ) {
00148       bld->unchainbuildingfromfield();
00149       for (int i = 0; i < BuildingType::xdimension; i++)
00150          for (int j = 0; j < BuildingType::ydimension; j++)
00151             if ( bld->typ->fieldExists ( BuildingType::LocalCoordinate(i,j) ) ) {
00152                MapField* fld = bld->getField( BuildingType::LocalCoordinate(i,j) );
00153                if ( fld ) {
00154                   typedef BuildingType::DestructionObjects::const_iterator J;
00155                   pair<J,J> b = bld->typ->destructionObjects.equal_range(BuildingType::LocalCoordinate(i,j));
00156                   for ( J o = b.first; o != b.second; ++o)
00157                      (new SpawnObject( getMap(), bld->getFieldCoordinates(BuildingType::LocalCoordinate(i,j)), o->second  ))->execute( context );
00158                }
00159             }
00160    }
00161    
00162    hadViewOnMap = false;
00163    if( fieldRegistration != CARRIER ) {
00164       if ( veh && veh->isViewing() ) {
00165          veh->removeview();
00166          hadViewOnMap = true;
00167       } else if ( bld && bld->isViewing() ) {
00168          bld->removeview();
00169          hadViewOnMap = true;
00170       } 
00171    }
00172    
00173    MapCoordinate pos = container->getPosition();
00174    int viewrange = container->baseType->view;
00175    
00176    delete container;
00177    
00178    evaluateviewcalculation( getMap(), pos, viewrange, 0, false, &context );
00179    
00180    
00181    return ActionResult(0);
00182 }
00183 
00184 
00185 ActionResult DestructContainer::undoAction( const Context& context )
00186 {
00187    MemoryStream memstream( unitBuffer, tnstream::reading );
00188    if ( building ) {
00189       Building* bld = Building::newFromStream( getMap(), memstream );
00190       bld->chainbuildingtofield( bld->getEntry() );
00191       if ( bld->getOwner() < bld->getMap()->getPlayerCount() && hadViewOnMap )
00192          bld->addview();
00193    } else {
00194       Vehicle* veh = Vehicle::newFromStream( getMap(), memstream );
00195 
00196       if ( fieldRegistration == FIRST )
00197          getMap()->getField( veh->getPosition() )->vehicle = veh;
00198       else if ( fieldRegistration == CARRIER ) {
00199          ContainerBase* carrier = getMap()->getContainer( hostingCarrier );  
00200          carrier->addToCargo( veh, cargoSlot );
00201       }
00202 
00203       /*
00204       SECOND is not a permanent registration, so we don't redo it
00205       if ( fieldRegistration == SECOND )
00206          getMap()->getField( veh->getPosition() )->vehicle = veh;
00207       */
00208         
00209       if ( fieldRegistration != CARRIER && hadViewOnMap )
00210          veh->addview();
00211    }
00212    
00213    return ActionResult(0);
00214 }
00215 
00216 DestructContainer::~DestructContainer()
00217 {
00218    delete unitBuffer;  
00219 }
00220 
00221 
00222 namespace {
00223    const bool r1 = registerAction<DestructContainer> ( ActionRegistry::DestructContainer );
00224 }

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