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