00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cmath>
00023
00024 #include "changeunitmovement.h"
00025 #include "changeunitproperty.h"
00026 #include "action-registry.h"
00027
00028 #include "../vehicle.h"
00029 #include "../gamemap.h"
00030
00031
00032 ChangeUnitMovement::ChangeUnitMovement( Vehicle* veh, int movement, bool delta, Recursivity recursive )
00033 : UnitAction( veh->getMap(), veh->networkid ), originalMovement(-1), resultingMovement(-1)
00034 {
00035 this->movement = movement;
00036 this->delta = delta;
00037 this->recursive = recursive;
00038 }
00039
00040
00041 ASCString ChangeUnitMovement::getDescription() const
00042 {
00043 ASCString res = "Change movement ";
00044 if ( getUnit(false) )
00045 res += " of unit " + getUnit(false)->getName();
00046
00047 if ( delta )
00048 res += " by ";
00049 else
00050 res += " to ";
00051 res += ASCString::toString(movement) + " points ";
00052 return res;
00053 }
00054
00055 static const int changeUnitMovementStreamVersion = 2;
00056
00057 void ChangeUnitMovement::readData ( tnstream& stream )
00058 {
00059 UnitAction::readData( stream );
00060 int version = stream.readInt();
00061 if ( version < 1 || version > changeUnitMovementStreamVersion )
00062 throw tinvalidversion ( "ChangeUnitMovement", changeUnitMovementStreamVersion, version );
00063
00064 movement = stream.readInt();
00065 delta = stream.readInt();
00066 originalMovement = stream.readInt();
00067 resultingMovement = stream.readInt();
00068 if ( version >= 2 )
00069 recursive = (Recursivity) stream.readInt();
00070 else
00071 recursive = NORMAL;
00072 };
00073
00074
00075 void ChangeUnitMovement::writeData ( tnstream& stream ) const
00076 {
00077 UnitAction::writeData( stream );
00078 stream.writeInt( changeUnitMovementStreamVersion );
00079 stream.writeInt( movement );
00080 stream.writeInt( delta );
00081 stream.writeInt( originalMovement );
00082 stream.writeInt( resultingMovement );
00083 stream.writeInt( (int) recursive );
00084 };
00085
00086
00087 GameActionID ChangeUnitMovement::getID() const
00088 {
00089 return ActionRegistry::ChangeUnitMovement;
00090 }
00091
00092 void ChangeUnitMovement::decreaseMovement( Vehicle* veh, float fraction, const Context& context )
00093 {
00094 if ( recursive != NONE )
00095 if ( veh->typ->movement[ getFirstBit ( veh->height ) ] ) {
00096 float cargoFraction = fraction;
00097 if ( veh->cargoNestingDepth() == 0 && veh->typ->cargoMovementDivisor != 0 && recursive == NORMAL )
00098 cargoFraction /= veh->typ->cargoMovementDivisor;
00099
00100 for ( Vehicle::Cargo::const_iterator i = veh->getCargo().begin(); i != veh->getCargo().end(); ++i )
00101 if ( *i )
00102 decreaseMovement( *i, cargoFraction, context );
00103 }
00104
00105 float f = float(veh->maxMovement()) * fraction;
00106 float f2 = ceil(f);
00107 if ( fabs ( f-f2) > 0.999 )
00108 f2 -= 1;
00109
00110 int i = int( f2 );
00111 int newMovement = veh->getMovement(false,false) - i;
00112
00113 (new ChangeUnitProperty(veh, ChangeUnitProperty::Movement, newMovement ))->execute( context );
00114 }
00115
00116
00117 ActionResult ChangeUnitMovement::runAction( const Context& context )
00118 {
00119 Vehicle* veh = getUnit();
00120
00121 originalMovement = veh->getMovement( false, false );
00122
00123 float fraction;
00124 if ( delta ) {
00125 fraction = float(movement) / float( veh->maxMovement());
00126 } else {
00127 fraction = float(originalMovement - movement) / float( veh->maxMovement());
00128 }
00129
00130 decreaseMovement( veh, fraction, context );
00131
00132 resultingMovement = veh->getMovement( false, false );
00133 return ActionResult(0);
00134 }
00135
00136
00137 ActionResult ChangeUnitMovement::undoAction( const Context& context )
00138 {
00139 return ActionResult(0);
00140 }
00141
00142 ActionResult ChangeUnitMovement::preCheck()
00143 {
00144 if ( getUnit()->getMovement( false, false ) != originalMovement )
00145 throw ActionResult( 21103, getUnit() );
00146
00147 return ActionResult(0);
00148 }
00149
00150 ActionResult ChangeUnitMovement::postCheck()
00151 {
00152 if ( getUnit()->getMovement( false, false ) != resultingMovement )
00153 throw ActionResult( 21103, getUnit() );
00154
00155 return ActionResult(0);
00156 }
00157
00158
00159 namespace {
00160 const bool r1 = registerAction<ChangeUnitMovement> ( ActionRegistry::ChangeUnitMovement );
00161 }