00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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";
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
00205
00206
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 }