00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "destructbuildingcommand.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 "../containercontrols.h"
00033 #include "changeunitproperty.h"
00034 #include "spawnbuilding.h"
00035 #include "changeunitmovement.h"
00036 #include "consumeresource.h"
00037 #include "destructcontainer.h"
00038
00039
00040
00041 bool DestructBuildingCommand :: avail ( const Vehicle* eht )
00042 {
00043 if ( !eht )
00044 return false;
00045
00046 if ( eht->attacked == false && !eht->hasMoved() )
00047 if ( eht->getOwner() == eht->getMap()->actplayer )
00048 if ( eht->typ->hasFunction( ContainerBaseType::ConstructBuildings ) || !eht->typ->buildingsBuildable.empty() )
00049 if ( eht->getTank().fuel >= destruct_building_fuel_usage * eht->typ->fuelConsumption )
00050 return true;
00051
00052 return false;
00053 }
00054
00055
00056 DestructBuildingCommand :: DestructBuildingCommand ( Vehicle* container )
00057 : UnitCommand ( container )
00058 {
00059
00060 }
00061
00062 Resources DestructBuildingCommand::getDestructionCost( const Building* bld) const
00063 {
00064 Resources r;
00065 r.material = - bld->typ->productionCost.material * (100 - bld->damage) / destruct_building_material_get / 100;
00066 r.fuel = destruct_building_fuel_usage * getUnit()->typ->fuelConsumption;
00067 return r;
00068 }
00069
00070
00071 vector<MapCoordinate> DestructBuildingCommand::getFields()
00072 {
00073 vector<MapCoordinate> fields;
00074 Vehicle* veh = getUnit();
00075 for ( int d = 0; d < 6; ++d ) {
00076 MapCoordinate pos = getNeighbouringFieldCoordinate( veh->getPosition(), d );
00077 MapField* fld = getMap()->getField(pos);
00078 if ( fld )
00079 if ( fld->building && getheightdelta( getFirstBit(veh->height), getFirstBit(fld->building->typ->height)) == 0 && !fld->building->typ->buildingNotRemovable )
00080 fields.push_back( pos );
00081 }
00082
00083 return fields;
00084 }
00085
00086 bool DestructBuildingCommand :: isFieldUsable( const MapCoordinate& pos )
00087 {
00088 vector<MapCoordinate> fields = getFields();
00089 return find( fields.begin(), fields.end(), pos ) != fields.end() ;
00090 }
00091
00092
00093 void DestructBuildingCommand :: setTargetPosition( const MapCoordinate& pos )
00094 {
00095 this->target = pos;
00096 MapField* fld = getMap()->getField(target);
00097
00098 if ( !fld )
00099 throw ActionResult(21002);
00100
00101 setState( SetUp );
00102
00103 }
00104
00105
00106
00107 ActionResult DestructBuildingCommand::go ( const Context& context )
00108 {
00109 if ( getState() != SetUp )
00110 return ActionResult(22000);
00111
00112
00113 Building* building = getMap()->getField( target )->building;
00114 if ( !building )
00115 return ActionResult(22502);
00116
00117 const BuildingType* buildingType = building->typ;
00118
00119 Resources cost = getDestructionCost( building );
00120
00121 auto_ptr<DestructContainer> dc ( new DestructContainer( building, true ));
00122 ActionResult res = dc->execute( context );
00123 if ( res.successful() )
00124 dc.release();
00125 else
00126 return res;
00127
00128 auto_ptr<ConsumeResource> cr ( new ConsumeResource( getUnit(), cost ));
00129 res = cr->execute( context );
00130 if ( res.successful() )
00131 cr.release();
00132 else
00133 return res;
00134
00135 auto_ptr<ChangeUnitMovement> cum ( new ChangeUnitMovement( getUnit(), 0 ));
00136 res = cum->execute( context );
00137 if ( res.successful() )
00138 cum.release();
00139 else
00140 return res;
00141
00142 auto_ptr<ChangeUnitProperty> cup ( new ChangeUnitProperty( getUnit(), ChangeUnitProperty::AttackedFlag, 1 ));
00143 res = cup->execute( context );
00144 if ( res.successful() )
00145 cup.release();
00146 else
00147 return res;
00148
00149 evaluateviewcalculation( getMap(), target, buildingType->view, 0, false, &context );
00150
00151
00152 if ( context.display )
00153 context.display->repaintDisplay();
00154
00155 return ActionResult(0);
00156 }
00157
00158
00159
00160 static const int DestructBuildingCommandVersion = 1;
00161
00162 void DestructBuildingCommand :: readData ( tnstream& stream )
00163 {
00164 UnitCommand::readData( stream );
00165 int version = stream.readInt();
00166 if ( version > DestructBuildingCommandVersion )
00167 throw tinvalidversion ( "DestructBuildingCommand", DestructBuildingCommandVersion, version );
00168 target.read( stream );
00169 }
00170
00171 void DestructBuildingCommand :: writeData ( tnstream& stream ) const
00172 {
00173 UnitCommand::writeData( stream );
00174 stream.writeInt( DestructBuildingCommandVersion );
00175 target.write( stream );
00176 }
00177
00178
00179
00180 ASCString DestructBuildingCommand :: getCommandString() const
00181 {
00182 ASCString c;
00183 c.format("unitDestructBuilding ( map, %d, asc.MapCoordinate(%d, %d) )", getUnitID(), target.x, target.y );
00184 return c;
00185 }
00186
00187 GameActionID DestructBuildingCommand::getID() const
00188 {
00189 return ActionRegistry::DestructBuildingCommand;
00190 }
00191
00192 ASCString DestructBuildingCommand::getDescription() const
00193 {
00194 ASCString s = "Destruct building at "+ target.toString() ;
00195
00196
00197 if ( getUnit() ) {
00198 s += " with " + getUnit()->getName();
00199 }
00200 return s;
00201 }
00202
00203 namespace
00204 {
00205 const bool r1 = registerAction<DestructBuildingCommand> ( ActionRegistry::DestructBuildingCommand );
00206 }
00207