# 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 }