jumpdrivecommand.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 "jumpdrivecommand.h"
00023 
00024 #include "../vehicle.h"
00025 #include "../mapfield.h"
00026 #include "../gamemap.h"
00027 #include "../viewcalculation.h"
00028 #include "../spfst.h"
00029 #include "changeunitmovement.h"
00030 #include "../mapdisplayinterface.h"
00031 #include "action-registry.h"
00032 #include "../reactionfire.h"
00033 #include "../soundList.h"
00034 #include "consumeresource.h"
00035 #include "servicecommand.h"
00036 #include "unitfieldregistration.h"
00037 #include "changeunitproperty.h"
00038 
00039 ActionAvailability JumpDriveCommand :: available( const Vehicle* unit )
00040 {
00041    ActionAvailability avail;
00042    if ( !unit )
00043       return avail.set( ActionAvailability::notAtAll, "No unit selected");
00044    
00045    if ( !unit->typ->jumpDrive.height )
00046       return avail.set( ActionAvailability::notAtAll, "Unit has no jump drive");
00047    
00048    if ( unit->hasMoved() )
00049       avail.set( ActionAvailability::partially, "Unit has already moved" );
00050    
00051    if ( unit->attacked )
00052       avail.set( ActionAvailability::partially, "Unit has already attacked" );
00053    
00054    if ( (unit->reactionfire.getStatus() != Vehicle::ReactionFire::off) && !unit->typ->hasFunction(VehicleType::MoveWithReactionFire ) )
00055       avail.set( ActionAvailability::partially, "Unit has reaction fire enabled" );
00056    
00057    if ( !(unit->height & unit->typ->jumpDrive.height) ) 
00058       avail.set( ActionAvailability::partially, "Unit needs to be on this height: " + heightToString(unit->typ->jumpDrive.height)  );
00059    
00060    if ( unit->getResource( unit->typ->jumpDrive.consumption ) < unit->typ->jumpDrive.consumption ) 
00061       avail.set( ActionAvailability::partially, "Unit is missing resources. Required: " + unit->typ->jumpDrive.consumption.toString()  );
00062    
00063    return avail;
00064 }
00065 
00066 JumpDriveCommand :: JumpDriveCommand ( Vehicle* unit)
00067    : UnitCommand ( unit )
00068 {
00069 
00070 }
00071 
00072 
00073 bool JumpDriveCommand::fieldReachable( const MapCoordinate& dest )
00074 {
00075    MapField* fld = getMap()->getField( dest );
00076    if ( beeline( dest, getUnit()->getPosition()) <= getUnit()->typ->jumpDrive.maxDistance )
00077       if ( !fld->vehicle && !fld->building ) 
00078          if ( fieldvisiblenow( fld, getUnit()->getOwner() ))
00079             if ( getUnit()->typ->jumpDrive.targetterrain.accessible( fld->bdt ) > 0 ) 
00080                return true;
00081    
00082    return false;
00083 }
00084 
00085 
00086 vector<MapCoordinate> JumpDriveCommand::getDestinations()
00087 {
00088    vector<MapCoordinate> fields;
00089    
00090    if ( !available( getUnit() ).ready() )
00091       return fields;
00092      
00093    GameMap* gamemap = getMap();
00094     
00095    for ( int y = 0; y < gamemap->ysize; ++y )
00096       for (int x = 0; x < gamemap->xsize; ++x ) {
00097          MapCoordinate dest (x,y); 
00098          if ( fieldReachable( dest)) 
00099             fields.push_back( dest );
00100          
00101       }
00102   return fields;
00103 }
00104 
00105 void JumpDriveCommand::setDestination( const MapCoordinate& position )
00106 {
00107    if ( fieldReachable( position )) {
00108       destination = position;
00109       setState( SetUp );
00110    }
00111 }
00112 
00113 
00114 ActionResult JumpDriveCommand::go ( const Context& context )
00115 {
00116    if ( getState() != SetUp )
00117       return ActionResult(22000);
00118 
00119    Vehicle* unit = getUnit();
00120    
00121    if ( !available( unit ).ready() )
00122       return ActionResult( 22600 );
00123    
00124    if ( !fieldReachable( destination ))
00125       return ActionResult( 22601 );
00126    
00127    
00128    auto_ptr<ConsumeResource> cr ( new ConsumeResource( unit, unit->typ->jumpDrive.consumption ));
00129    ActionResult res = cr->execute( context );
00130    if ( !res.successful() )
00131       return res;
00132    else
00133       cr.release();
00134    
00135    auto_ptr<UnitFieldRegistration> ufr1 ( new UnitFieldRegistration( unit, unit->getPosition(), UnitFieldRegistration::RemoveView ));
00136    res = ufr1->execute( context );
00137    if ( !res.successful() )
00138       return res;
00139    else
00140       ufr1.release();
00141    
00142    auto_ptr<UnitFieldRegistration> ufr2 ( new UnitFieldRegistration( unit, unit->getPosition(), UnitFieldRegistration::UnregisterOnField ));
00143    res = ufr2->execute( context );
00144    if ( !res.successful() )
00145       return res;
00146    else
00147       ufr2.release();
00148    
00149    
00150    MapCoordinate3D dest3D (destination, unit->height );
00151 
00152    tsearchreactionfireingunits srfu( getMap() );
00153    srfu.init( unit , dest3D );
00154    
00155    
00156    auto_ptr<UnitFieldRegistration> ufr3( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::Position3D ));
00157    res = ufr3->execute( context );
00158    if ( !res.successful() )
00159       return res;
00160    else
00161       ufr3.release();
00162    
00163    auto_ptr<UnitFieldRegistration> ufr4 ( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::RegisterOnField ));
00164    res = ufr4->execute( context );
00165    if ( !res.successful() )
00166       return res;
00167    else
00168       ufr4.release();
00169    
00170    
00171    if ( context.display )
00172       context.display->playPositionalSound( dest3D, SoundList::getInstance().getSound( SoundList::jumpdrive ));
00173 
00174    auto_ptr<ChangeUnitMovement> cum ( new ChangeUnitMovement( unit, 0, false, ChangeUnitMovement::ALLFULL ));
00175    res = cum->execute( context );
00176    if ( !res.successful() )
00177       return res;
00178    else
00179       cum.release();
00180       
00181    auto_ptr<ChangeUnitProperty> cup ( new ChangeUnitProperty( unit, ChangeUnitProperty::AttackedFlag, 1 ));
00182    res = cup->execute( context );
00183    if ( !res.successful() )
00184       return res;
00185    else
00186       cup.release();
00187       
00188       
00189    auto_ptr<UnitFieldRegistration> ufr5( new UnitFieldRegistration( unit, dest3D, UnitFieldRegistration::AddView ));
00190    res = ufr5->execute( context );
00191    if ( !res.successful() )
00192       return res;
00193    else
00194       ufr5.release();
00195    
00196    computeview( getMap(), 0, false, &context );
00197    
00198 
00199    int unitOwner = unit->getOwner();
00200    srfu.checkfield( dest3D, unit, context );
00201    srfu.finalCheck( unitOwner, context );
00202 
00203    
00204    if ( context.display )
00205       context.display->repaintDisplay();
00206    
00207    if ( res.successful() )
00208       setState( Finished );
00209    else
00210       setState( Failed );
00211    
00212    return res;
00213 }
00214 
00215 
00216 
00217 static const int JumpDriveCommandVersion = 1;
00218 
00219 void JumpDriveCommand :: readData ( tnstream& stream )
00220 {
00221    UnitCommand::readData( stream );
00222    int version = stream.readInt();
00223    if ( version > JumpDriveCommandVersion )
00224       throw tinvalidversion ( "JumpDriveCommand", JumpDriveCommandVersion, version );
00225    destination.read( stream );   
00226 }
00227 
00228 void JumpDriveCommand :: writeData ( tnstream& stream ) const
00229 {
00230    UnitCommand::writeData( stream );
00231    stream.writeInt( JumpDriveCommandVersion );
00232    destination.write( stream );
00233 }
00234 
00235 
00236 ASCString JumpDriveCommand :: getCommandString() const
00237 {
00238    ASCString c;
00239    c.format("unitJump ( map, %d, asc.MapCoordinate( %d, %d ) )", getUnitID(), destination.x, destination.y );
00240    return c;
00241 
00242 }
00243 
00244 GameActionID JumpDriveCommand::getID() const
00245 {
00246    return ActionRegistry::JumpDriveCommand;
00247 }
00248 
00249 ASCString JumpDriveCommand::getDescription() const
00250 {
00251    ASCString s = "Jump ";
00252    
00253    if ( getUnit())
00254       s += getUnit()->getName();
00255    
00256    s += " to " + destination.toString();
00257    return s;
00258 }
00259 
00260 namespace
00261 {
00262    const bool r1 = registerAction<JumpDriveCommand> ( ActionRegistry::JumpDriveCommand );
00263 }
00264 

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