00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "landscape.h"
00014 #include "gui.h"
00015 #include "command_func.h"
00016 #include "network/network_type.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 "texteff.hpp"
00023 #include "town.h"
00024 #include "date_func.h"
00025 #include "company_func.h"
00026 #include "company_base.h"
00027 #include "signal_func.h"
00028 #include "core/backup_type.hpp"
00029 #include "object_base.h"
00030
00031 #include "table/strings.h"
00032
00033 CommandProc CmdBuildRailroadTrack;
00034 CommandProc CmdRemoveRailroadTrack;
00035 CommandProc CmdBuildSingleRail;
00036 CommandProc CmdRemoveSingleRail;
00037
00038 CommandProc CmdLandscapeClear;
00039
00040 CommandProc CmdBuildBridge;
00041
00042 CommandProc CmdBuildRailStation;
00043 CommandProc CmdRemoveFromRailStation;
00044 CommandProc CmdConvertRail;
00045
00046 CommandProc CmdBuildSingleSignal;
00047 CommandProc CmdRemoveSingleSignal;
00048
00049 CommandProc CmdTerraformLand;
00050
00051 CommandProc CmdBuildObject;
00052 CommandProc CmdSellLandArea;
00053
00054 CommandProc CmdBuildTunnel;
00055
00056 CommandProc CmdBuildTrainDepot;
00057 CommandProc CmdBuildRailWaypoint;
00058 CommandProc CmdRenameWaypoint;
00059 CommandProc CmdRemoveFromRailWaypoint;
00060
00061 CommandProc CmdBuildRoadStop;
00062 CommandProc CmdRemoveRoadStop;
00063
00064 CommandProc CmdBuildLongRoad;
00065 CommandProc CmdRemoveLongRoad;
00066 CommandProc CmdBuildRoad;
00067
00068 CommandProc CmdBuildRoadDepot;
00069
00070 CommandProc CmdBuildAirport;
00071
00072 CommandProc CmdBuildDock;
00073
00074 CommandProc CmdBuildShipDepot;
00075
00076 CommandProc CmdBuildBuoy;
00077
00078 CommandProc CmdPlantTree;
00079
00080 CommandProc CmdMoveRailVehicle;
00081
00082 CommandProc CmdBuildVehicle;
00083 CommandProc CmdSellVehicle;
00084 CommandProc CmdRefitVehicle;
00085 CommandProc CmdSendVehicleToDepot;
00086
00087 CommandProc CmdForceTrainProceed;
00088 CommandProc CmdReverseTrainDirection;
00089
00090 CommandProc CmdClearOrderBackup;
00091 CommandProc CmdModifyOrder;
00092 CommandProc CmdSkipToOrder;
00093 CommandProc CmdDeleteOrder;
00094 CommandProc CmdInsertOrder;
00095 CommandProc CmdChangeServiceInt;
00096
00097 CommandProc CmdBuildIndustry;
00098
00099 CommandProc CmdSetCompanyManagerFace;
00100 CommandProc CmdSetCompanyColour;
00101
00102 CommandProc CmdIncreaseLoan;
00103 CommandProc CmdDecreaseLoan;
00104
00105 CommandProc CmdWantEnginePreview;
00106
00107 CommandProc CmdRenameVehicle;
00108 CommandProc CmdRenameEngine;
00109
00110 CommandProc CmdRenameCompany;
00111 CommandProc CmdRenamePresident;
00112
00113 CommandProc CmdRenameStation;
00114 CommandProc CmdRenameDepot;
00115
00116 CommandProc CmdPlaceSign;
00117 CommandProc CmdRenameSign;
00118
00119 CommandProc CmdTurnRoadVeh;
00120
00121 CommandProc CmdPause;
00122
00123 CommandProc CmdBuyShareInCompany;
00124 CommandProc CmdSellShareInCompany;
00125 CommandProc CmdBuyCompany;
00126
00127 CommandProc CmdFoundTown;
00128 CommandProc CmdRenameTown;
00129 CommandProc CmdDoTownAction;
00130 CommandProc CmdExpandTown;
00131 CommandProc CmdDeleteTown;
00132
00133 CommandProc CmdChangeSetting;
00134 CommandProc CmdChangeCompanySetting;
00135
00136 CommandProc CmdOrderRefit;
00137 CommandProc CmdCloneOrder;
00138
00139 CommandProc CmdClearArea;
00140
00141 CommandProc CmdGiveMoney;
00142 CommandProc CmdMoneyCheat;
00143 CommandProc CmdBuildCanal;
00144 CommandProc CmdBuildLock;
00145
00146 CommandProc CmdCompanyCtrl;
00147
00148 CommandProc CmdLevelLand;
00149
00150 CommandProc CmdBuildSignalTrack;
00151 CommandProc CmdRemoveSignalTrack;
00152
00153 CommandProc CmdSetAutoReplace;
00154
00155 CommandProc CmdCloneVehicle;
00156 CommandProc CmdStartStopVehicle;
00157 CommandProc CmdMassStartStopVehicle;
00158 CommandProc CmdAutoreplaceVehicle;
00159 CommandProc CmdDepotSellAllVehicles;
00160 CommandProc CmdDepotMassAutoReplace;
00161
00162 CommandProc CmdCreateGroup;
00163 CommandProc CmdRenameGroup;
00164 CommandProc CmdDeleteGroup;
00165 CommandProc CmdAddVehicleGroup;
00166 CommandProc CmdAddSharedVehicleGroup;
00167 CommandProc CmdRemoveAllVehiclesGroup;
00168 CommandProc CmdSetGroupReplaceProtection;
00169
00170 CommandProc CmdMoveOrder;
00171 CommandProc CmdChangeTimetable;
00172 CommandProc CmdSetVehicleOnTime;
00173 CommandProc CmdAutofillTimetable;
00174 CommandProc CmdSetTimetableStart;
00175
00176 #define DEF_CMD(proc, flags, type) {proc, #proc, flags, type}
00177
00185 static const Command _command_proc_table[] = {
00186 DEF_CMD(CmdBuildRailroadTrack, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00187 DEF_CMD(CmdRemoveRailroadTrack, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00188 DEF_CMD(CmdBuildSingleRail, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00189 DEF_CMD(CmdRemoveSingleRail, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00190 DEF_CMD(CmdLandscapeClear, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00191 DEF_CMD(CmdBuildBridge, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00192 DEF_CMD(CmdBuildRailStation, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00193 DEF_CMD(CmdBuildTrainDepot, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00194 DEF_CMD(CmdBuildSingleSignal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00195 DEF_CMD(CmdRemoveSingleSignal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00196 DEF_CMD(CmdTerraformLand, CMD_ALL_TILES | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00197 DEF_CMD(CmdBuildObject, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00198 DEF_CMD(CmdBuildTunnel, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00199 DEF_CMD(CmdRemoveFromRailStation, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00200 DEF_CMD(CmdConvertRail, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00201 DEF_CMD(CmdBuildRailWaypoint, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00202 DEF_CMD(CmdRenameWaypoint, 0, CMDT_OTHER_MANAGEMENT ),
00203 DEF_CMD(CmdRemoveFromRailWaypoint, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00204
00205 DEF_CMD(CmdBuildRoadStop, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00206 DEF_CMD(CmdRemoveRoadStop, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00207 DEF_CMD(CmdBuildLongRoad, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00208 DEF_CMD(CmdRemoveLongRoad, CMD_NO_TEST | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00209 DEF_CMD(CmdBuildRoad, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00210 DEF_CMD(CmdBuildRoadDepot, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00211
00212 DEF_CMD(CmdBuildAirport, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00213 DEF_CMD(CmdBuildDock, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00214 DEF_CMD(CmdBuildShipDepot, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00215 DEF_CMD(CmdBuildBuoy, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00216 DEF_CMD(CmdPlantTree, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00217
00218 DEF_CMD(CmdBuildVehicle, CMD_CLIENT_ID, CMDT_VEHICLE_CONSTRUCTION ),
00219 DEF_CMD(CmdSellVehicle, CMD_CLIENT_ID, CMDT_VEHICLE_CONSTRUCTION ),
00220 DEF_CMD(CmdRefitVehicle, 0, CMDT_VEHICLE_CONSTRUCTION ),
00221 DEF_CMD(CmdSendVehicleToDepot, 0, CMDT_VEHICLE_MANAGEMENT ),
00222
00223 DEF_CMD(CmdMoveRailVehicle, 0, CMDT_VEHICLE_CONSTRUCTION ),
00224 DEF_CMD(CmdForceTrainProceed, 0, CMDT_VEHICLE_MANAGEMENT ),
00225 DEF_CMD(CmdReverseTrainDirection, 0, CMDT_VEHICLE_MANAGEMENT ),
00226
00227 DEF_CMD(CmdClearOrderBackup, CMD_CLIENT_ID, CMDT_ROUTE_MANAGEMENT ),
00228 DEF_CMD(CmdModifyOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00229 DEF_CMD(CmdSkipToOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00230 DEF_CMD(CmdDeleteOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00231 DEF_CMD(CmdInsertOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00232
00233 DEF_CMD(CmdChangeServiceInt, 0, CMDT_VEHICLE_MANAGEMENT ),
00234
00235 DEF_CMD(CmdBuildIndustry, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00236 DEF_CMD(CmdSetCompanyManagerFace, 0, CMDT_OTHER_MANAGEMENT ),
00237 DEF_CMD(CmdSetCompanyColour, 0, CMDT_OTHER_MANAGEMENT ),
00238
00239 DEF_CMD(CmdIncreaseLoan, 0, CMDT_MONEY_MANAGEMENT ),
00240 DEF_CMD(CmdDecreaseLoan, 0, CMDT_MONEY_MANAGEMENT ),
00241
00242 DEF_CMD(CmdWantEnginePreview, 0, CMDT_VEHICLE_MANAGEMENT ),
00243
00244 DEF_CMD(CmdRenameVehicle, 0, CMDT_OTHER_MANAGEMENT ),
00245 DEF_CMD(CmdRenameEngine, 0, CMDT_OTHER_MANAGEMENT ),
00246
00247 DEF_CMD(CmdRenameCompany, 0, CMDT_OTHER_MANAGEMENT ),
00248 DEF_CMD(CmdRenamePresident, 0, CMDT_OTHER_MANAGEMENT ),
00249
00250 DEF_CMD(CmdRenameStation, 0, CMDT_OTHER_MANAGEMENT ),
00251 DEF_CMD(CmdRenameDepot, 0, CMDT_OTHER_MANAGEMENT ),
00252
00253 DEF_CMD(CmdPlaceSign, 0, CMDT_OTHER_MANAGEMENT ),
00254 DEF_CMD(CmdRenameSign, 0, CMDT_OTHER_MANAGEMENT ),
00255
00256 DEF_CMD(CmdTurnRoadVeh, 0, CMDT_VEHICLE_MANAGEMENT ),
00257
00258 DEF_CMD(CmdPause, CMD_SERVER, CMDT_SERVER_SETTING ),
00259
00260 DEF_CMD(CmdBuyShareInCompany, 0, CMDT_MONEY_MANAGEMENT ),
00261 DEF_CMD(CmdSellShareInCompany, 0, CMDT_MONEY_MANAGEMENT ),
00262 DEF_CMD(CmdBuyCompany, 0, CMDT_MONEY_MANAGEMENT ),
00263
00264 DEF_CMD(CmdFoundTown, CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION),
00265 DEF_CMD(CmdRenameTown, CMD_SERVER, CMDT_OTHER_MANAGEMENT ),
00266 DEF_CMD(CmdDoTownAction, 0, CMDT_LANDSCAPE_CONSTRUCTION),
00267 DEF_CMD(CmdExpandTown, CMD_OFFLINE, CMDT_LANDSCAPE_CONSTRUCTION),
00268 DEF_CMD(CmdDeleteTown, CMD_OFFLINE, CMDT_LANDSCAPE_CONSTRUCTION),
00269
00270 DEF_CMD(CmdOrderRefit, 0, CMDT_ROUTE_MANAGEMENT ),
00271 DEF_CMD(CmdCloneOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00272
00273 DEF_CMD(CmdClearArea, CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION),
00274
00275 DEF_CMD(CmdMoneyCheat, CMD_OFFLINE, CMDT_CHEAT ),
00276 DEF_CMD(CmdBuildCanal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00277 DEF_CMD(CmdCompanyCtrl, CMD_SPECTATOR | CMD_CLIENT_ID, CMDT_SERVER_SETTING ),
00278
00279 DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00280
00281 DEF_CMD(CmdBuildLock, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00282
00283 DEF_CMD(CmdBuildSignalTrack, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00284 DEF_CMD(CmdRemoveSignalTrack, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION),
00285
00286 DEF_CMD(CmdGiveMoney, 0, CMDT_MONEY_MANAGEMENT ),
00287 DEF_CMD(CmdChangeSetting, CMD_SERVER, CMDT_SERVER_SETTING ),
00288 DEF_CMD(CmdChangeCompanySetting, 0, CMDT_COMPANY_SETTING ),
00289 DEF_CMD(CmdSetAutoReplace, 0, CMDT_VEHICLE_MANAGEMENT ),
00290 DEF_CMD(CmdCloneVehicle, CMD_NO_TEST, CMDT_VEHICLE_CONSTRUCTION ),
00291 DEF_CMD(CmdStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ),
00292 DEF_CMD(CmdMassStartStopVehicle, 0, CMDT_VEHICLE_MANAGEMENT ),
00293 DEF_CMD(CmdAutoreplaceVehicle, 0, CMDT_VEHICLE_MANAGEMENT ),
00294 DEF_CMD(CmdDepotSellAllVehicles, 0, CMDT_VEHICLE_CONSTRUCTION ),
00295 DEF_CMD(CmdDepotMassAutoReplace, 0, CMDT_VEHICLE_CONSTRUCTION ),
00296 DEF_CMD(CmdCreateGroup, 0, CMDT_ROUTE_MANAGEMENT ),
00297 DEF_CMD(CmdDeleteGroup, 0, CMDT_ROUTE_MANAGEMENT ),
00298 DEF_CMD(CmdRenameGroup, 0, CMDT_OTHER_MANAGEMENT ),
00299 DEF_CMD(CmdAddVehicleGroup, 0, CMDT_ROUTE_MANAGEMENT ),
00300 DEF_CMD(CmdAddSharedVehicleGroup, 0, CMDT_ROUTE_MANAGEMENT ),
00301 DEF_CMD(CmdRemoveAllVehiclesGroup, 0, CMDT_ROUTE_MANAGEMENT ),
00302 DEF_CMD(CmdSetGroupReplaceProtection, 0, CMDT_ROUTE_MANAGEMENT ),
00303 DEF_CMD(CmdMoveOrder, 0, CMDT_ROUTE_MANAGEMENT ),
00304 DEF_CMD(CmdChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT ),
00305 DEF_CMD(CmdSetVehicleOnTime, 0, CMDT_ROUTE_MANAGEMENT ),
00306 DEF_CMD(CmdAutofillTimetable, 0, CMDT_ROUTE_MANAGEMENT ),
00307 DEF_CMD(CmdSetTimetableStart, 0, CMDT_ROUTE_MANAGEMENT ),
00308 };
00309
00316 bool IsValidCommand(uint32 cmd)
00317 {
00318 cmd &= CMD_ID_MASK;
00319
00320 return cmd < lengthof(_command_proc_table) && _command_proc_table[cmd].proc != NULL;
00321 }
00322
00330 byte GetCommandFlags(uint32 cmd)
00331 {
00332 assert(IsValidCommand(cmd));
00333
00334 return _command_proc_table[cmd & CMD_ID_MASK].flags;
00335 }
00336
00344 const char *GetCommandName(uint32 cmd)
00345 {
00346 assert(IsValidCommand(cmd));
00347
00348 return _command_proc_table[cmd & CMD_ID_MASK].name;
00349 }
00350
00356 bool IsCommandAllowedWhilePaused(uint32 cmd)
00357 {
00358
00359 static const int command_type_lookup[] = {
00360 CMDPL_ALL_ACTIONS,
00361 CMDPL_NO_LANDSCAPING,
00362 CMDPL_NO_LANDSCAPING,
00363 CMDPL_NO_CONSTRUCTION,
00364 CMDPL_NO_CONSTRUCTION,
00365 CMDPL_NO_CONSTRUCTION,
00366 CMDPL_NO_CONSTRUCTION,
00367 CMDPL_NO_ACTIONS,
00368 CMDPL_NO_ACTIONS,
00369 };
00370 assert_compile(lengthof(command_type_lookup) == CMDT_END);
00371
00372 assert(IsValidCommand(cmd));
00373 return _game_mode == GM_EDITOR || command_type_lookup[_command_proc_table[cmd & CMD_ID_MASK].type] <= _settings_game.construction.command_pause_level;
00374 }
00375
00376
00377 static int _docommand_recursive = 0;
00378
00387 CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
00388 {
00389 return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text);
00390 }
00391
00405 CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
00406 {
00407 CommandCost res;
00408
00409
00410 if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
00411
00412
00413 CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
00414
00415 _docommand_recursive++;
00416
00417
00418 if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
00419 if (_docommand_recursive == 1) _cleared_object_areas.Clear();
00420 SetTownRatingTestMode(true);
00421 res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
00422 SetTownRatingTestMode(false);
00423 if (res.Failed()) {
00424 goto error;
00425 }
00426
00427 if (_docommand_recursive == 1 &&
00428 !(flags & DC_QUERY_COST) &&
00429 !(flags & DC_BANKRUPT) &&
00430 !CheckCompanyHasMoney(res)) {
00431 goto error;
00432 }
00433
00434 if (!(flags & DC_EXEC)) {
00435 _docommand_recursive--;
00436 return res;
00437 }
00438 }
00439
00440
00441
00442 if (_docommand_recursive == 1) _cleared_object_areas.Clear();
00443 res = proc(tile, flags, p1, p2, text);
00444 if (res.Failed()) {
00445 error:
00446 _docommand_recursive--;
00447 return res;
00448 }
00449
00450
00451 if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
00452 SubtractMoneyFromCompany(res);
00453 }
00454
00455 return res;
00456 }
00457
00465 Money GetAvailableMoneyForCommand()
00466 {
00467 CompanyID company = _current_company;
00468 if (!Company::IsValidID(company)) return INT64_MAX;
00469 return Company::Get(company)->money;
00470 }
00471
00478 bool DoCommandP(const CommandContainer *container, bool my_cmd)
00479 {
00480 return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd);
00481 }
00482
00498 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd)
00499 {
00500
00501
00502
00503
00504
00505 bool estimate_only = _shift_pressed && IsLocalCompany() &&
00506 !IsGeneratingWorld() &&
00507 !(cmd & CMD_NETWORK_COMMAND) &&
00508 (cmd & CMD_ID_MASK) != CMD_PAUSE;
00509
00510
00511
00512 bool only_sending = _networking && !(cmd & CMD_NETWORK_COMMAND);
00513
00514
00515 int x = TileX(tile) * TILE_SIZE;
00516 int y = TileY(tile) * TILE_SIZE;
00517
00518 if (_pause_mode != PM_UNPAUSED && !IsCommandAllowedWhilePaused(cmd)) {
00519 ShowErrorMessage(GB(cmd, 16, 16), STR_ERROR_NOT_ALLOWED_WHILE_PAUSED, WL_INFO, x, y);
00520 return false;
00521 }
00522
00523 #ifdef ENABLE_NETWORK
00524
00525 if (!(cmd & CMD_NETWORK_COMMAND) && GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = CLIENT_ID_SERVER;
00526 #endif
00527
00528 CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only);
00529 if (res.Failed()) {
00530
00531 StringID error_part1 = GB(cmd, 16, 16);
00532 if (estimate_only || (IsLocalCompany() && error_part1 != 0 && my_cmd)) {
00533 ShowErrorMessage(error_part1, res.GetErrorMessage(), WL_INFO, x, y);
00534 }
00535 } else if (estimate_only) {
00536 ShowEstimatedCostOrIncome(res.GetCost(), x, y);
00537 } else if (!only_sending && res.GetCost() != 0 && tile != 0 && IsLocalCompany() && _game_mode != GM_EDITOR) {
00538
00539
00540
00541
00542
00543 ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res.GetCost());
00544 }
00545
00546 if (!estimate_only && !only_sending && callback != NULL) {
00547 callback(res, tile, p1, p2);
00548 }
00549
00550 return res.Succeeded();
00551 }
00552
00553
00559 #define return_dcpi(cmd, clear) { _docommand_recursive = 0; ClearStorageChanges(clear); return cmd; }
00560
00574 CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only)
00575 {
00576
00577 assert(_docommand_recursive == 0);
00578 _docommand_recursive = 1;
00579
00580
00581 _additional_cash_required = 0;
00582
00583
00584 byte cmd_id = cmd & CMD_ID_MASK;
00585 assert(cmd_id < lengthof(_command_proc_table));
00586
00587 CommandProc *proc = _command_proc_table[cmd_id].proc;
00588
00589
00590 assert(proc != NULL);
00591
00592
00593 uint cmd_flags = GetCommandFlags(cmd);
00594
00595 DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
00596
00597 #ifdef ENABLE_NETWORK
00598
00599 assert(!(cmd_flags & CMD_CLIENT_ID) || p2 != 0);
00600 #endif
00601
00602
00603 if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (cmd_flags & CMD_ALL_TILES) == 0))) return_dcpi(CMD_ERROR, false);
00604
00605
00606 bool exec_as_spectator = (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) != 0;
00607
00608
00609
00610
00611 if (_game_mode == GM_NORMAL && !exec_as_spectator && !Company::IsValidID(_current_company)) {
00612 return_dcpi(CMD_ERROR, false);
00613 }
00614
00615 Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00616 if (exec_as_spectator) cur_company.Change(COMPANY_SPECTATOR);
00617
00618 bool test_and_exec_can_differ = (cmd_flags & CMD_NO_TEST) != 0;
00619 bool skip_test = _networking && (cmd & CMD_NO_TEST_IF_IN_NETWORK) != 0;
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 CommandCost res;
00632 if (estimate_only || !skip_test) {
00633
00634 _cleared_object_areas.Clear();
00635 SetTownRatingTestMode(true);
00636 res = proc(tile, flags, p1, p2, text);
00637 SetTownRatingTestMode(false);
00638
00639
00640 assert(exec_as_spectator ? _current_company == COMPANY_SPECTATOR : cur_company.Verify());
00641
00642
00643
00644
00645
00646
00647 if (res.Failed() || estimate_only ||
00648 (!test_and_exec_can_differ && !CheckCompanyHasMoney(res))) {
00649 cur_company.Restore();
00650 return_dcpi(res, false);
00651 }
00652 }
00653
00654 #ifdef ENABLE_NETWORK
00655
00656
00657
00658
00659 if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
00660 NetworkSendCommand(tile, p1, p2, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company);
00661 cur_company.Restore();
00662
00663
00664
00665
00666
00667 return_dcpi(CommandCost(), false);
00668 }
00669 #endif
00670 DEBUG(desync, 1, "cmd: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \"%s\" (%s)", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd & ~CMD_NETWORK_COMMAND, text, GetCommandName(cmd));
00671
00672
00673
00674 _cleared_object_areas.Clear();
00675 CommandCost res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
00676
00677 if (cmd_id == CMD_COMPANY_CTRL) {
00678 cur_company.Trash();
00679
00680
00681
00682 _current_company = _local_company;
00683 } else {
00684
00685 assert(exec_as_spectator ? _current_company == COMPANY_SPECTATOR : cur_company.Verify());
00686 cur_company.Restore();
00687 }
00688
00689
00690
00691
00692
00693 if (!test_and_exec_can_differ && !skip_test) {
00694 assert(res.GetCost() == res2.GetCost() && res.Failed() == res2.Failed());
00695 } else if (res2.Failed()) {
00696 return_dcpi(res2, false);
00697 }
00698
00699
00700
00701 if (_additional_cash_required != 0 && res2.GetCost() == 0) {
00702
00703
00704 UpdateSignalsInBuffer();
00705 SetDParam(0, _additional_cash_required);
00706 return_dcpi(CommandCost(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY), false);
00707 }
00708
00709
00710 if (tile != 0) {
00711 Company *c = Company::GetIfValid(_current_company);
00712 if (c != NULL) c->last_build_coordinate = tile;
00713 }
00714
00715 SubtractMoneyFromCompany(res2);
00716
00717
00718 UpdateSignalsInBuffer();
00719
00720 return_dcpi(res2, true);
00721 }
00722 #undef return_dcpi
00723
00724
00730 void CommandCost::AddCost(const CommandCost &ret)
00731 {
00732 this->AddCost(ret.cost);
00733 if (this->success && !ret.success) {
00734 this->message = ret.message;
00735 this->success = false;
00736 }
00737 }