103 DEF_COMMAND(CmdRestoreOrderIndex); |
103 DEF_COMMAND(CmdRestoreOrderIndex); |
104 |
104 |
105 DEF_COMMAND(CmdBuildIndustry); |
105 DEF_COMMAND(CmdBuildIndustry); |
106 |
106 |
107 DEF_COMMAND(CmdBuildCompanyHQ); |
107 DEF_COMMAND(CmdBuildCompanyHQ); |
108 DEF_COMMAND(CmdSetPlayerFace); |
108 DEF_COMMAND(CmdSetCompanyManagerFace); |
109 DEF_COMMAND(CmdSetPlayerColor); |
109 DEF_COMMAND(CmdSetCompanyColor); |
110 |
110 |
111 DEF_COMMAND(CmdIncreaseLoan); |
111 DEF_COMMAND(CmdIncreaseLoan); |
112 DEF_COMMAND(CmdDecreaseLoan); |
112 DEF_COMMAND(CmdDecreaseLoan); |
113 |
113 |
114 DEF_COMMAND(CmdWantEnginePreview); |
114 DEF_COMMAND(CmdWantEnginePreview); |
253 |
253 |
254 {CmdChangeServiceInt, 0}, /* CMD_CHANGE_SERVICE_INT */ |
254 {CmdChangeServiceInt, 0}, /* CMD_CHANGE_SERVICE_INT */ |
255 |
255 |
256 {CmdBuildIndustry, 0}, /* CMD_BUILD_INDUSTRY */ |
256 {CmdBuildIndustry, 0}, /* CMD_BUILD_INDUSTRY */ |
257 {CmdBuildCompanyHQ, CMD_AUTO}, /* CMD_BUILD_COMPANY_HQ */ |
257 {CmdBuildCompanyHQ, CMD_AUTO}, /* CMD_BUILD_COMPANY_HQ */ |
258 {CmdSetPlayerFace, 0}, /* CMD_SET_PLAYER_FACE */ |
258 {CmdSetCompanyManagerFace, 0}, /* CMD_SET_COMPANY_MANAGER_FACE */ |
259 {CmdSetPlayerColor, 0}, /* CMD_SET_PLAYER_COLOR */ |
259 {CmdSetCompanyColor, 0}, /* CMD_SET_COMPANY_COLOR */ |
260 |
260 |
261 {CmdIncreaseLoan, 0}, /* CMD_INCREASE_LOAN */ |
261 {CmdIncreaseLoan, 0}, /* CMD_INCREASE_LOAN */ |
262 {CmdDecreaseLoan, 0}, /* CMD_DECREASE_LOAN */ |
262 {CmdDecreaseLoan, 0}, /* CMD_DECREASE_LOAN */ |
263 |
263 |
264 {CmdWantEnginePreview, 0}, /* CMD_WANT_ENGINE_PREVIEW */ |
264 {CmdWantEnginePreview, 0}, /* CMD_WANT_ENGINE_PREVIEW */ |
308 |
308 |
309 {CmdClearArea, 0}, /* CMD_CLEAR_AREA */ |
309 {CmdClearArea, 0}, /* CMD_CLEAR_AREA */ |
310 |
310 |
311 {CmdMoneyCheat, CMD_OFFLINE}, /* CMD_MONEY_CHEAT */ |
311 {CmdMoneyCheat, CMD_OFFLINE}, /* CMD_MONEY_CHEAT */ |
312 {CmdBuildCanal, CMD_AUTO}, /* CMD_BUILD_CANAL */ |
312 {CmdBuildCanal, CMD_AUTO}, /* CMD_BUILD_CANAL */ |
313 {CmdPlayerCtrl, 0}, /* CMD_PLAYER_CTRL */ |
313 {CmdCompanyCtrl, 0}, /* CMD_COMPANY_CTRL */ |
314 |
314 |
315 {CmdLevelLand, CMD_AUTO}, /* CMD_LEVEL_LAND */ |
315 {CmdLevelLand, CMD_AUTO}, /* CMD_LEVEL_LAND */ |
316 |
316 |
317 {CmdRefitRailVehicle, 0}, /* CMD_REFIT_RAIL_VEHICLE */ |
317 {CmdRefitRailVehicle, 0}, /* CMD_REFIT_RAIL_VEHICLE */ |
318 {CmdRestoreOrderIndex, 0}, /* CMD_RESTORE_ORDER_INDEX */ |
318 {CmdRestoreOrderIndex, 0}, /* CMD_RESTORE_ORDER_INDEX */ |
439 return CMD_ERROR; |
439 return CMD_ERROR; |
440 } |
440 } |
441 |
441 |
442 /* if toplevel, subtract the money. */ |
442 /* if toplevel, subtract the money. */ |
443 if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) { |
443 if (--_docommand_recursive == 0 && !(flags & DC_BANKRUPT)) { |
444 SubtractMoneyFromPlayer(res); |
444 SubtractMoneyFromCompany(res); |
445 /* XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player */ |
445 /* XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of company */ |
446 if (tile != 0 && IsValidPlayerID(_current_player)) { |
446 if (tile != 0 && IsValidCompanyID(_current_company)) { |
447 GetPlayer(_current_player)->last_build_coordinate = tile; |
447 GetCompany(_current_company)->last_build_coordinate = tile; |
448 } |
448 } |
449 } |
449 } |
450 |
450 |
451 _cmd_text = NULL; |
451 _cmd_text = NULL; |
452 return res; |
452 return res; |
453 } |
453 } |
454 |
454 |
455 /*! |
455 /*! |
456 * This functions returns the money which can be used to execute a command. |
456 * This functions returns the money which can be used to execute a command. |
457 * This is either the money of the current player or INT64_MAX if there |
457 * This is either the money of the current company or INT64_MAX if there |
458 * is no such a player "at the moment" like the server itself. |
458 * is no such a company "at the moment" like the server itself. |
459 * |
459 * |
460 * @return The available money of a player or INT64_MAX |
460 * @return The available money of a company or INT64_MAX |
461 */ |
461 */ |
462 Money GetAvailableMoneyForCommand() |
462 Money GetAvailableMoneyForCommand() |
463 { |
463 { |
464 PlayerID pid = _current_player; |
464 CompanyID company = _current_company; |
465 if (!IsValidPlayerID(pid)) return INT64_MAX; |
465 if (!IsValidCompanyID(company)) return INT64_MAX; |
466 return GetPlayer(pid)->player_money; |
466 return GetCompany(company)->money; |
467 } |
467 } |
468 |
468 |
469 /*! |
469 /*! |
470 * Toplevel network safe docommand function for the current player. Must not be called recursively. |
470 * Toplevel network safe docommand function for the current company. Must not be called recursively. |
471 * The callback is called when the command succeeded or failed. The parameters |
471 * The callback is called when the command succeeded or failed. The parameters |
472 * tile, p1 and p2 are from the #CommandProc function. The paramater cmd is the command to execute. |
472 * tile, p1 and p2 are from the #CommandProc function. The paramater cmd is the command to execute. |
473 * The parameter my_cmd is used to indicate if the command is from a player or the server. |
473 * The parameter my_cmd is used to indicate if the command is from a company or the server. |
474 * |
474 * |
475 * @param tile The tile to perform a command on (see #CommandProc) |
475 * @param tile The tile to perform a command on (see #CommandProc) |
476 * @param p1 Additional data for the command (see #CommandProc) |
476 * @param p1 Additional data for the command (see #CommandProc) |
477 * @param p2 Additional data for the command (see #CommandProc) |
477 * @param p2 Additional data for the command (see #CommandProc) |
478 * @param callback A callback function to call after the command is finished |
478 * @param callback A callback function to call after the command is finished |
479 * @param cmd The command to execute (a CMD_* value) |
479 * @param cmd The command to execute (a CMD_* value) |
480 * @param my_cmd indicator if the command is from a player or server (to display error messages for a user) |
480 * @param my_cmd indicator if the command is from a company or server (to display error messages for a user) |
481 * @return true if the command succeeded, else false |
481 * @return true if the command succeeded, else false |
482 */ |
482 */ |
483 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd, bool my_cmd) |
483 bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd, bool my_cmd) |
484 { |
484 { |
485 CommandCost res, res2; |
485 CommandCost res, res2; |
503 error_part1 = GB(cmd, 16, 16); |
503 error_part1 = GB(cmd, 16, 16); |
504 _additional_cash_required = 0; |
504 _additional_cash_required = 0; |
505 |
505 |
506 /** Spectator has no rights except for the (dedicated) server which |
506 /** Spectator has no rights except for the (dedicated) server which |
507 * is/can be a spectator but as the server it can do anything */ |
507 * is/can be a spectator but as the server it can do anything */ |
508 if (_current_player == PLAYER_SPECTATOR && !_network_server) { |
508 if (_current_company == COMPANY_SPECTATOR && !_network_server) { |
509 if (my_cmd) ShowErrorMessage(_error_message, error_part1, x, y); |
509 if (my_cmd) ShowErrorMessage(_error_message, error_part1, x, y); |
510 _cmd_text = NULL; |
510 _cmd_text = NULL; |
511 return false; |
511 return false; |
512 } |
512 } |
513 |
513 |
545 _docommand_recursive = 1; |
545 _docommand_recursive = 1; |
546 |
546 |
547 /* cost estimation only? */ |
547 /* cost estimation only? */ |
548 if (!IsGeneratingWorld() && |
548 if (!IsGeneratingWorld() && |
549 _shift_pressed && |
549 _shift_pressed && |
550 IsLocalPlayer() && |
550 IsLocalCompany() && |
551 !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) && |
551 !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) && |
552 (cmd & 0xFF) != CMD_PAUSE) { |
552 (cmd & 0xFF) != CMD_PAUSE) { |
553 /* estimate the cost. */ |
553 /* estimate the cost. */ |
554 SetTownRatingTestMode(true); |
554 SetTownRatingTestMode(true); |
555 res = proc(tile, flags, p1, p2); |
555 res = proc(tile, flags, p1, p2); |
576 if (CmdFailed(res)) { |
576 if (CmdFailed(res)) { |
577 res.SetGlobalErrorMessage(); |
577 res.SetGlobalErrorMessage(); |
578 goto show_error; |
578 goto show_error; |
579 } |
579 } |
580 /* no money? Only check if notest is off */ |
580 /* no money? Only check if notest is off */ |
581 if (!notest && res.GetCost() != 0 && !CheckPlayerHasMoney(res)) goto show_error; |
581 if (!notest && res.GetCost() != 0 && !CheckCompanyHasMoney(res)) goto show_error; |
582 } |
582 } |
583 |
583 |
584 #ifdef ENABLE_NETWORK |
584 #ifdef ENABLE_NETWORK |
585 /** If we are in network, and the command is not from the network |
585 /** If we are in network, and the command is not from the network |
586 * send it to the command-queue and abort execution |
586 * send it to the command-queue and abort execution |
587 * If we are a dedicated server temporarily switch local player, otherwise |
587 * If we are a dedicated server temporarily switch local company, otherwise |
588 * the other parties won't be able to execute our command and will desync. |
588 * the other parties won't be able to execute our command and will desync. |
589 * We also need to do this if the server's company has gone bankrupt |
589 * We also need to do this if the server's company has gone bankrupt |
590 * @todo Rewrite (dedicated) server to something more than a dirty hack! |
590 * @todo Rewrite (dedicated) server to something more than a dirty hack! |
591 */ |
591 */ |
592 if (_networking && !(cmd & CMD_NETWORK_COMMAND)) { |
592 if (_networking && !(cmd & CMD_NETWORK_COMMAND)) { |
593 PlayerID pbck = _local_player; |
593 CompanyID pbck = _local_company; |
594 if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = PLAYER_FIRST; |
594 if (_network_dedicated || (_network_server && pbck == COMPANY_SPECTATOR)) _local_company = COMPANY_FIRST; |
595 NetworkSend_Command(tile, p1, p2, cmd, callback); |
595 NetworkSend_Command(tile, p1, p2, cmd, callback); |
596 if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck; |
596 if (_network_dedicated || (_network_server && pbck == COMPANY_SPECTATOR)) _local_company = pbck; |
597 _docommand_recursive = 0; |
597 _docommand_recursive = 0; |
598 _cmd_text = NULL; |
598 _cmd_text = NULL; |
599 ClearStorageChanges(false); |
599 ClearStorageChanges(false); |
600 return true; |
600 return true; |
601 } |
601 } |
602 #endif /* ENABLE_NETWORK */ |
602 #endif /* ENABLE_NETWORK */ |
603 DebugDumpCommands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)_current_player, tile, p1, p2, cmd, _cmd_text); |
603 DebugDumpCommands("ddc:cmd:%d;%d;%d;%d;%d;%d;%d;%s\n", _date, _date_fract, (int)_current_company, tile, p1, p2, cmd, _cmd_text); |
604 |
604 |
605 /* update last build coordinate of player. */ |
605 /* update last build coordinate of company. */ |
606 if (tile != 0 && IsValidPlayerID(_current_player)) { |
606 if (tile != 0 && IsValidCompanyID(_current_company)) { |
607 GetPlayer(_current_player)->last_build_coordinate = tile; |
607 GetCompany(_current_company)->last_build_coordinate = tile; |
608 } |
608 } |
609 |
609 |
610 /* Actually try and execute the command. If no cost-type is given |
610 /* Actually try and execute the command. If no cost-type is given |
611 * use the construction one */ |
611 * use the construction one */ |
612 res2 = proc(tile, flags | DC_EXEC, p1, p2); |
612 res2 = proc(tile, flags | DC_EXEC, p1, p2); |
620 res.SetGlobalErrorMessage(); |
620 res.SetGlobalErrorMessage(); |
621 goto show_error; |
621 goto show_error; |
622 } |
622 } |
623 } |
623 } |
624 |
624 |
625 SubtractMoneyFromPlayer(res2); |
625 SubtractMoneyFromCompany(res2); |
626 |
626 |
627 /* update signals if needed */ |
627 /* update signals if needed */ |
628 UpdateSignalsInBuffer(); |
628 UpdateSignalsInBuffer(); |
629 |
629 |
630 if (IsLocalPlayer() && _game_mode != GM_EDITOR) { |
630 if (IsLocalCompany() && _game_mode != GM_EDITOR) { |
631 if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost()); |
631 if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost()); |
632 if (_additional_cash_required != 0) { |
632 if (_additional_cash_required != 0) { |
633 SetDParam(0, _additional_cash_required); |
633 SetDParam(0, _additional_cash_required); |
634 if (my_cmd) ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x, y); |
634 if (my_cmd) ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x, y); |
635 if (res2.GetCost() == 0) goto callb_err; |
635 if (res2.GetCost() == 0) goto callb_err; |