# command.cpp

Go to the documentation of this file.

    00001 /* $Id: command.cpp 18292 2009-11-25 23:37:15Z rubidium $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "openttd.h"
    00014 #include "landscape.h"
    00015 #include "gui.h"
    00016 #include "command_func.h"
    00017 #include "network/network.h"
    00018 #include "genworld.h"
    00019 #include "newgrf_storage.h"
    00020 #include "strings_func.h"
    00021 #include "gfx_func.h"
    00022 #include "functions.h"
    00023 #include "town.h"
    00024 #include "date_func.h"
    00025 #include "debug.h"
    00026 #include "company_func.h"
    00027 #include "company_base.h"
    00028 #include "signal_func.h"
    00029
    00030 #include "table/strings.h"
    00031
    00032 StringID _error_message;
    00033
    00043 #define DEF_COMMAND(yyyy) CommandCost yyyy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    00044
    00045 DEF_COMMAND(CmdBuildRailroadTrack);
    00046 DEF_COMMAND(CmdRemoveRailroadTrack);
    00047 DEF_COMMAND(CmdBuildSingleRail);
    00048 DEF_COMMAND(CmdRemoveSingleRail);
    00049
    00050 DEF_COMMAND(CmdLandscapeClear);
    00051
    00052 DEF_COMMAND(CmdBuildBridge);
    00053
    00054 DEF_COMMAND(CmdBuildRailStation);
    00055 DEF_COMMAND(CmdRemoveFromRailStation);
    00056 DEF_COMMAND(CmdConvertRail);
    00057
    00058 DEF_COMMAND(CmdBuildSingleSignal);
    00059 DEF_COMMAND(CmdRemoveSingleSignal);
    00060
    00061 DEF_COMMAND(CmdTerraformLand);
    00062
    00063 DEF_COMMAND(CmdPurchaseLandArea);
    00064 DEF_COMMAND(CmdSellLandArea);
    00065
    00066 DEF_COMMAND(CmdBuildTunnel);
    00067
    00068 DEF_COMMAND(CmdBuildTrainDepot);
    00069 DEF_COMMAND(CmdBuildRailWaypoint);
    00070 DEF_COMMAND(CmdRenameWaypoint);
    00071 DEF_COMMAND(CmdRemoveFromRailWaypoint);
    00072
    00073 DEF_COMMAND(CmdBuildRoadStop);
    00074 DEF_COMMAND(CmdRemoveRoadStop);
    00075
    00076 DEF_COMMAND(CmdBuildLongRoad);
    00077 DEF_COMMAND(CmdRemoveLongRoad);
    00078 DEF_COMMAND(CmdBuildRoad);
    00079 DEF_COMMAND(CmdRemoveRoad);
    00080
    00081 DEF_COMMAND(CmdBuildRoadDepot);
    00082
    00083 DEF_COMMAND(CmdBuildAirport);
    00084
    00085 DEF_COMMAND(CmdBuildDock);
    00086
    00087 DEF_COMMAND(CmdBuildShipDepot);
    00088
    00089 DEF_COMMAND(CmdBuildBuoy);
    00090
    00091 DEF_COMMAND(CmdPlantTree);
    00092
    00093 DEF_COMMAND(CmdBuildRailVehicle);
    00094 DEF_COMMAND(CmdMoveRailVehicle);
    00095
    00096 DEF_COMMAND(CmdSellRailWagon);
    00097
    00098 DEF_COMMAND(CmdSendTrainToDepot);
    00099 DEF_COMMAND(CmdForceTrainProceed);
    00100 DEF_COMMAND(CmdReverseTrainDirection);
    00101
    00102 DEF_COMMAND(CmdModifyOrder);
    00103 DEF_COMMAND(CmdSkipToOrder);
    00104 DEF_COMMAND(CmdDeleteOrder);
    00105 DEF_COMMAND(CmdInsertOrder);
    00106 DEF_COMMAND(CmdChangeServiceInt);
    00107 DEF_COMMAND(CmdRestoreOrderIndex);
    00108
    00109 DEF_COMMAND(CmdBuildIndustry);
    00110
    00111 DEF_COMMAND(CmdBuildCompanyHQ);
    00112 DEF_COMMAND(CmdSetCompanyManagerFace);
    00113 DEF_COMMAND(CmdSetCompanyColour);
    00114
    00115 DEF_COMMAND(CmdIncreaseLoan);
    00116 DEF_COMMAND(CmdDecreaseLoan);
    00117
    00118 DEF_COMMAND(CmdWantEnginePreview);
    00119
    00120 DEF_COMMAND(CmdRenameVehicle);
    00121 DEF_COMMAND(CmdRenameEngine);
    00122
    00123 DEF_COMMAND(CmdRenameCompany);
    00124 DEF_COMMAND(CmdRenamePresident);
    00125
    00126 DEF_COMMAND(CmdRenameStation);
    00127
    00128 DEF_COMMAND(CmdSellAircraft);
    00129 DEF_COMMAND(CmdBuildAircraft);
    00130 DEF_COMMAND(CmdSendAircraftToHangar);
    00131 DEF_COMMAND(CmdRefitAircraft);
    00132
    00133 DEF_COMMAND(CmdPlaceSign);
    00134 DEF_COMMAND(CmdRenameSign);
    00135
    00136 DEF_COMMAND(CmdBuildRoadVeh);
    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(CmdFoundTown);
    00149
    00150 DEF_COMMAND(CmdRenameTown);
    00151 DEF_COMMAND(CmdDoTownAction);
    00152
    00153 DEF_COMMAND(CmdChangeSetting);
    00154 DEF_COMMAND(CmdChangeCompanySetting);
    00155
    00156 DEF_COMMAND(CmdSellShip);
    00157 DEF_COMMAND(CmdBuildShip);
    00158 DEF_COMMAND(CmdSendShipToDepot);
    00159 DEF_COMMAND(CmdRefitShip);
    00160
    00161 DEF_COMMAND(CmdOrderRefit);
    00162 DEF_COMMAND(CmdCloneOrder);
    00163
    00164 DEF_COMMAND(CmdClearArea);
    00165
    00166 DEF_COMMAND(CmdGiveMoney);
    00167 DEF_COMMAND(CmdMoneyCheat);
    00168 DEF_COMMAND(CmdBuildCanal);
    00169 DEF_COMMAND(CmdBuildLock);
    00170
    00171 DEF_COMMAND(CmdCompanyCtrl);
    00172
    00173 DEF_COMMAND(CmdLevelLand);
    00174
    00175 DEF_COMMAND(CmdRefitRailVehicle);
    00176
    00177 DEF_COMMAND(CmdBuildSignalTrack);
    00178 DEF_COMMAND(CmdRemoveSignalTrack);
    00179
    00180 DEF_COMMAND(CmdSetAutoReplace);
    00181
    00182 DEF_COMMAND(CmdCloneVehicle);
    00183 DEF_COMMAND(CmdStartStopVehicle);
    00184 DEF_COMMAND(CmdMassStartStopVehicle);
    00185 DEF_COMMAND(CmdAutoreplaceVehicle);
    00186 DEF_COMMAND(CmdDepotSellAllVehicles);
    00187 DEF_COMMAND(CmdDepotMassAutoReplace);
    00188
    00189 DEF_COMMAND(CmdCreateGroup);
    00190 DEF_COMMAND(CmdRenameGroup);
    00191 DEF_COMMAND(CmdDeleteGroup);
    00192 DEF_COMMAND(CmdAddVehicleGroup);
    00193 DEF_COMMAND(CmdAddSharedVehicleGroup);
    00194 DEF_COMMAND(CmdRemoveAllVehiclesGroup);
    00195 DEF_COMMAND(CmdSetGroupReplaceProtection);
    00196
    00197 DEF_COMMAND(CmdMoveOrder);
    00198 DEF_COMMAND(CmdChangeTimetable);
    00199 DEF_COMMAND(CmdSetVehicleOnTime);
    00200 DEF_COMMAND(CmdAutofillTimetable);
    00201 DEF_COMMAND(CmdSetTimetableStart);
    00202 #undef DEF_COMMAND
    00203
    00211 static const Command _command_proc_table[] = {
    00212   {CmdBuildRailroadTrack,   CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_RAILROAD_TRACK
    00213   {CmdRemoveRailroadTrack,                 CMD_AUTO}, // CMD_REMOVE_RAILROAD_TRACK
    00214   {CmdBuildSingleRail,      CMD_NO_WATER | 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   {CmdBuildRailStation,     CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_RAIL_STATION
    00219   {CmdBuildTrainDepot,      CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_TRAIN_DEPOT
    00220   {CmdBuildSingleSignal,                   CMD_AUTO}, // CMD_BUILD_SIGNALS
    00221   {CmdRemoveSingleSignal,                  CMD_AUTO}, // CMD_REMOVE_SIGNALS
    00222   {CmdTerraformLand,       CMD_ALL_TILES | CMD_AUTO}, // CMD_TERRAFORM_LAND
    00223   {CmdPurchaseLandArea,     CMD_NO_WATER | CMD_AUTO}, // CMD_PURCHASE_LAND_AREA
    00224   {CmdSellLandArea,                               0}, // CMD_SELL_LAND_AREA
    00225   {CmdBuildTunnel,                         CMD_AUTO}, // CMD_BUILD_TUNNEL
    00226   {CmdRemoveFromRailStation,                      0}, // CMD_REMOVE_FROM_RAIL_STATION
    00227   {CmdConvertRail,                                0}, // CMD_CONVERT_RAILD
    00228   {CmdBuildRailWaypoint,                          0}, // CMD_BUILD_RAIL_WAYPOINT
    00229   {CmdRenameWaypoint,                             0}, // CMD_RENAME_WAYPOINT
    00230   {CmdRemoveFromRailWaypoint,                     0}, // CMD_REMOVE_FROM_RAIL_WAYPOINT
    00231
    00232   {CmdBuildRoadStop,        CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_ROAD_STOP
    00233   {CmdRemoveRoadStop,                             0}, // CMD_REMOVE_ROAD_STOP
    00234   {CmdBuildLongRoad,        CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_LONG_ROAD
    00235   {CmdRemoveLongRoad,        CMD_NO_TEST | CMD_AUTO}, // CMD_REMOVE_LONG_ROAD; towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed.
    00236   {CmdBuildRoad,                                  0}, // CMD_BUILD_ROAD
    00237   {CmdRemoveRoad,                                 0}, // CMD_REMOVE_ROAD
    00238   {CmdBuildRoadDepot,       CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_ROAD_DEPOT
    00239
    00240   {CmdBuildAirport,         CMD_NO_WATER | 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
    00248   {CmdSellRailWagon,                              0}, // CMD_SELL_RAIL_WAGON
    00249   {CmdSendTrainToDepot,                           0}, // CMD_SEND_TRAIN_TO_DEPOT
    00250   {CmdForceTrainProceed,                          0}, // CMD_FORCE_TRAIN_PROCEED
    00251   {CmdReverseTrainDirection,                      0}, // CMD_REVERSE_TRAIN_DIRECTION
    00252
    00253   {CmdModifyOrder,                                0}, // CMD_MODIFY_ORDER
    00254   {CmdSkipToOrder,                                0}, // CMD_SKIP_TO_ORDER
    00255   {CmdDeleteOrder,                                0}, // CMD_DELETE_ORDER
    00256   {CmdInsertOrder,                                0}, // CMD_INSERT_ORDER
    00257
    00258   {CmdChangeServiceInt,                           0}, // CMD_CHANGE_SERVICE_INT
    00259
    00260   {CmdBuildIndustry,                              0}, // CMD_BUILD_INDUSTRY
    00261   {CmdBuildCompanyHQ,       CMD_NO_WATER | CMD_AUTO}, // CMD_BUILD_COMPANY_HQ
    00262   {CmdSetCompanyManagerFace,                      0}, // CMD_SET_COMPANY_MANAGER_FACE
    00263   {CmdSetCompanyColour,                           0}, // CMD_SET_COMPANY_COLOUR
    00264
    00265   {CmdIncreaseLoan,                               0}, // CMD_INCREASE_LOAN
    00266   {CmdDecreaseLoan,                               0}, // CMD_DECREASE_LOAN
    00267
    00268   {CmdWantEnginePreview,                          0}, // CMD_WANT_ENGINE_PREVIEW
    00269
    00270   {CmdRenameVehicle,                              0}, // CMD_RENAME_VEHICLE
    00271   {CmdRenameEngine,                               0}, // CMD_RENAME_ENGINE
    00272
    00273   {CmdRenameCompany,                              0}, // CMD_RENAME_COMPANY
    00274   {CmdRenamePresident,                            0}, // CMD_RENAME_PRESIDENT
    00275
    00276   {CmdRenameStation,                              0}, // CMD_RENAME_STATION
    00277
    00278   {CmdSellAircraft,                               0}, // CMD_SELL_AIRCRAFT
    00279
    00280   {CmdBuildAircraft,                              0}, // CMD_BUILD_AIRCRAFT
    00281   {CmdSendAircraftToHangar,                       0}, // CMD_SEND_AIRCRAFT_TO_HANGAR
    00282   {CmdRefitAircraft,                              0}, // CMD_REFIT_AIRCRAFT
    00283
    00284   {CmdPlaceSign,                                  0}, // CMD_PLACE_SIGN
    00285   {CmdRenameSign,                                 0}, // CMD_RENAME_SIGN
    00286
    00287   {CmdBuildRoadVeh,                               0}, // CMD_BUILD_ROAD_VEH
    00288   {CmdSellRoadVeh,                                0}, // CMD_SELL_ROAD_VEH
    00289   {CmdSendRoadVehToDepot,                         0}, // CMD_SEND_ROADVEH_TO_DEPOT
    00290   {CmdTurnRoadVeh,                                0}, // CMD_TURN_ROADVEH
    00291   {CmdRefitRoadVeh,                               0}, // CMD_REFIT_ROAD_VEH
    00292
    00293   {CmdPause,                             CMD_SERVER}, // CMD_PAUSE
    00294
    00295   {CmdBuyShareInCompany,                          0}, // CMD_BUY_SHARE_IN_COMPANY
    00296   {CmdSellShareInCompany,                         0}, // CMD_SELL_SHARE_IN_COMPANY
    00297   {CmdBuyCompany,                                 0}, // CMD_BUY_COMANY
    00298
    00299   {CmdFoundTown,                        CMD_NO_TEST}, // CMD_FOUND_TOWN; founding random town can fail only in exec run
    00300   {CmdRenameTown,                        CMD_SERVER}, // CMD_RENAME_TOWN
    00301   {CmdDoTownAction,                               0}, // CMD_DO_TOWN_ACTION
    00302
    00303   {CmdSellShip,                                   0}, // CMD_SELL_SHIP
    00304   {CmdBuildShip,                                  0}, // CMD_BUILD_SHIP
    00305   {CmdSendShipToDepot,                            0}, // CMD_SEND_SHIP_TO_DEPOT
    00306   {CmdRefitShip,                                  0}, // CMD_REFIT_SHIP
    00307
    00308   {CmdOrderRefit,                                 0}, // CMD_ORDER_REFIT
    00309   {CmdCloneOrder,                                 0}, // CMD_CLONE_ORDER
    00310
    00311   {CmdClearArea,                        CMD_NO_TEST}, // CMD_CLEAR_AREA; destroying multi-tile houses makes town rating differ between test and execution
    00312
    00313   {CmdMoneyCheat,                       CMD_OFFLINE}, // CMD_MONEY_CHEAT
    00314   {CmdBuildCanal,                          CMD_AUTO}, // CMD_BUILD_CANAL
    00315   {CmdCompanyCtrl,                    CMD_SPECTATOR}, // CMD_COMPANY_CTRL
    00316
    00317   {CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO}, // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once
    00318
    00319   {CmdRefitRailVehicle,                           0}, // CMD_REFIT_RAIL_VEHICLE
    00320   {CmdRestoreOrderIndex,                          0}, // CMD_RESTORE_ORDER_INDEX
    00321   {CmdBuildLock,                           CMD_AUTO}, // CMD_BUILD_LOCK
    00322
    00323   {CmdBuildSignalTrack,                    CMD_AUTO}, // CMD_BUILD_SIGNAL_TRACK
    00324   {CmdRemoveSignalTrack,                   CMD_AUTO}, // CMD_REMOVE_SIGNAL_TRACK
    00325
    00326   {CmdGiveMoney,                                  0}, // CMD_GIVE_MONEY
    00327   {CmdChangeSetting,                     CMD_SERVER}, // CMD_CHANGE_SETTING
    00328   {CmdChangeCompanySetting,                       0}, // CMD_CHANGE_COMPANY_SETTING
    00329   {CmdSetAutoReplace,                             0}, // CMD_SET_AUTOREPLACE
    00330   {CmdCloneVehicle,                     CMD_NO_TEST}, // CMD_CLONE_VEHICLE; NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost
    00331   {CmdStartStopVehicle,                           0}, // CMD_START_STOP_VEHICLE
    00332   {CmdMassStartStopVehicle,                       0}, // CMD_MASS_START_STOP
    00333   {CmdAutoreplaceVehicle,                         0}, // CMD_AUTOREPLACE_VEHICLE
    00334   {CmdDepotSellAllVehicles,                       0}, // CMD_DEPOT_SELL_ALL_VEHICLES
    00335   {CmdDepotMassAutoReplace,                       0}, // CMD_DEPOT_MASS_AUTOREPLACE
    00336   {CmdCreateGroup,                                0}, // CMD_CREATE_GROUP
    00337   {CmdDeleteGroup,                                0}, // CMD_DELETE_GROUP
    00338   {CmdRenameGroup,                                0}, // CMD_RENAME_GROUP
    00339   {CmdAddVehicleGroup,                            0}, // CMD_ADD_VEHICLE_GROUP
    00340   {CmdAddSharedVehicleGroup,                      0}, // CMD_ADD_SHARE_VEHICLE_GROUP
    00341   {CmdRemoveAllVehiclesGroup,                     0}, // CMD_REMOVE_ALL_VEHICLES_GROUP
    00342   {CmdSetGroupReplaceProtection,                  0}, // CMD_SET_GROUP_REPLACE_PROTECTION
    00343   {CmdMoveOrder,                                  0}, // CMD_MOVE_ORDER
    00344   {CmdChangeTimetable,                            0}, // CMD_CHANGE_TIMETABLE
    00345   {CmdSetVehicleOnTime,                           0}, // CMD_SET_VEHICLE_ON_TIME
    00346   {CmdAutofillTimetable,                          0}, // CMD_AUTOFILL_TIMETABLE
    00347   {CmdSetTimetableStart,                          0}, // CMD_SET_TIMETABLE_START
    00348 };
    00349
    00356 bool IsValidCommand(uint32 cmd)
    00357 {
    00358   cmd &= CMD_ID_MASK;
    00359
    00360   return
    00361     cmd < lengthof(_command_proc_table) &&
    00362     _command_proc_table[cmd].proc != NULL;
    00363 }
    00364
    00372 byte GetCommandFlags(uint32 cmd)
    00373 {
    00374   assert(IsValidCommand(cmd));
    00375
    00376   return _command_proc_table[cmd & CMD_ID_MASK].flags;
    00377 }
    00378
    00379 static int _docommand_recursive = 0;
    00380
    00389 CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
    00390 {
    00391   return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text);
    00392 }
    00393
    00407 CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
    00408 {
    00409   CommandCost res;
    00410
    00411   /* Do not even think about executing out-of-bounds tile-commands */
    00412   if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
    00413
    00414   /* Chop of any CMD_MSG or other flags; we don't need those here */
    00415   CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
    00416
    00417   if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
    00418
    00419   _docommand_recursive++;
    00420
    00421   /* only execute the test call if it's toplevel, or we're not execing. */
    00422   if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
    00423     SetTownRatingTestMode(true);
    00424     res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
    00425     SetTownRatingTestMode(false);
    00426     if (CmdFailed(res)) {
    00427       res.SetGlobalErrorMessage();
    00428       goto error;
    00429     }
    00430
    00431     if (_docommand_recursive == 1 &&
    00432         !(flags & DC_QUERY_COST) &&
    00433         !(flags & DC_BANKRUPT) &&
    00434         res.GetCost() != 0 &&
    00435         !CheckCompanyHasMoney(res)) {
    00436       goto error;
    00437     }
    00438
    00439     if (!(flags & DC_EXEC)) {
    00440       _docommand_recursive--;
    00441       return res;
    00442     }
    00443   }
    00444
    00445   /* Execute the command here. All cost-relevant functions set the expenses type
    00446    * themselves to the cost object at some point */
    00447   res = proc(tile, flags, p1, p2, text);
    00448   if (CmdFailed(res)) {
    00449     res.SetGlobalErrorMessage();
    00450 error:
    00451     _docommand_recursive--;
    00452     return CMD_ERROR;
    00453   }
    00454
    00455   /* if toplevel, subtract the money. */
    00456   if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
    00457     SubtractMoneyFromCompany(res);
    00458   }
    00459
    00460   return res;
    00461 }
    00462
    00470 Money GetAvailableMoneyForCommand()
    00471 {
    00472   CompanyID company = _current_company;
    00473   if (!Company::IsValidID(company)) return INT64_MAX;
    00474   return Company::Get(company)->money;
    00475 }
    00476
    00483 bool DoCommandP(const CommandContainer *container, bool my_cmd)
    00484 {
    00485   return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd);
    00486 }
    00487
    00503 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd)
    00504 {
    00505   assert(_docommand_recursive == 0);
    00506
    00507   CommandCost res, res2;
    00508
    00509   int x = TileX(tile) * TILE_SIZE;
    00510   int y = TileY(tile) * TILE_SIZE;
    00511
    00512   _error_message = INVALID_STRING_ID;
    00513   StringID error_part1 = GB(cmd, 16, 16);
    00514   _additional_cash_required = 0;
    00515
    00516   /* get pointer to command handler */
    00517   byte cmd_id = cmd & CMD_ID_MASK;
    00518   assert(cmd_id < lengthof(_command_proc_table));
    00519
    00520   CommandProc *proc = _command_proc_table[cmd_id].proc;
    00521   if (proc == NULL) return false;
    00522
    00523   /* Command flags are used internally */
    00524   uint cmd_flags = GetCommandFlags(cmd);
    00525   /* Flags get send to the DoCommand */
    00526   DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
    00527
    00528   /* Do not even think about executing out-of-bounds tile-commands */
    00529   if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (cmd_flags & CMD_ALL_TILES) == 0))) return false;
    00530
    00531   /* Always execute server and spectator commands as spectator */
    00532   if (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) _current_company = COMPANY_SPECTATOR;
    00533
    00534   CompanyID old_company = _current_company;
    00535
    00536   /* If the company isn't valid it may only do server command or start a new company!
    00537    * The server will ditch any server commands a client sends to it, so effectively
    00538    * this guards the server from executing functions for an invalid company. */
    00539   if (_game_mode == GM_NORMAL && (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) == 0 && !Company::IsValidID(_current_company)) {
    00540     if (my_cmd) ShowErrorMessage(error_part1, _error_message, x, y);
    00541     return false;
    00542   }
    00543
    00544   bool notest = (cmd_flags & CMD_NO_TEST) != 0;
    00545
    00546   _docommand_recursive = 1;
    00547
    00548   /* cost estimation only? */
    00549   if (!IsGeneratingWorld() &&
    00550       _shift_pressed &&
    00551       IsLocalCompany() &&
    00552       !(cmd & CMD_NETWORK_COMMAND) &&
    00553       cmd_id != CMD_PAUSE) {
    00554     /* estimate the cost. */
    00555     SetTownRatingTestMode(true);
    00556     res = proc(tile, flags, p1, p2, text);
    00557     SetTownRatingTestMode(false);
    00558     if (CmdFailed(res)) {
    00559       res.SetGlobalErrorMessage();
    00560       ShowErrorMessage(error_part1, _error_message, x, y);
    00561     } else {
    00562       ShowEstimatedCostOrIncome(res.GetCost(), x, y);
    00563     }
    00564
    00565     _docommand_recursive = 0;
    00566     ClearStorageChanges(false);
    00567     return false;
    00568   }
    00569
    00570
    00571   if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
    00572     /* first test if the command can be executed. */
    00573     SetTownRatingTestMode(true);
    00574     res = proc(tile, flags, p1, p2, text);
    00575     SetTownRatingTestMode(false);
    00576     assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
    00577     if (CmdFailed(res)) {
    00578       res.SetGlobalErrorMessage();
    00579       goto show_error;
    00580     }
    00581     /* no money? Only check if notest is off */
    00582     if (!notest && res.GetCost() != 0 && !CheckCompanyHasMoney(res)) goto show_error;
    00583   }
    00584
    00585 #ifdef ENABLE_NETWORK
    00586   /*
    00587    * If we are in network, and the command is not from the network
    00588    * send it to the command-queue and abort execution
    00589    */
    00590   if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
    00591     NetworkSend_Command(tile, p1, p2, cmd & ~CMD_FLAGS_MASK, callback, text);
    00592     _docommand_recursive = 0;
    00593     ClearStorageChanges(false);
    00594     return true;
    00595   }
    00596 #endif /* ENABLE_NETWORK */
    00597   DEBUG(desync, 1, "cmd: %08x; %08x; %1x; %06x; %08x; %08x; %04x; %s\n", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text);
    00598
    00599   /* update last build coordinate of company. */
    00600   if (tile != 0) {
    00601     Company *c = Company::GetIfValid(_current_company);
    00602     if (c != NULL) c->last_build_coordinate = tile;
    00603   }
    00604
    00605   /* Actually try and execute the command. If no cost-type is given
    00606    * use the construction one */
    00607   res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
    00608
    00609   assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
    00610
    00611   /* If notest is on, it means the result of the test can be different than
    00612    *  the real command.. so ignore the test */
    00613   if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
    00614     assert(res.GetCost() == res2.GetCost() && CmdFailed(res) == CmdFailed(res2)); // sanity check
    00615   } else {
    00616     if (CmdFailed(res2)) {
    00617       res2.SetGlobalErrorMessage();
    00618       goto show_error;
    00619     }
    00620   }
    00621
    00622   SubtractMoneyFromCompany(res2);
    00623
    00624   /* update signals if needed */
    00625   UpdateSignalsInBuffer();
    00626
    00627   if (IsLocalCompany() && _game_mode != GM_EDITOR) {
    00628     if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost());
    00629     if (_additional_cash_required != 0) {
    00630       SetDParam(0, _additional_cash_required);
    00631       if (my_cmd) ShowErrorMessage(error_part1, STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY, x, y);
    00632       if (res2.GetCost() == 0) goto callb_err;
    00633     }
    00634   }
    00635
    00636   _docommand_recursive = 0;
    00637
    00638   if (callback) callback(true, tile, p1, p2);
    00639   ClearStorageChanges(true);
    00640   return true;
    00641
    00642 show_error:
    00643   /* show error message if the command fails? */
    00644   if (IsLocalCompany() && error_part1 != 0 && my_cmd) {
    00645     ShowErrorMessage(error_part1, _error_message, x, y);
    00646   }
    00647
    00648 callb_err:
    00649   _docommand_recursive = 0;
    00650
    00651   if (callback) callback(false, tile, p1, p2);
    00652   ClearStorageChanges(false);
    00653   return false;
    00654 }
    00655
    00656
    00657 CommandCost CommandCost::AddCost(CommandCost ret)
    00658 {
    00659   this->AddCost(ret.cost);
    00660   if (this->success && !ret.success) {
    00661     this->message = ret.message;
    00662     this->success = false;
    00663   }
    00664   return *this;
    00665 }