command.cpp

Go to the documentation of this file.
00001 /* $Id: command.cpp 12304 2008-02-28 00:17:49Z glx $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "landscape.h"
00008 #include "tile_map.h"
00009 #include "gui.h"
00010 #include "command_func.h"
00011 #include "network/network.h"
00012 #include "variables.h"
00013 #include "genworld.h"
00014 #include "newgrf_storage.h"
00015 #include "strings_func.h"
00016 #include "gfx_func.h"
00017 #include "functions.h"
00018 #include "town.h"
00019 #include "date_func.h"
00020 #include "debug.h"
00021 #include "player_func.h"
00022 #include "player_base.h"
00023 #include "signal_func.h"
00024 
00025 #include "table/strings.h"
00026 
00027 const char *_cmd_text = NULL;
00028 StringID _error_message;
00029 
00039 #define DEF_COMMAND(yyyy) CommandCost yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
00040 
00041 DEF_COMMAND(CmdBuildRailroadTrack);
00042 DEF_COMMAND(CmdRemoveRailroadTrack);
00043 DEF_COMMAND(CmdBuildSingleRail);
00044 DEF_COMMAND(CmdRemoveSingleRail);
00045 
00046 DEF_COMMAND(CmdLandscapeClear);
00047 
00048 DEF_COMMAND(CmdBuildBridge);
00049 
00050 DEF_COMMAND(CmdBuildRailroadStation);
00051 DEF_COMMAND(CmdRemoveFromRailroadStation);
00052 DEF_COMMAND(CmdConvertRail);
00053 
00054 DEF_COMMAND(CmdBuildSingleSignal);
00055 DEF_COMMAND(CmdRemoveSingleSignal);
00056 
00057 DEF_COMMAND(CmdTerraformLand);
00058 
00059 DEF_COMMAND(CmdPurchaseLandArea);
00060 DEF_COMMAND(CmdSellLandArea);
00061 
00062 DEF_COMMAND(CmdBuildTunnel);
00063 
00064 DEF_COMMAND(CmdBuildTrainDepot);
00065 DEF_COMMAND(CmdBuildTrainWaypoint);
00066 DEF_COMMAND(CmdRenameWaypoint);
00067 DEF_COMMAND(CmdRemoveTrainWaypoint);
00068 
00069 DEF_COMMAND(CmdBuildRoadStop);
00070 DEF_COMMAND(CmdRemoveRoadStop);
00071 
00072 DEF_COMMAND(CmdBuildLongRoad);
00073 DEF_COMMAND(CmdRemoveLongRoad);
00074 DEF_COMMAND(CmdBuildRoad);
00075 DEF_COMMAND(CmdRemoveRoad);
00076 
00077 DEF_COMMAND(CmdBuildRoadDepot);
00078 
00079 DEF_COMMAND(CmdBuildAirport);
00080 
00081 DEF_COMMAND(CmdBuildDock);
00082 
00083 DEF_COMMAND(CmdBuildShipDepot);
00084 
00085 DEF_COMMAND(CmdBuildBuoy);
00086 
00087 DEF_COMMAND(CmdPlantTree);
00088 
00089 DEF_COMMAND(CmdBuildRailVehicle);
00090 DEF_COMMAND(CmdMoveRailVehicle);
00091 
00092 DEF_COMMAND(CmdStartStopTrain);
00093 
00094 DEF_COMMAND(CmdSellRailWagon);
00095 
00096 DEF_COMMAND(CmdSendTrainToDepot);
00097 DEF_COMMAND(CmdForceTrainProceed);
00098 DEF_COMMAND(CmdReverseTrainDirection);
00099 
00100 DEF_COMMAND(CmdModifyOrder);
00101 DEF_COMMAND(CmdSkipToOrder);
00102 DEF_COMMAND(CmdDeleteOrder);
00103 DEF_COMMAND(CmdInsertOrder);
00104 DEF_COMMAND(CmdChangeServiceInt);
00105 DEF_COMMAND(CmdRestoreOrderIndex);
00106 
00107 DEF_COMMAND(CmdBuildIndustry);
00108 
00109 DEF_COMMAND(CmdBuildCompanyHQ);
00110 DEF_COMMAND(CmdSetPlayerFace);
00111 DEF_COMMAND(CmdSetPlayerColor);
00112 
00113 DEF_COMMAND(CmdIncreaseLoan);
00114 DEF_COMMAND(CmdDecreaseLoan);
00115 
00116 DEF_COMMAND(CmdWantEnginePreview);
00117 
00118 DEF_COMMAND(CmdNameVehicle);
00119 DEF_COMMAND(CmdRenameEngine);
00120 
00121 DEF_COMMAND(CmdChangeCompanyName);
00122 DEF_COMMAND(CmdChangePresidentName);
00123 
00124 DEF_COMMAND(CmdRenameStation);
00125 
00126 DEF_COMMAND(CmdSellAircraft);
00127 DEF_COMMAND(CmdStartStopAircraft);
00128 DEF_COMMAND(CmdBuildAircraft);
00129 DEF_COMMAND(CmdSendAircraftToHangar);
00130 DEF_COMMAND(CmdRefitAircraft);
00131 
00132 DEF_COMMAND(CmdPlaceSign);
00133 DEF_COMMAND(CmdRenameSign);
00134 
00135 DEF_COMMAND(CmdBuildRoadVeh);
00136 DEF_COMMAND(CmdStartStopRoadVeh);
00137 DEF_COMMAND(CmdSellRoadVeh);
00138 DEF_COMMAND(CmdSendRoadVehToDepot);
00139 DEF_COMMAND(CmdTurnRoadVeh);
00140 DEF_COMMAND(CmdRefitRoadVeh);
00141 
00142 DEF_COMMAND(CmdPause);
00143 
00144 DEF_COMMAND(CmdBuyShareInCompany);
00145 DEF_COMMAND(CmdSellShareInCompany);
00146 DEF_COMMAND(CmdBuyCompany);
00147 
00148 DEF_COMMAND(CmdBuildTown);
00149 
00150 DEF_COMMAND(CmdRenameTown);
00151 DEF_COMMAND(CmdDoTownAction);
00152 
00153 DEF_COMMAND(CmdSetRoadDriveSide);
00154 
00155 DEF_COMMAND(CmdChangeDifficultyLevel);
00156 DEF_COMMAND(CmdChangePatchSetting);
00157 
00158 DEF_COMMAND(CmdStartStopShip);
00159 DEF_COMMAND(CmdSellShip);
00160 DEF_COMMAND(CmdBuildShip);
00161 DEF_COMMAND(CmdSendShipToDepot);
00162 DEF_COMMAND(CmdRefitShip);
00163 
00164 DEF_COMMAND(CmdOrderRefit);
00165 DEF_COMMAND(CmdCloneOrder);
00166 
00167 DEF_COMMAND(CmdClearArea);
00168 
00169 DEF_COMMAND(CmdGiveMoney);
00170 DEF_COMMAND(CmdMoneyCheat);
00171 DEF_COMMAND(CmdBuildCanal);
00172 DEF_COMMAND(CmdBuildLock);
00173 
00174 DEF_COMMAND(CmdPlayerCtrl);
00175 
00176 DEF_COMMAND(CmdLevelLand);
00177 
00178 DEF_COMMAND(CmdRefitRailVehicle);
00179 
00180 DEF_COMMAND(CmdBuildSignalTrack);
00181 DEF_COMMAND(CmdRemoveSignalTrack);
00182 
00183 DEF_COMMAND(CmdSetAutoReplace);
00184 
00185 DEF_COMMAND(CmdCloneVehicle);
00186 DEF_COMMAND(CmdMassStartStopVehicle);
00187 DEF_COMMAND(CmdDepotSellAllVehicles);
00188 DEF_COMMAND(CmdDepotMassAutoReplace);
00189 
00190 DEF_COMMAND(CmdCreateGroup);
00191 DEF_COMMAND(CmdRenameGroup);
00192 DEF_COMMAND(CmdDeleteGroup);
00193 DEF_COMMAND(CmdAddVehicleGroup);
00194 DEF_COMMAND(CmdAddSharedVehicleGroup);
00195 DEF_COMMAND(CmdRemoveAllVehiclesGroup);
00196 DEF_COMMAND(CmdSetGroupReplaceProtection);
00197 
00198 DEF_COMMAND(CmdMoveOrder);
00199 DEF_COMMAND(CmdChangeTimetable);
00200 DEF_COMMAND(CmdSetVehicleOnTime);
00201 DEF_COMMAND(CmdAutofillTimetable);
00202 #undef DEF_COMMAND
00203 
00211 static const Command _command_proc_table[] = {
00212   {CmdBuildRailroadTrack,           CMD_AUTO}, /* CMD_BUILD_RAILROAD_TRACK */
00213   {CmdRemoveRailroadTrack,          CMD_AUTO}, /* CMD_REMOVE_RAILROAD_TRACK */
00214   {CmdBuildSingleRail,              CMD_AUTO}, /* CMD_BUILD_SINGLE_RAIL */
00215   {CmdRemoveSingleRail,             CMD_AUTO}, /* CMD_REMOVE_SINGLE_RAIL */
00216   {CmdLandscapeClear,                      0}, /* CMD_LANDSCAPE_CLEAR */
00217   {CmdBuildBridge,                  CMD_AUTO}, /* CMD_BUILD_BRIDGE */
00218   {CmdBuildRailroadStation,         CMD_AUTO}, /* CMD_BUILD_RAILROAD_STATION */
00219   {CmdBuildTrainDepot,              CMD_AUTO}, /* CMD_BUILD_TRAIN_DEPOT */
00220   {CmdBuildSingleSignal,            CMD_AUTO}, /* CMD_BUILD_SIGNALS */
00221   {CmdRemoveSingleSignal,           CMD_AUTO}, /* CMD_REMOVE_SIGNALS */
00222   {CmdTerraformLand,                CMD_AUTO}, /* CMD_TERRAFORM_LAND */
00223   {CmdPurchaseLandArea,             CMD_AUTO}, /* CMD_PURCHASE_LAND_AREA */
00224   {CmdSellLandArea,                        0}, /* CMD_SELL_LAND_AREA */
00225   {CmdBuildTunnel,                  CMD_AUTO}, /* CMD_BUILD_TUNNEL */
00226   {CmdRemoveFromRailroadStation,           0}, /* CMD_REMOVE_FROM_RAILROAD_STATION */
00227   {CmdConvertRail,                         0}, /* CMD_CONVERT_RAILD */
00228   {CmdBuildTrainWaypoint,                  0}, /* CMD_BUILD_TRAIN_WAYPOINT */
00229   {CmdRenameWaypoint,                      0}, /* CMD_RENAME_WAYPOINT */
00230   {CmdRemoveTrainWaypoint,                 0}, /* CMD_REMOVE_TRAIN_WAYPOINT */
00231 
00232   {CmdBuildRoadStop,                CMD_AUTO}, /* CMD_BUILD_ROAD_STOP */
00233   {CmdRemoveRoadStop,                      0}, /* CMD_REMOVE_ROAD_STOP */
00234   {CmdBuildLongRoad,                CMD_AUTO}, /* CMD_BUILD_LONG_ROAD */
00235   {CmdRemoveLongRoad,               CMD_AUTO}, /* CMD_REMOVE_LONG_ROAD */
00236   {CmdBuildRoad,                           0}, /* CMD_BUILD_ROAD */
00237   {CmdRemoveRoad,                          0}, /* CMD_REMOVE_ROAD */
00238   {CmdBuildRoadDepot,               CMD_AUTO}, /* CMD_BUILD_ROAD_DEPOT */
00239 
00240   {CmdBuildAirport,                 CMD_AUTO}, /* CMD_BUILD_AIRPORT */
00241   {CmdBuildDock,                    CMD_AUTO}, /* CMD_BUILD_DOCK */
00242   {CmdBuildShipDepot,               CMD_AUTO}, /* CMD_BUILD_SHIP_DEPOT */
00243   {CmdBuildBuoy,                    CMD_AUTO}, /* CMD_BUILD_BUOY */
00244   {CmdPlantTree,                    CMD_AUTO}, /* CMD_PLANT_TREE */
00245   {CmdBuildRailVehicle,                    0}, /* CMD_BUILD_RAIL_VEHICLE */
00246   {CmdMoveRailVehicle,                     0}, /* CMD_MOVE_RAIL_VEHICLE */
00247   {CmdStartStopTrain,                      0}, /* CMD_START_STOP_TRAIN */
00248 
00249   {CmdSellRailWagon,                       0}, /* CMD_SELL_RAIL_WAGON */
00250   {CmdSendTrainToDepot,                    0}, /* CMD_SEND_TRAIN_TO_DEPOT */
00251   {CmdForceTrainProceed,                   0}, /* CMD_FORCE_TRAIN_PROCEED */
00252   {CmdReverseTrainDirection,               0}, /* CMD_REVERSE_TRAIN_DIRECTION */
00253 
00254   {CmdModifyOrder,                         0}, /* CMD_MODIFY_ORDER */
00255   {CmdSkipToOrder,                         0}, /* CMD_SKIP_TO_ORDER */
00256   {CmdDeleteOrder,                         0}, /* CMD_DELETE_ORDER */
00257   {CmdInsertOrder,                         0}, /* CMD_INSERT_ORDER */
00258 
00259   {CmdChangeServiceInt,                    0}, /* CMD_CHANGE_SERVICE_INT */
00260 
00261   {CmdBuildIndustry,                       0}, /* CMD_BUILD_INDUSTRY */
00262   {CmdBuildCompanyHQ,               CMD_AUTO}, /* CMD_BUILD_COMPANY_HQ */
00263   {CmdSetPlayerFace,                       0}, /* CMD_SET_PLAYER_FACE */
00264   {CmdSetPlayerColor,                      0}, /* CMD_SET_PLAYER_COLOR */
00265 
00266   {CmdIncreaseLoan,                        0}, /* CMD_INCREASE_LOAN */
00267   {CmdDecreaseLoan,                        0}, /* CMD_DECREASE_LOAN */
00268 
00269   {CmdWantEnginePreview,                   0}, /* CMD_WANT_ENGINE_PREVIEW */
00270 
00271   {CmdNameVehicle,                         0}, /* CMD_NAME_VEHICLE */
00272   {CmdRenameEngine,                        0}, /* CMD_RENAME_ENGINE */
00273 
00274   {CmdChangeCompanyName,                   0}, /* CMD_CHANGE_COMPANY_NAME */
00275   {CmdChangePresidentName,                 0}, /* CMD_CHANGE_PRESIDENT_NAME */
00276 
00277   {CmdRenameStation,                       0}, /* CMD_RENAME_STATION */
00278 
00279   {CmdSellAircraft,                        0}, /* CMD_SELL_AIRCRAFT */
00280   {CmdStartStopAircraft,                   0}, /* CMD_START_STOP_AIRCRAFT */
00281 
00282   {CmdBuildAircraft,                       0}, /* CMD_BUILD_AIRCRAFT */
00283   {CmdSendAircraftToHangar,                0}, /* CMD_SEND_AIRCRAFT_TO_HANGAR */
00284   {CmdRefitAircraft,                       0}, /* CMD_REFIT_AIRCRAFT */
00285 
00286   {CmdPlaceSign,                           0}, /* CMD_PLACE_SIGN */
00287   {CmdRenameSign,                          0}, /* CMD_RENAME_SIGN */
00288 
00289   {CmdBuildRoadVeh,                        0}, /* CMD_BUILD_ROAD_VEH */
00290   {CmdStartStopRoadVeh,                    0}, /* CMD_START_STOP_ROADVEH */
00291   {CmdSellRoadVeh,                         0}, /* CMD_SELL_ROAD_VEH */
00292   {CmdSendRoadVehToDepot,                  0}, /* CMD_SEND_ROADVEH_TO_DEPOT */
00293   {CmdTurnRoadVeh,                         0}, /* CMD_TURN_ROADVEH */
00294   {CmdRefitRoadVeh,                        0}, /* CMD_REFIT_ROAD_VEH */
00295 
00296   {CmdPause,                      CMD_SERVER}, /* CMD_PAUSE */
00297 
00298   {CmdBuyShareInCompany,                   0}, /* CMD_BUY_SHARE_IN_COMPANY */
00299   {CmdSellShareInCompany,                  0}, /* CMD_SELL_SHARE_IN_COMPANY */
00300   {CmdBuyCompany,                          0}, /* CMD_BUY_COMANY */
00301 
00302   {CmdBuildTown,                 CMD_OFFLINE}, /* CMD_BUILD_TOWN */
00303   {CmdRenameTown,                 CMD_SERVER}, /* CMD_RENAME_TOWN */
00304   {CmdDoTownAction,                        0}, /* CMD_DO_TOWN_ACTION */
00305 
00306   {CmdSetRoadDriveSide,           CMD_SERVER}, /* CMD_SET_ROAD_DRIVE_SIDE */
00307   {CmdChangeDifficultyLevel,      CMD_SERVER}, /* CMD_CHANGE_DIFFICULTY_LEVEL */
00308 
00309   {CmdStartStopShip,                       0}, /* CMD_START_STOP_SHIP */
00310   {CmdSellShip,                            0}, /* CMD_SELL_SHIP */
00311   {CmdBuildShip,                           0}, /* CMD_BUILD_SHIP */
00312   {CmdSendShipToDepot,                     0}, /* CMD_SEND_SHIP_TO_DEPOT */
00313   {CmdRefitShip,                           0}, /* CMD_REFIT_SHIP */
00314 
00315   {CmdOrderRefit,                          0}, /* CMD_ORDER_REFIT */
00316   {CmdCloneOrder,                          0}, /* CMD_CLONE_ORDER */
00317 
00318   {CmdClearArea,                           0}, /* CMD_CLEAR_AREA */
00319 
00320   {CmdMoneyCheat,                CMD_OFFLINE}, /* CMD_MONEY_CHEAT */
00321   {CmdBuildCanal,                   CMD_AUTO}, /* CMD_BUILD_CANAL */
00322   {CmdPlayerCtrl,                          0}, /* CMD_PLAYER_CTRL */
00323 
00324   {CmdLevelLand,                    CMD_AUTO}, /* CMD_LEVEL_LAND */
00325 
00326   {CmdRefitRailVehicle,                    0}, /* CMD_REFIT_RAIL_VEHICLE */
00327   {CmdRestoreOrderIndex,                   0}, /* CMD_RESTORE_ORDER_INDEX */
00328   {CmdBuildLock,                    CMD_AUTO}, /* CMD_BUILD_LOCK */
00329 
00330   {CmdBuildSignalTrack,             CMD_AUTO}, /* CMD_BUILD_SIGNAL_TRACK */
00331   {CmdRemoveSignalTrack,            CMD_AUTO}, /* CMD_REMOVE_SIGNAL_TRACK */
00332 
00333   {CmdGiveMoney,                           0}, /* CMD_GIVE_MONEY */
00334   {CmdChangePatchSetting,         CMD_SERVER}, /* CMD_CHANGE_PATCH_SETTING */
00335   {CmdSetAutoReplace,                      0}, /* CMD_SET_AUTOREPLACE */
00336   {CmdCloneVehicle,                        0}, /* CMD_CLONE_VEHICLE */
00337   {CmdMassStartStopVehicle,                0}, /* CMD_MASS_START_STOP */
00338   {CmdDepotSellAllVehicles,                0}, /* CMD_DEPOT_SELL_ALL_VEHICLES */
00339   {CmdDepotMassAutoReplace,                0}, /* CMD_DEPOT_MASS_AUTOREPLACE */
00340   {CmdCreateGroup,                         0}, /* CMD_CREATE_GROUP */
00341   {CmdDeleteGroup,                         0}, /* CMD_DELETE_GROUP */
00342   {CmdRenameGroup,                         0}, /* CMD_RENAME_GROUP */
00343   {CmdAddVehicleGroup,                     0}, /* CMD_ADD_VEHICLE_GROUP */
00344   {CmdAddSharedVehicleGroup,               0}, /* CMD_ADD_SHARE_VEHICLE_GROUP */
00345   {CmdRemoveAllVehiclesGroup,              0}, /* CMD_REMOVE_ALL_VEHICLES_GROUP */
00346   {CmdSetGroupReplaceProtection,           0}, /* CMD_SET_GROUP_REPLACE_PROTECTION */
00347   {CmdMoveOrder,                           0}, /* CMD_MOVE_ORDER */
00348   {CmdChangeTimetable,                     0}, /* CMD_CHANGE_TIMETABLE */
00349   {CmdSetVehicleOnTime,                    0}, /* CMD_SET_VEHICLE_ON_TIME */
00350   {CmdAutofillTimetable,                   0}, /* CMD_AUTOFILL_TIMETABLE */
00351 };
00352 
00359 bool IsValidCommand(uint cmd)
00360 {
00361   cmd &= 0xFF;
00362 
00363   return
00364     cmd < lengthof(_command_proc_table) &&
00365     _command_proc_table[cmd].proc != NULL;
00366 }
00367 
00378 byte GetCommandFlags(uint cmd)
00379 {
00380   return _command_proc_table[cmd & 0xFF].flags;
00381 }
00382 
00383 static int _docommand_recursive = 0;
00384 
00396 CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint32 procc)
00397 {
00398   CommandCost res;
00399   CommandProc *proc;
00400 
00401   /* Do not even think about executing out-of-bounds tile-commands */
00402   if (!IsValidTile(tile)) {
00403     _cmd_text = NULL;
00404     return CMD_ERROR;
00405   }
00406 
00407   proc = _command_proc_table[procc].proc;
00408 
00409   if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
00410 
00411   _docommand_recursive++;
00412 
00413   /* only execute the test call if it's toplevel, or we're not execing. */
00414   if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
00415     SetTownRatingTestMode(true);
00416     res = proc(tile, flags & ~DC_EXEC, p1, p2);
00417     SetTownRatingTestMode(false);
00418     if (CmdFailed(res)) {
00419       res.SetGlobalErrorMessage();
00420       goto error;
00421     }
00422 
00423     if (_docommand_recursive == 1 &&
00424         !(flags & DC_QUERY_COST) &&
00425         !(flags & DC_BANKRUPT) &&
00426         res.GetCost() != 0 &&
00427         !CheckPlayerHasMoney(res)) {
00428       goto error;
00429     }
00430 
00431     if (!(flags & DC_EXEC)) {
00432       _docommand_recursive--;
00433       _cmd_text = NULL;
00434       return res;
00435     }
00436   }
00437 
00438   /* Execute the command here. All cost-relevant functions set the expenses type
00439    * themselves to the cost object at some point */
00440   res = proc(tile, flags, p1, p2);
00441   if (CmdFailed(res)) {
00442     res.SetGlobalErrorMessage();
00443 error:
00444     _docommand_recursive--;
00445     _cmd_text = NULL;
00446     return CMD_ERROR;
00447   }
00448 
00449   /* if toplevel, subtract the money. */
00450   if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
00451     SubtractMoneyFromPlayer(res);
00452     /* XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player */
00453     if (tile != 0 && IsValidPlayer(_current_player)) {
00454       GetPlayer(_current_player)->last_build_coordinate = tile;
00455     }
00456   }
00457 
00458   _cmd_text = NULL;
00459   return res;
00460 }
00461 
00469 Money GetAvailableMoneyForCommand()
00470 {
00471   PlayerID pid = _current_player;
00472   if (!IsValidPlayer(pid)) return INT64_MAX;
00473   return GetPlayer(pid)->player_money;
00474 }
00475 
00490 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd, bool my_cmd)
00491 {
00492   CommandCost res, res2;
00493   CommandProc *proc;
00494   uint32 flags;
00495   bool notest;
00496   StringID error_part1;
00497 
00498   int x = TileX(tile) * TILE_SIZE;
00499   int y = TileY(tile) * TILE_SIZE;
00500 
00501   /* Do not even think about executing out-of-bounds tile-commands */
00502   if (!IsValidTile(tile)) {
00503     _cmd_text = NULL;
00504     return false;
00505   }
00506 
00507   assert(_docommand_recursive == 0);
00508 
00509   _error_message = INVALID_STRING_ID;
00510   error_part1 = GB(cmd, 16, 16);
00511   _additional_cash_required = 0;
00512 
00515   if (_current_player == PLAYER_SPECTATOR && !_network_server) {
00516     if (my_cmd) ShowErrorMessage(_error_message, error_part1, x, y);
00517     _cmd_text = NULL;
00518     return false;
00519   }
00520 
00521   flags = 0;
00522   if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
00523 
00524   /* get pointer to command handler */
00525   assert((cmd & 0xFF) < lengthof(_command_proc_table));
00526   proc = _command_proc_table[cmd & 0xFF].proc;
00527   if (proc == NULL) {
00528     _cmd_text = NULL;
00529     return false;
00530   }
00531 
00532   if (GetCommandFlags(cmd) & CMD_AUTO) flags |= DC_AUTO;
00533 
00534   /* Some commands have a different output in dryrun than the realrun
00535    *  e.g.: if you demolish a whole town, the dryrun would say okay.
00536    *  but by really destroying, your rating drops and at a certain point
00537    *  it will fail. so res and res2 are different
00538    * CMD_REMOVE_LONG_ROAD: This command has special local authority
00539    * restrictions which may cause the test run to fail (the previous
00540    * road fragments still stay there and the town won't let you
00541    * disconnect the road system), but the exec will succeed and this
00542    * fact will trigger an assertion failure. --pasky
00543    * CMD_CLONE_VEHICLE: Both building new vehicles and refitting them can be
00544    * influenced by newgrf callbacks, which makes it impossible to accurately
00545    * estimate the cost of cloning a vehicle. */
00546   notest =
00547     (cmd & 0xFF) == CMD_CLEAR_AREA ||
00548     (cmd & 0xFF) == CMD_LEVEL_LAND ||
00549     (cmd & 0xFF) == CMD_REMOVE_LONG_ROAD ||
00550     (cmd & 0xFF) == CMD_CLONE_VEHICLE;
00551 
00552   _docommand_recursive = 1;
00553 
00554   /* cost estimation only? */
00555   if (!IsGeneratingWorld() &&
00556       _shift_pressed &&
00557       IsLocalPlayer() &&
00558       !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) &&
00559       (cmd & 0xFF) != CMD_PAUSE) {
00560     /* estimate the cost. */
00561     SetTownRatingTestMode(true);
00562     res = proc(tile, flags, p1, p2);
00563     SetTownRatingTestMode(false);
00564     if (CmdFailed(res)) {
00565       res.SetGlobalErrorMessage();
00566       ShowErrorMessage(_error_message, error_part1, x, y);
00567     } else {
00568       ShowEstimatedCostOrIncome(res.GetCost(), x, y);
00569     }
00570 
00571     _docommand_recursive = 0;
00572     _cmd_text = NULL;
00573     ClearStorageChanges(false);
00574     return false;
00575   }
00576 
00577 
00578   if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
00579     /* first test if the command can be executed. */
00580     SetTownRatingTestMode(true);
00581     res = proc(tile, flags, p1, p2);
00582     SetTownRatingTestMode(false);
00583     if (CmdFailed(res)) {
00584       res.SetGlobalErrorMessage();
00585       goto show_error;
00586     }
00587     /* no money? Only check if notest is off */
00588     if (!notest && res.GetCost() != 0 && !CheckPlayerHasMoney(res)) goto show_error;
00589   }
00590 
00591 #ifdef ENABLE_NETWORK
00592 
00599   if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
00600     PlayerID pbck = _local_player;
00601     if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = PLAYER_FIRST;
00602     NetworkSend_Command(tile, p1, p2, cmd, callback);
00603     if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck;
00604     _docommand_recursive = 0;
00605     _cmd_text = NULL;
00606     ClearStorageChanges(false);
00607     return true;
00608   }
00609 #endif /* ENABLE_NETWORK */
00610   DebugDumpCommands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)_current_player, tile, p1, p2, cmd, _cmd_text);
00611 
00612   /* update last build coordinate of player. */
00613   if (tile != 0 && IsValidPlayer(_current_player)) {
00614     GetPlayer(_current_player)->last_build_coordinate = tile;
00615   }
00616 
00617   /* Actually try and execute the command. If no cost-type is given
00618    * use the construction one */
00619   res2 = proc(tile, flags | DC_EXEC, p1, p2);
00620 
00621   /* If notest is on, it means the result of the test can be different than
00622    *  the real command.. so ignore the test */
00623   if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
00624     assert(res.GetCost() == res2.GetCost() && CmdFailed(res) == CmdFailed(res2)); // sanity check
00625   } else {
00626     if (CmdFailed(res2)) {
00627       res.SetGlobalErrorMessage();
00628       goto show_error;
00629     }
00630   }
00631 
00632   SubtractMoneyFromPlayer(res2);
00633 
00634   /* update signals if needed */
00635   UpdateSignalsInBuffer();
00636 
00637   if (IsLocalPlayer() && _game_mode != GM_EDITOR) {
00638     if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost());
00639     if (_additional_cash_required != 0) {
00640       SetDParam(0, _additional_cash_required);
00641       if (my_cmd) ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x, y);
00642       if (res2.GetCost() == 0) goto callb_err;
00643     }
00644   }
00645 
00646   _docommand_recursive = 0;
00647 
00648   if (callback) callback(true, tile, p1, p2);
00649   _cmd_text = NULL;
00650   ClearStorageChanges(true);
00651   return true;
00652 
00653 show_error:
00654   /* show error message if the command fails? */
00655   if (IsLocalPlayer() && error_part1 != 0 && my_cmd) {
00656     ShowErrorMessage(_error_message, error_part1, x, y);
00657   }
00658 
00659 callb_err:
00660   _docommand_recursive = 0;
00661 
00662   if (callback) callback(false, tile, p1, p2);
00663   _cmd_text = NULL;
00664   ClearStorageChanges(false);
00665   return false;
00666 }
00667 
00668 
00669 CommandCost CommandCost::AddCost(CommandCost ret)
00670 {
00671   this->AddCost(ret.cost);
00672   if (this->success && !ret.success) {
00673     this->message = ret.message;
00674     this->success = false;
00675   }
00676   return *this;
00677 }
00678 
00679 CommandCost CommandCost::AddCost(Money cost)
00680 {
00681   this->cost += cost;
00682   return *this;
00683 }
00684 
00685 CommandCost CommandCost::MultiplyCost(int factor)
00686 {
00687   this->cost *= factor;
00688   return *this;
00689 }
00690 
00691 Money CommandCost::GetCost() const
00692 {
00693   return this->cost;
00694 }
00695 
00696 ExpensesType CommandCost::GetExpensesType() const
00697 {
00698   return this->expense_type;
00699 }
00700 
00701 void CommandCost::SetGlobalErrorMessage() const
00702 {
00703   extern StringID _error_message;
00704   if (this->message != INVALID_STRING_ID) _error_message = this->message;
00705 }
00706 
00707 bool CommandCost::Succeeded() const
00708 {
00709   return this->success;
00710 }
00711 
00712 bool CommandCost::Failed() const
00713 {
00714   return !this->success;
00715 }

Generated on Mon Sep 22 20:34:15 2008 for openttd by  doxygen 1.5.6