00001
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},
00213 {CmdRemoveRailroadTrack, CMD_AUTO},
00214 {CmdBuildSingleRail, CMD_AUTO},
00215 {CmdRemoveSingleRail, CMD_AUTO},
00216 {CmdLandscapeClear, 0},
00217 {CmdBuildBridge, CMD_AUTO},
00218 {CmdBuildRailroadStation, CMD_AUTO},
00219 {CmdBuildTrainDepot, CMD_AUTO},
00220 {CmdBuildSingleSignal, CMD_AUTO},
00221 {CmdRemoveSingleSignal, CMD_AUTO},
00222 {CmdTerraformLand, CMD_AUTO},
00223 {CmdPurchaseLandArea, CMD_AUTO},
00224 {CmdSellLandArea, 0},
00225 {CmdBuildTunnel, CMD_AUTO},
00226 {CmdRemoveFromRailroadStation, 0},
00227 {CmdConvertRail, 0},
00228 {CmdBuildTrainWaypoint, 0},
00229 {CmdRenameWaypoint, 0},
00230 {CmdRemoveTrainWaypoint, 0},
00231
00232 {CmdBuildRoadStop, CMD_AUTO},
00233 {CmdRemoveRoadStop, 0},
00234 {CmdBuildLongRoad, CMD_AUTO},
00235 {CmdRemoveLongRoad, CMD_AUTO},
00236 {CmdBuildRoad, 0},
00237 {CmdRemoveRoad, 0},
00238 {CmdBuildRoadDepot, CMD_AUTO},
00239
00240 {CmdBuildAirport, CMD_AUTO},
00241 {CmdBuildDock, CMD_AUTO},
00242 {CmdBuildShipDepot, CMD_AUTO},
00243 {CmdBuildBuoy, CMD_AUTO},
00244 {CmdPlantTree, CMD_AUTO},
00245 {CmdBuildRailVehicle, 0},
00246 {CmdMoveRailVehicle, 0},
00247 {CmdStartStopTrain, 0},
00248
00249 {CmdSellRailWagon, 0},
00250 {CmdSendTrainToDepot, 0},
00251 {CmdForceTrainProceed, 0},
00252 {CmdReverseTrainDirection, 0},
00253
00254 {CmdModifyOrder, 0},
00255 {CmdSkipToOrder, 0},
00256 {CmdDeleteOrder, 0},
00257 {CmdInsertOrder, 0},
00258
00259 {CmdChangeServiceInt, 0},
00260
00261 {CmdBuildIndustry, 0},
00262 {CmdBuildCompanyHQ, CMD_AUTO},
00263 {CmdSetPlayerFace, 0},
00264 {CmdSetPlayerColor, 0},
00265
00266 {CmdIncreaseLoan, 0},
00267 {CmdDecreaseLoan, 0},
00268
00269 {CmdWantEnginePreview, 0},
00270
00271 {CmdNameVehicle, 0},
00272 {CmdRenameEngine, 0},
00273
00274 {CmdChangeCompanyName, 0},
00275 {CmdChangePresidentName, 0},
00276
00277 {CmdRenameStation, 0},
00278
00279 {CmdSellAircraft, 0},
00280 {CmdStartStopAircraft, 0},
00281
00282 {CmdBuildAircraft, 0},
00283 {CmdSendAircraftToHangar, 0},
00284 {CmdRefitAircraft, 0},
00285
00286 {CmdPlaceSign, 0},
00287 {CmdRenameSign, 0},
00288
00289 {CmdBuildRoadVeh, 0},
00290 {CmdStartStopRoadVeh, 0},
00291 {CmdSellRoadVeh, 0},
00292 {CmdSendRoadVehToDepot, 0},
00293 {CmdTurnRoadVeh, 0},
00294 {CmdRefitRoadVeh, 0},
00295
00296 {CmdPause, CMD_SERVER},
00297
00298 {CmdBuyShareInCompany, 0},
00299 {CmdSellShareInCompany, 0},
00300 {CmdBuyCompany, 0},
00301
00302 {CmdBuildTown, CMD_OFFLINE},
00303 {CmdRenameTown, CMD_SERVER},
00304 {CmdDoTownAction, 0},
00305
00306 {CmdSetRoadDriveSide, CMD_SERVER},
00307 {CmdChangeDifficultyLevel, CMD_SERVER},
00308
00309 {CmdStartStopShip, 0},
00310 {CmdSellShip, 0},
00311 {CmdBuildShip, 0},
00312 {CmdSendShipToDepot, 0},
00313 {CmdRefitShip, 0},
00314
00315 {CmdOrderRefit, 0},
00316 {CmdCloneOrder, 0},
00317
00318 {CmdClearArea, 0},
00319
00320 {CmdMoneyCheat, CMD_OFFLINE},
00321 {CmdBuildCanal, CMD_AUTO},
00322 {CmdPlayerCtrl, 0},
00323
00324 {CmdLevelLand, CMD_AUTO},
00325
00326 {CmdRefitRailVehicle, 0},
00327 {CmdRestoreOrderIndex, 0},
00328 {CmdBuildLock, CMD_AUTO},
00329
00330 {CmdBuildSignalTrack, CMD_AUTO},
00331 {CmdRemoveSignalTrack, CMD_AUTO},
00332
00333 {CmdGiveMoney, 0},
00334 {CmdChangePatchSetting, CMD_SERVER},
00335 {CmdSetAutoReplace, 0},
00336 {CmdCloneVehicle, 0},
00337 {CmdMassStartStopVehicle, 0},
00338 {CmdDepotSellAllVehicles, 0},
00339 {CmdDepotMassAutoReplace, 0},
00340 {CmdCreateGroup, 0},
00341 {CmdDeleteGroup, 0},
00342 {CmdRenameGroup, 0},
00343 {CmdAddVehicleGroup, 0},
00344 {CmdAddSharedVehicleGroup, 0},
00345 {CmdRemoveAllVehiclesGroup, 0},
00346 {CmdSetGroupReplaceProtection, 0},
00347 {CmdMoveOrder, 0},
00348 {CmdChangeTimetable, 0},
00349 {CmdSetVehicleOnTime, 0},
00350 {CmdAutofillTimetable, 0},
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
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
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
00439
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
00450 if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) {
00451 SubtractMoneyFromPlayer(res);
00452
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
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
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
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
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
00555 if (!IsGeneratingWorld() &&
00556 _shift_pressed &&
00557 IsLocalPlayer() &&
00558 !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) &&
00559 (cmd & 0xFF) != CMD_PAUSE) {
00560
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
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
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
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
00613 if (tile != 0 && IsValidPlayer(_current_player)) {
00614 GetPlayer(_current_player)->last_build_coordinate = tile;
00615 }
00616
00617
00618
00619 res2 = proc(tile, flags | DC_EXEC, p1, p2);
00620
00621
00622
00623 if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
00624 assert(res.GetCost() == res2.GetCost() && CmdFailed(res) == CmdFailed(res2));
00625 } else {
00626 if (CmdFailed(res2)) {
00627 res.SetGlobalErrorMessage();
00628 goto show_error;
00629 }
00630 }
00631
00632 SubtractMoneyFromPlayer(res2);
00633
00634
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
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 }