00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "repairunitcommand.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 "changeunitproperty.h"
00032 #include "changecontainerproperty.h"
00033 #include "servicing.h"
00034 #include "consumeresource.h"
00035
00036
00037 bool RepairUnitCommand :: availInternally ( const ContainerBase* servicer )
00038 {
00039 return servicer->baseType->hasFunction( ContainerBaseType::InternalUnitRepair );
00040 }
00041
00042
00043 bool RepairUnitCommand :: avail ( const ContainerBase* servicer )
00044 {
00045 if ( !servicer )
00046 return false;
00047
00048 if ( availInternally( servicer ))
00049 return true;
00050
00051 const Vehicle* v = dynamic_cast<const Vehicle*>(servicer);
00052 if ( v )
00053 return availExternally( v );
00054 else
00055 return false;
00056 }
00057
00058
00059 bool RepairUnitCommand :: availExternally ( const Vehicle* veh )
00060 {
00061 if ( !veh )
00062 return false;
00063
00064 if ( veh && !veh->attacked && veh->reactionfire.getStatus() == Vehicle::ReactionFire::off )
00065 if ( veh->typ->hasFunction( ContainerBaseType::ExternalRepair ))
00066 for ( int i = 0; i < veh->typ->weapons.count; i++ )
00067 if ( veh->typ->weapons.weapon[i].service() )
00068 return true;
00069
00070 return false;
00071 }
00072
00073
00074
00075 RepairUnitCommand :: RepairUnitCommand ( ContainerBase* container )
00076 : ContainerCommand ( container )
00077 {
00078 }
00079
00080
00081
00082 vector<Vehicle*> RepairUnitCommand :: getExternalTargets()
00083 {
00084 ServiceTargetSearcher sts( getContainer(), ServiceTargetSearcher::checkRepair );
00085 sts.startSearch();
00086 externalTargets.clear();
00087
00088 for ( ServiceTargetSearcher::Targets::const_iterator i = sts.getTargets().begin(); i != sts.getTargets().end(); ++i )
00089 if ( !(*i)->getCarrier() ) {
00090 Vehicle* v = dynamic_cast<Vehicle*>(*i);
00091 if ( v )
00092 externalTargets.push_back( v );
00093 }
00094
00095 return externalTargets;
00096 }
00097
00098 vector<Vehicle*> RepairUnitCommand :: getInternalTargets()
00099 {
00100 ServiceTargetSearcher sts( getContainer(), ServiceTargetSearcher::checkRepair );
00101 sts.startSearch();
00102
00103 internalTargets.clear();
00104
00105 for ( ServiceTargetSearcher::Targets::const_iterator i = sts.getTargets().begin(); i != sts.getTargets().end(); ++i )
00106 if ( (*i)->getCarrier() == getContainer() ) {
00107 Vehicle* v = dynamic_cast<Vehicle*>(*i);
00108 if ( v )
00109 internalTargets.push_back( v );
00110 }
00111
00112 return internalTargets;
00113 }
00114
00115
00116 bool RepairUnitCommand::validTarget( const Vehicle* target )
00117 {
00118 ServiceTargetSearcher sts( getContainer(), ServiceTargetSearcher::checkRepair );
00119 sts.startSearch();
00120 for ( ServiceTargetSearcher::Targets::const_iterator i = sts.getTargets().begin(); i != sts.getTargets().end(); ++i )
00121 if ( target == *i )
00122 return true;
00123
00124 return false;
00125 }
00126
00127 void RepairUnitCommand::setTarget( Vehicle* target )
00128 {
00129 if ( !target )
00130 return;
00131
00132 if ( validTarget(target) ) {
00133 targetNWid = target->networkid;
00134 setState( SetUp );
00135 }
00136 }
00137
00138
00139
00140 ActionResult RepairUnitCommand::go ( const Context& context )
00141 {
00142 if ( getState() != SetUp )
00143 return ActionResult(22000);
00144
00145 ContainerBase* servicer = getContainer();
00146 if ( !avail( servicer ))
00147 return ActionResult( 22401 );
00148
00149 Vehicle* target = getMap()->getUnit( targetNWid );
00150 if ( !target )
00151 return ActionResult( 22400 );
00152
00153 if ( !validTarget(target))
00154 return ActionResult( 22402 );
00155
00156
00157 Resources cost;
00158 int oldDamage = target->damage;
00159 int newDamage = servicer->getMaxRepair ( target, 0, cost );
00160
00161 auto_ptr<ChangeContainerProperty> propChange ( new ChangeContainerProperty( target, ChangeContainerProperty::Damage, newDamage ));
00162 ActionResult res = propChange->execute( context );
00163 if ( res.successful() )
00164 propChange.release();
00165 else
00166 return res;
00167
00168 int experience = target->experience;
00169 for ( int i = 0; i < experienceDecreaseDamageBoundaryNum; i++)
00170 if ( oldDamage > experienceDecreaseDamageBoundaries[i] && newDamage < experienceDecreaseDamageBoundaries[i] )
00171 if ( experience > 0 )
00172 experience-=1;
00173
00174 if ( experience != target->experience ) {
00175 auto_ptr<ChangeUnitProperty> expChange ( new ChangeUnitProperty( target, ChangeUnitProperty::Experience, experience ));
00176 ActionResult res = expChange->execute( context );
00177 if ( res.successful() )
00178 expChange.release();
00179 else
00180 return res;
00181 }
00182
00183 auto_ptr<ConsumeResource> resource ( new ConsumeResource( getContainer(), cost ));
00184 res = resource->execute( context );
00185 if ( res.successful() )
00186 resource.release();
00187
00188
00189 return res;
00190 }
00191
00192
00193
00194 static const int RepairUnitCommandVersion = 1;
00195
00196 void RepairUnitCommand :: readData ( tnstream& stream )
00197 {
00198 ContainerCommand::readData( stream );
00199 int version = stream.readInt();
00200 if ( version > RepairUnitCommandVersion )
00201 throw tinvalidversion ( "RepairUnitCommand", RepairUnitCommandVersion, version );
00202 targetNWid = stream.readInt();
00203 }
00204
00205 void RepairUnitCommand :: writeData ( tnstream& stream ) const
00206 {
00207 ContainerCommand::writeData( stream );
00208 stream.writeInt( RepairUnitCommandVersion );
00209 stream.writeInt( targetNWid );
00210 }
00211
00212
00213 ASCString RepairUnitCommand :: getCommandString() const
00214 {
00215 ASCString c;
00216 c.format("repairUnit ( map, %d, %d )", getContainerID(), targetNWid );
00217 return c;
00218
00219 }
00220
00221 GameActionID RepairUnitCommand::getID() const
00222 {
00223 return ActionRegistry::RepairUnitCommand;
00224 }
00225
00226 ASCString RepairUnitCommand::getDescription() const
00227 {
00228 ASCString s = "Repair unit " + ASCString::toString( targetNWid );
00229
00230 if ( getContainer( false ))
00231 s += " with " + getContainer()->getName();
00232
00233 return s;
00234 }
00235
00236 ActionResult RepairUnitCommand::checkExecutionPrecondition() const
00237 {
00238 if ( getMap()->getCurrentPlayer().diplomacy.isAllied( getContainer() ))
00239 return ActionResult(0);
00240 else
00241 return ActionResult(101);
00242 }
00243
00244
00245 namespace
00246 {
00247 const bool r1 = registerAction<RepairUnitCommand> ( ActionRegistry::RepairUnitCommand );
00248 }
00249