00001
00002
00003
00004
00005
00006
00007
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
00034 CommandProc CmdBuildRailroadTrack;
00035 CommandProc CmdRemoveRailroadTrack;
00036 CommandProc CmdBuildSingleRail;
00037 CommandProc CmdRemoveSingleRail;
00038
00039 CommandProc CmdLandscapeClear;
00040
00041 CommandProc CmdBuildBridge;
00042
00043 CommandProc CmdBuildRailStation;
00044 CommandProc CmdRemoveFromRailStation;
00045 CommandProc CmdConvertRail;
00046
00047 CommandProc CmdBuildSingleSignal;
00048 CommandProc CmdRemoveSingleSignal;
00049
00050 CommandProc CmdTerraformLand;
00051
00052 CommandProc CmdPurchaseLandArea;
00053 CommandProc CmdSellLandArea;
00054
00055 CommandProc CmdBuildTunnel;
00056
00057 CommandProc CmdBuildTrainDepot;
00058 CommandProc CmdBuildRailWaypoint;
00059 CommandProc CmdRenameWaypoint;
00060 CommandProc CmdRemoveFromRailWaypoint;
00061
00062 CommandProc CmdBuildRoadStop;
00063 CommandProc CmdRemoveRoadStop;
00064
00065 CommandProc CmdBuildLongRoad;
00066 CommandProc CmdRemoveLongRoad;
00067 CommandProc CmdBuildRoad;
00068 CommandProc CmdRemoveRoad;
00069
00070 CommandProc CmdBuildRoadDepot;
00071
00072 CommandProc CmdBuildAirport;
00073
00074 CommandProc CmdBuildDock;
00075
00076 CommandProc CmdBuildShipDepot;
00077
00078 CommandProc CmdBuildBuoy;
00079
00080 CommandProc CmdPlantTree;
00081
00082 CommandProc CmdBuildRailVehicle;
00083 CommandProc CmdMoveRailVehicle;
00084
00085 CommandProc CmdSellRailWagon;
00086
00087 CommandProc CmdSendTrainToDepot;
00088 CommandProc CmdForceTrainProceed;
00089 CommandProc CmdReverseTrainDirection;
00090
00091 CommandProc CmdModifyOrder;
00092 CommandProc CmdSkipToOrder;
00093 CommandProc CmdDeleteOrder;
00094 CommandProc CmdInsertOrder;
00095 CommandProc CmdChangeServiceInt;
00096 CommandProc CmdRestoreOrderIndex;
00097
00098 CommandProc CmdBuildIndustry;
00099
00100 CommandProc CmdBuildCompanyHQ;
00101 CommandProc CmdSetCompanyManagerFace;
00102 CommandProc CmdSetCompanyColour;
00103
00104 CommandProc CmdIncreaseLoan;
00105 CommandProc CmdDecreaseLoan;
00106
00107 CommandProc CmdWantEnginePreview;
00108
00109 CommandProc CmdRenameVehicle;
00110 CommandProc CmdRenameEngine;
00111
00112 CommandProc CmdRenameCompany;
00113 CommandProc CmdRenamePresident;
00114
00115 CommandProc CmdRenameStation;
00116
00117 CommandProc CmdSellAircraft;
00118 CommandProc CmdBuildAircraft;
00119 CommandProc CmdSendAircraftToHangar;
00120 CommandProc CmdRefitAircraft;
00121
00122 CommandProc CmdPlaceSign;
00123 CommandProc CmdRenameSign;
00124
00125 CommandProc CmdBuildRoadVeh;
00126 CommandProc CmdSellRoadVeh;
00127 CommandProc CmdSendRoadVehToDepot;
00128 CommandProc CmdTurnRoadVeh;
00129 CommandProc CmdRefitRoadVeh;
00130
00131 CommandProc CmdPause;
00132
00133 CommandProc CmdBuyShareInCompany;
00134 CommandProc CmdSellShareInCompany;
00135 CommandProc CmdBuyCompany;
00136
00137 CommandProc CmdFoundTown;
00138
00139 CommandProc CmdRenameTown;
00140 CommandProc CmdDoTownAction;
00141
00142 CommandProc CmdChangeSetting;
00143 CommandProc CmdChangeCompanySetting;
00144
00145 CommandProc CmdSellShip;
00146 CommandProc CmdBuildShip;
00147 CommandProc CmdSendShipToDepot;
00148 CommandProc CmdRefitShip;
00149
00150 CommandProc CmdOrderRefit;
00151 CommandProc CmdCloneOrder;
00152
00153 CommandProc CmdClearArea;
00154
00155 CommandProc CmdGiveMoney;
00156 CommandProc CmdMoneyCheat;
00157 CommandProc CmdBuildCanal;
00158 CommandProc CmdBuildLock;
00159
00160 CommandProc CmdCompanyCtrl;
00161
00162 CommandProc CmdLevelLand;
00163
00164 CommandProc CmdRefitRailVehicle;
00165
00166 CommandProc CmdBuildSignalTrack;
00167 CommandProc CmdRemoveSignalTrack;
00168
00169 CommandProc CmdSetAutoReplace;
00170
00171 CommandProc CmdCloneVehicle;
00172 CommandProc CmdStartStopVehicle;
00173 CommandProc CmdMassStartStopVehicle;
00174 CommandProc CmdAutoreplaceVehicle;
00175 CommandProc CmdDepotSellAllVehicles;
00176 CommandProc CmdDepotMassAutoReplace;
00177
00178 CommandProc CmdCreateGroup;
00179 CommandProc CmdRenameGroup;
00180 CommandProc CmdDeleteGroup;
00181 CommandProc CmdAddVehicleGroup;
00182 CommandProc CmdAddSharedVehicleGroup;
00183 CommandProc CmdRemoveAllVehiclesGroup;
00184 CommandProc CmdSetGroupReplaceProtection;
00185
00186 CommandProc CmdMoveOrder;
00187 CommandProc CmdChangeTimetable;
00188 CommandProc CmdSetVehicleOnTime;
00189 CommandProc CmdAutofillTimetable;
00190 CommandProc CmdSetTimetableStart;
00191
00199 static const Command _command_proc_table[] = {
00200 {CmdBuildRailroadTrack, CMD_NO_WATER | CMD_AUTO},
00201 {CmdRemoveRailroadTrack, CMD_AUTO},
00202 {CmdBuildSingleRail, CMD_NO_WATER | CMD_AUTO},
00203 {CmdRemoveSingleRail, CMD_AUTO},
00204 {CmdLandscapeClear, 0},
00205 {CmdBuildBridge, CMD_AUTO},
00206 {CmdBuildRailStation, CMD_NO_WATER | CMD_AUTO},
00207 {CmdBuildTrainDepot, CMD_NO_WATER | CMD_AUTO},
00208 {CmdBuildSingleSignal, CMD_AUTO},
00209 {CmdRemoveSingleSignal, CMD_AUTO},
00210 {CmdTerraformLand, CMD_ALL_TILES | CMD_AUTO},
00211 {CmdPurchaseLandArea, CMD_NO_WATER | CMD_AUTO},
00212 {CmdSellLandArea, 0},
00213 {CmdBuildTunnel, CMD_AUTO},
00214 {CmdRemoveFromRailStation, 0},
00215 {CmdConvertRail, 0},
00216 {CmdBuildRailWaypoint, 0},
00217 {CmdRenameWaypoint, 0},
00218 {CmdRemoveFromRailWaypoint, 0},
00219
00220 {CmdBuildRoadStop, CMD_NO_WATER | CMD_AUTO},
00221 {CmdRemoveRoadStop, 0},
00222 {CmdBuildLongRoad, CMD_NO_WATER | CMD_AUTO},
00223 {CmdRemoveLongRoad, CMD_NO_TEST | CMD_AUTO},
00224 {CmdBuildRoad, 0},
00225 {CmdRemoveRoad, 0},
00226 {CmdBuildRoadDepot, CMD_NO_WATER | CMD_AUTO},
00227
00228 {CmdBuildAirport, CMD_NO_WATER | CMD_AUTO},
00229 {CmdBuildDock, CMD_AUTO},
00230 {CmdBuildShipDepot, CMD_AUTO},
00231 {CmdBuildBuoy, CMD_AUTO},
00232 {CmdPlantTree, CMD_AUTO},
00233 {CmdBuildRailVehicle, 0},
00234 {CmdMoveRailVehicle, 0},
00235
00236 {CmdSellRailWagon, 0},
00237 {CmdSendTrainToDepot, 0},
00238 {CmdForceTrainProceed, 0},
00239 {CmdReverseTrainDirection, 0},
00240
00241 {CmdModifyOrder, 0},
00242 {CmdSkipToOrder, 0},
00243 {CmdDeleteOrder, 0},
00244 {CmdInsertOrder, 0},
00245
00246 {CmdChangeServiceInt, 0},
00247
00248 {CmdBuildIndustry, 0},
00249 {CmdBuildCompanyHQ, CMD_NO_WATER | CMD_AUTO},
00250 {CmdSetCompanyManagerFace, 0},
00251 {CmdSetCompanyColour, 0},
00252
00253 {CmdIncreaseLoan, 0},
00254 {CmdDecreaseLoan, 0},
00255
00256 {CmdWantEnginePreview, 0},
00257
00258 {CmdRenameVehicle, 0},
00259 {CmdRenameEngine, 0},
00260
00261 {CmdRenameCompany, 0},
00262 {CmdRenamePresident, 0},
00263
00264 {CmdRenameStation, 0},
00265
00266 {CmdSellAircraft, 0},
00267
00268 {CmdBuildAircraft, 0},
00269 {CmdSendAircraftToHangar, 0},
00270 {CmdRefitAircraft, 0},
00271
00272 {CmdPlaceSign, 0},
00273 {CmdRenameSign, 0},
00274
00275 {CmdBuildRoadVeh, 0},
00276 {CmdSellRoadVeh, 0},
00277 {CmdSendRoadVehToDepot, 0},
00278 {CmdTurnRoadVeh, 0},
00279 {CmdRefitRoadVeh, 0},
00280
00281 {CmdPause, CMD_SERVER},
00282
00283 {CmdBuyShareInCompany, 0},
00284 {CmdSellShareInCompany, 0},
00285 {CmdBuyCompany, 0},
00286
00287 {CmdFoundTown, CMD_NO_TEST},
00288 {CmdRenameTown, CMD_SERVER},
00289 {CmdDoTownAction, 0},
00290
00291 {CmdSellShip, 0},
00292 {CmdBuildShip, 0},
00293 {CmdSendShipToDepot, 0},
00294 {CmdRefitShip, 0},
00295
00296 {CmdOrderRefit, 0},
00297 {CmdCloneOrder, 0},
00298
00299 {CmdClearArea, CMD_NO_TEST},
00300
00301 {CmdMoneyCheat, CMD_OFFLINE},
00302 {CmdBuildCanal, CMD_AUTO},
00303 {CmdCompanyCtrl, CMD_SPECTATOR},
00304
00305 {CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO},
00306
00307 {CmdRefitRailVehicle, 0},
00308 {CmdRestoreOrderIndex, 0},
00309 {CmdBuildLock, CMD_AUTO},
00310
00311 {CmdBuildSignalTrack, CMD_AUTO},
00312 {CmdRemoveSignalTrack, CMD_AUTO},
00313
00314 {CmdGiveMoney, 0},
00315 {CmdChangeSetting, CMD_SERVER},
00316 {CmdChangeCompanySetting, 0},
00317 {CmdSetAutoReplace, 0},
00318 {CmdCloneVehicle, CMD_NO_TEST},
00319 {CmdStartStopVehicle, 0},
00320 {CmdMassStartStopVehicle, 0},
00321 {CmdAutoreplaceVehicle, 0},
00322 {CmdDepotSellAllVehicles, 0},
00323 {CmdDepotMassAutoReplace, 0},
00324 {CmdCreateGroup, 0},
00325 {CmdDeleteGroup, 0},
00326 {CmdRenameGroup, 0},
00327 {CmdAddVehicleGroup, 0},
00328 {CmdAddSharedVehicleGroup, 0},
00329 {CmdRemoveAllVehiclesGroup, 0},
00330 {CmdSetGroupReplaceProtection, 0},
00331 {CmdMoveOrder, 0},
00332 {CmdChangeTimetable, 0},
00333 {CmdSetVehicleOnTime, 0},
00334 {CmdAutofillTimetable, 0},
00335 {CmdSetTimetableStart, 0},
00336 };
00337
00344 bool IsValidCommand(uint32 cmd)
00345 {
00346 cmd &= CMD_ID_MASK;
00347
00348 return
00349 cmd < lengthof(_command_proc_table) &&
00350 _command_proc_table[cmd].proc != NULL;
00351 }
00352
00360 byte GetCommandFlags(uint32 cmd)
00361 {
00362 assert(IsValidCommand(cmd));
00363
00364 return _command_proc_table[cmd & CMD_ID_MASK].flags;
00365 }
00366
00367 static int _docommand_recursive = 0;
00368
00377 CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
00378 {
00379 return DoCommand(container->tile, container->p1, container->p2, flags, container->cmd & CMD_ID_MASK, container->text);
00380 }
00381
00395 CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, DoCommandFlag flags, uint32 cmd, const char *text)
00396 {
00397 CommandCost res;
00398
00399
00400 if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (flags & DC_ALL_TILES) == 0))) return CMD_ERROR;
00401
00402
00403 CommandProc *proc = _command_proc_table[cmd & CMD_ID_MASK].proc;
00404
00405 if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
00406
00407 _docommand_recursive++;
00408
00409
00410 if (_docommand_recursive == 1 || !(flags & DC_EXEC) ) {
00411 SetTownRatingTestMode(true);
00412 res = proc(tile, flags & ~DC_EXEC, p1, p2, text);
00413 SetTownRatingTestMode(false);
00414 if (res.Failed()) {
00415 goto error;
00416 }
00417
00418 if (_docommand_recursive == 1 &&
00419 !(flags & DC_QUERY_COST) &&
00420 !(flags & DC_BANKRUPT) &&
00421 !CheckCompanyHasMoney(res)) {
00422 goto error;
00423 }
00424
00425 if (!(flags & DC_EXEC)) {
00426 _docommand_recursive--;
00427 return res;
00428 }
00429 }
00430
00431
00432
00433 res = proc(tile, flags, p1, p2, text);
00434 if (res.Failed()) {
00435 error:
00436 res.SetGlobalErrorMessage();
00437 _docommand_recursive--;
00438 return CMD_ERROR;
00439 }
00440
00441
00442 if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
00443 SubtractMoneyFromCompany(res);
00444 }
00445
00446 return res;
00447 }
00448
00456 Money GetAvailableMoneyForCommand()
00457 {
00458 CompanyID company = _current_company;
00459 if (!Company::IsValidID(company)) return INT64_MAX;
00460 return Company::Get(company)->money;
00461 }
00462
00469 bool DoCommandP(const CommandContainer *container, bool my_cmd)
00470 {
00471 return DoCommandP(container->tile, container->p1, container->p2, container->cmd, container->callback, container->text, my_cmd);
00472 }
00473
00489 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd)
00490 {
00491
00492
00493
00494
00495
00496 bool estimate_only = _shift_pressed && IsLocalCompany() &&
00497 !IsGeneratingWorld() &&
00498 !(cmd & CMD_NETWORK_COMMAND) &&
00499 (cmd & CMD_ID_MASK) != CMD_PAUSE;
00500
00501
00502
00503 bool only_sending = _networking && !(cmd & CMD_NETWORK_COMMAND);
00504
00505
00506 int x = TileX(tile) * TILE_SIZE;
00507 int y = TileY(tile) * TILE_SIZE;
00508
00509 CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only);
00510 if (res.Failed()) {
00511 res.SetGlobalErrorMessage();
00512
00513
00514 StringID error_part1 = GB(cmd, 16, 16);
00515 if (estimate_only || (IsLocalCompany() && error_part1 != 0 && my_cmd)) {
00516 ShowErrorMessage(error_part1, _error_message, x, y);
00517 }
00518 } else if (estimate_only) {
00519 ShowEstimatedCostOrIncome(res.GetCost(), x, y);
00520 } else if (!only_sending && res.GetCost() != 0 && tile != 0 && IsLocalCompany() && _game_mode != GM_EDITOR) {
00521
00522
00523
00524
00525
00526 ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res.GetCost());
00527 }
00528
00529 if (!estimate_only && !only_sending && callback != NULL) {
00530 callback(res, tile, p1, p2);
00531 }
00532
00533 return res.Succeeded();
00534 }
00535
00536
00542 #define return_dcpi(cmd, clear) { _docommand_recursive = 0; ClearStorageChanges(clear); return cmd; }
00543
00557 CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback, const char *text, bool my_cmd, bool estimate_only)
00558 {
00559
00560 assert(_docommand_recursive == 0);
00561 _docommand_recursive = 1;
00562
00563
00564 _error_message = INVALID_STRING_ID;
00565 _additional_cash_required = 0;
00566
00567
00568 byte cmd_id = cmd & CMD_ID_MASK;
00569 assert(cmd_id < lengthof(_command_proc_table));
00570
00571 CommandProc *proc = _command_proc_table[cmd_id].proc;
00572
00573
00574 assert(proc != NULL);
00575
00576
00577 uint cmd_flags = GetCommandFlags(cmd);
00578
00579 DoCommandFlag flags = CommandFlagsToDCFlags(cmd_flags);
00580
00581
00582 if (tile != 0 && (tile >= MapSize() || (!IsValidTile(tile) && (cmd_flags & CMD_ALL_TILES) == 0))) return_dcpi(CMD_ERROR, false);
00583
00584
00585 if (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) _current_company = COMPANY_SPECTATOR;
00586
00587 CompanyID old_company = _current_company;
00588
00589
00590
00591
00592 if (_game_mode == GM_NORMAL && (cmd_flags & (CMD_SPECTATOR | CMD_SERVER)) == 0 && !Company::IsValidID(_current_company)) {
00593 return_dcpi(CMD_ERROR, false);
00594 }
00595
00596 bool test_and_exec_can_differ = (cmd_flags & CMD_NO_TEST) != 0;
00597 bool skip_test = _networking && (cmd & CMD_NO_TEST_IF_IN_NETWORK) != 0;
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 CommandCost res;
00610 if (estimate_only || !skip_test) {
00611
00612 SetTownRatingTestMode(true);
00613 res = proc(tile, flags, p1, p2, text);
00614 SetTownRatingTestMode(false);
00615
00616
00617 assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
00618
00619
00620
00621
00622
00623
00624 if (res.Failed() || estimate_only ||
00625 (!test_and_exec_can_differ && !CheckCompanyHasMoney(res))) {
00626 return_dcpi(res, false);
00627 }
00628 }
00629
00630 #ifdef ENABLE_NETWORK
00631
00632
00633
00634
00635 if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
00636 NetworkSend_Command(tile, p1, p2, cmd & ~CMD_FLAGS_MASK, callback, text, _current_company);
00637
00638
00639
00640
00641
00642 return_dcpi(CommandCost(), false);
00643 }
00644 #endif
00645 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);
00646
00647
00648
00649 CommandCost res2 = proc(tile, flags | DC_EXEC, p1, p2, text);
00650
00651
00652 assert(cmd_id == CMD_COMPANY_CTRL || old_company == _current_company);
00653
00654
00655
00656
00657
00658 if (!test_and_exec_can_differ && !skip_test) {
00659 assert(res.GetCost() == res2.GetCost() && res.Failed() == res2.Failed());
00660 } else if (res2.Failed()) {
00661 return_dcpi(res2, false);
00662 }
00663
00664
00665
00666 if (_additional_cash_required != 0 && res2.GetCost() == 0) {
00667 SetDParam(0, _additional_cash_required);
00668 return_dcpi(CommandCost(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY), false);
00669 }
00670
00671
00672 if (tile != 0) {
00673 Company *c = Company::GetIfValid(_current_company);
00674 if (c != NULL) c->last_build_coordinate = tile;
00675 }
00676
00677 SubtractMoneyFromCompany(res2);
00678
00679
00680 UpdateSignalsInBuffer();
00681
00682 return_dcpi(res2, true);
00683 }
00684 #undef return_dcpi
00685
00686
00687 CommandCost CommandCost::AddCost(CommandCost ret)
00688 {
00689 this->AddCost(ret.cost);
00690 if (this->success && !ret.success) {
00691 this->message = ret.message;
00692 this->success = false;
00693 }
00694 return *this;
00695 }