src/command.cpp
changeset 10207 c291a21b304e
parent 10151 0dd6c35bf0cc
child 10208 72c00af5c95d
equal deleted inserted replaced
10206:0050610c0368 10207:c291a21b304e
   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);
   163 DEF_COMMAND(CmdGiveMoney);
   163 DEF_COMMAND(CmdGiveMoney);
   164 DEF_COMMAND(CmdMoneyCheat);
   164 DEF_COMMAND(CmdMoneyCheat);
   165 DEF_COMMAND(CmdBuildCanal);
   165 DEF_COMMAND(CmdBuildCanal);
   166 DEF_COMMAND(CmdBuildLock);
   166 DEF_COMMAND(CmdBuildLock);
   167 
   167 
   168 DEF_COMMAND(CmdPlayerCtrl);
   168 DEF_COMMAND(CmdCompanyCtrl);
   169 
   169 
   170 DEF_COMMAND(CmdLevelLand);
   170 DEF_COMMAND(CmdLevelLand);
   171 
   171 
   172 DEF_COMMAND(CmdRefitRailVehicle);
   172 DEF_COMMAND(CmdRefitRailVehicle);
   173 
   173 
   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 */
   415 
   415 
   416 		if (_docommand_recursive == 1 &&
   416 		if (_docommand_recursive == 1 &&
   417 				!(flags & DC_QUERY_COST) &&
   417 				!(flags & DC_QUERY_COST) &&
   418 				!(flags & DC_BANKRUPT) &&
   418 				!(flags & DC_BANKRUPT) &&
   419 				res.GetCost() != 0 &&
   419 				res.GetCost() != 0 &&
   420 				!CheckPlayerHasMoney(res)) {
   420 				!CheckCompanyHasMoney(res)) {
   421 			goto error;
   421 			goto error;
   422 		}
   422 		}
   423 
   423 
   424 		if (!(flags & DC_EXEC)) {
   424 		if (!(flags & DC_EXEC)) {
   425 			_docommand_recursive--;
   425 			_docommand_recursive--;
   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;
   643 	ClearStorageChanges(true);
   643 	ClearStorageChanges(true);
   644 	return true;
   644 	return true;
   645 
   645 
   646 show_error:
   646 show_error:
   647 	/* show error message if the command fails? */
   647 	/* show error message if the command fails? */
   648 	if (IsLocalPlayer() && error_part1 != 0 && my_cmd) {
   648 	if (IsLocalCompany() && error_part1 != 0 && my_cmd) {
   649 		ShowErrorMessage(_error_message, error_part1, x, y);
   649 		ShowErrorMessage(_error_message, error_part1, x, y);
   650 	}
   650 	}
   651 
   651 
   652 callb_err:
   652 callb_err:
   653 	_docommand_recursive = 0;
   653 	_docommand_recursive = 0;