547 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			547 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* $Id$ */
 | |
| 
 | |
| #include "stdafx.h"
 | |
| #include "openttd.h"
 | |
| #include "table/strings.h"
 | |
| #include "functions.h"
 | |
| #include "map.h"
 | |
| #include "gui.h"
 | |
| #include "command.h"
 | |
| #include "player.h"
 | |
| #include "network.h"
 | |
| #include "variables.h"
 | |
| 
 | |
| const char* _cmd_text = NULL;
 | |
| 
 | |
| #define DEF_COMMAND(yyyy) int32 yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRailroadTrack);
 | |
| DEF_COMMAND(CmdRemoveRailroadTrack);
 | |
| DEF_COMMAND(CmdBuildSingleRail);
 | |
| DEF_COMMAND(CmdRemoveSingleRail);
 | |
| 
 | |
| DEF_COMMAND(CmdLandscapeClear);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildBridge);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRailroadStation);
 | |
| DEF_COMMAND(CmdRemoveFromRailroadStation);
 | |
| DEF_COMMAND(CmdConvertRail);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildSingleSignal);
 | |
| DEF_COMMAND(CmdRemoveSingleSignal);
 | |
| 
 | |
| DEF_COMMAND(CmdTerraformLand);
 | |
| 
 | |
| DEF_COMMAND(CmdPurchaseLandArea);
 | |
| DEF_COMMAND(CmdSellLandArea);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildTunnel);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildTrainDepot);
 | |
| DEF_COMMAND(CmdBuildTrainWaypoint);
 | |
| DEF_COMMAND(CmdRenameWaypoint);
 | |
| DEF_COMMAND(CmdRemoveTrainWaypoint);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRoadStop);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildLongRoad);
 | |
| DEF_COMMAND(CmdRemoveLongRoad);
 | |
| DEF_COMMAND(CmdBuildRoad);
 | |
| DEF_COMMAND(CmdRemoveRoad);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRoadDepot);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildAirport);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildDock);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildShipDepot);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildBuoy);
 | |
| 
 | |
| DEF_COMMAND(CmdPlantTree);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRailVehicle);
 | |
| DEF_COMMAND(CmdMoveRailVehicle);
 | |
| 
 | |
| DEF_COMMAND(CmdStartStopTrain);
 | |
| 
 | |
| DEF_COMMAND(CmdSellRailWagon);
 | |
| 
 | |
| DEF_COMMAND(CmdSendTrainToDepot);
 | |
| DEF_COMMAND(CmdForceTrainProceed);
 | |
| DEF_COMMAND(CmdReverseTrainDirection);
 | |
| 
 | |
| DEF_COMMAND(CmdModifyOrder);
 | |
| DEF_COMMAND(CmdSkipOrder);
 | |
| DEF_COMMAND(CmdDeleteOrder);
 | |
| DEF_COMMAND(CmdInsertOrder);
 | |
| DEF_COMMAND(CmdChangeServiceInt);
 | |
| DEF_COMMAND(CmdRestoreOrderIndex);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildIndustry);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildCompanyHQ);
 | |
| DEF_COMMAND(CmdSetPlayerFace);
 | |
| DEF_COMMAND(CmdSetPlayerColor);
 | |
| 
 | |
| DEF_COMMAND(CmdIncreaseLoan);
 | |
| DEF_COMMAND(CmdDecreaseLoan);
 | |
| 
 | |
| DEF_COMMAND(CmdWantEnginePreview);
 | |
| 
 | |
| DEF_COMMAND(CmdNameVehicle);
 | |
| DEF_COMMAND(CmdRenameEngine);
 | |
| 
 | |
| DEF_COMMAND(CmdChangeCompanyName);
 | |
| DEF_COMMAND(CmdChangePresidentName);
 | |
| 
 | |
| DEF_COMMAND(CmdRenameStation);
 | |
| 
 | |
| DEF_COMMAND(CmdSellAircraft);
 | |
| DEF_COMMAND(CmdStartStopAircraft);
 | |
| DEF_COMMAND(CmdBuildAircraft);
 | |
| DEF_COMMAND(CmdSendAircraftToHangar);
 | |
| DEF_COMMAND(CmdRefitAircraft);
 | |
| 
 | |
| DEF_COMMAND(CmdPlaceSign);
 | |
| DEF_COMMAND(CmdRenameSign);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildRoadVeh);
 | |
| DEF_COMMAND(CmdStartStopRoadVeh);
 | |
| DEF_COMMAND(CmdSellRoadVeh);
 | |
| DEF_COMMAND(CmdSendRoadVehToDepot);
 | |
| DEF_COMMAND(CmdTurnRoadVeh);
 | |
| 
 | |
| DEF_COMMAND(CmdPause);
 | |
| 
 | |
| DEF_COMMAND(CmdBuyShareInCompany);
 | |
| DEF_COMMAND(CmdSellShareInCompany);
 | |
| DEF_COMMAND(CmdBuyCompany);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildTown);
 | |
| 
 | |
| DEF_COMMAND(CmdRenameTown);
 | |
| DEF_COMMAND(CmdDoTownAction);
 | |
| 
 | |
| DEF_COMMAND(CmdSetRoadDriveSide);
 | |
| 
 | |
| DEF_COMMAND(CmdChangeDifficultyLevel);
 | |
| DEF_COMMAND(CmdChangePatchSetting);
 | |
| 
 | |
| DEF_COMMAND(CmdStartStopShip);
 | |
| DEF_COMMAND(CmdSellShip);
 | |
| DEF_COMMAND(CmdBuildShip);
 | |
| DEF_COMMAND(CmdSendShipToDepot);
 | |
| DEF_COMMAND(CmdRefitShip);
 | |
| 
 | |
| DEF_COMMAND(CmdCloneOrder);
 | |
| 
 | |
| DEF_COMMAND(CmdClearArea);
 | |
| 
 | |
| DEF_COMMAND(CmdGiveMoney);
 | |
| DEF_COMMAND(CmdMoneyCheat);
 | |
| DEF_COMMAND(CmdBuildCanal);
 | |
| DEF_COMMAND(CmdBuildLock);
 | |
| 
 | |
| DEF_COMMAND(CmdPlayerCtrl);
 | |
| 
 | |
| DEF_COMMAND(CmdLevelLand);
 | |
| 
 | |
| DEF_COMMAND(CmdRefitRailVehicle);
 | |
| 
 | |
| DEF_COMMAND(CmdBuildSignalTrack);
 | |
| DEF_COMMAND(CmdRemoveSignalTrack);
 | |
| 
 | |
| DEF_COMMAND(CmdReplaceVehicle);
 | |
| 
 | |
| DEF_COMMAND(CmdCloneVehicle);
 | |
| 
 | |
| 
 | |
| /* The master command table */
 | |
| static const Command _command_proc_table[] = {
 | |
| 	{CmdBuildRailroadTrack,                  0}, /*   0 */
 | |
| 	{CmdRemoveRailroadTrack,                 0}, /*   1 */
 | |
| 	{CmdBuildSingleRail,                     0}, /*   2 */
 | |
| 	{CmdRemoveSingleRail,                    0}, /*   3 */
 | |
| 	{CmdLandscapeClear,                      0}, /*   4 */
 | |
| 	{CmdBuildBridge,                         0}, /*   5 */
 | |
| 	{CmdBuildRailroadStation,                0}, /*   6 */
 | |
| 	{CmdBuildTrainDepot,                     0}, /*   7 */
 | |
| 	{CmdBuildSingleSignal,                   0}, /*   8 */
 | |
| 	{CmdRemoveSingleSignal,                  0}, /*   9 */
 | |
| 	{CmdTerraformLand,                       0}, /*  10 */
 | |
| 	{CmdPurchaseLandArea,                    0}, /*  11 */
 | |
| 	{CmdSellLandArea,                        0}, /*  12 */
 | |
| 	{CmdBuildTunnel,                         0}, /*  13 */
 | |
| 	{CmdRemoveFromRailroadStation,           0}, /*  14 */
 | |
| 	{CmdConvertRail,                         0}, /*  15 */
 | |
| 	{CmdBuildTrainWaypoint,                  0}, /*  16 */
 | |
| 	{CmdRenameWaypoint,                      0}, /*  17 */
 | |
| 	{CmdRemoveTrainWaypoint,                 0}, /*  18 */
 | |
| 	{NULL,                                   0}, /*  19 */
 | |
| 	{NULL,                                   0}, /*  20 */
 | |
| 	{CmdBuildRoadStop,                       0}, /*  21 */
 | |
| 	{NULL,                                   0}, /*  22 */
 | |
| 	{CmdBuildLongRoad,                       0}, /*  23 */
 | |
| 	{CmdRemoveLongRoad,                      0}, /*  24 */
 | |
| 	{CmdBuildRoad,                           0}, /*  25 */
 | |
| 	{CmdRemoveRoad,                          0}, /*  26 */
 | |
| 	{CmdBuildRoadDepot,                      0}, /*  27 */
 | |
| 	{NULL,                                   0}, /*  28 */
 | |
| 	{CmdBuildAirport,                        0}, /*  29 */
 | |
| 	{CmdBuildDock,                           0}, /*  30 */
 | |
| 	{CmdBuildShipDepot,                      0}, /*  31 */
 | |
| 	{CmdBuildBuoy,                           0}, /*  32 */
 | |
| 	{CmdPlantTree,                           0}, /*  33 */
 | |
| 	{CmdBuildRailVehicle,                    0}, /*  34 */
 | |
| 	{CmdMoveRailVehicle,                     0}, /*  35 */
 | |
| 	{CmdStartStopTrain,                      0}, /*  36 */
 | |
| 	{NULL,                                   0}, /*  37 */
 | |
| 	{CmdSellRailWagon,                       0}, /*  38 */
 | |
| 	{CmdSendTrainToDepot,                    0}, /*  39 */
 | |
| 	{CmdForceTrainProceed,                   0}, /*  40 */
 | |
| 	{CmdReverseTrainDirection,               0}, /*  41 */
 | |
| 
 | |
| 	{CmdModifyOrder,                         0}, /*  42 */
 | |
| 	{CmdSkipOrder,                           0}, /*  43 */
 | |
| 	{CmdDeleteOrder,                         0}, /*  44 */
 | |
| 	{CmdInsertOrder,                         0}, /*  45 */
 | |
| 
 | |
| 	{CmdChangeServiceInt,                    0}, /*  46 */
 | |
| 
 | |
| 	{CmdBuildIndustry,                       0}, /*  47 */
 | |
| 	{CmdBuildCompanyHQ,                      0}, /*  48 */
 | |
| 	{CmdSetPlayerFace,                       0}, /*  49 */
 | |
| 	{CmdSetPlayerColor,                      0}, /*  50 */
 | |
| 
 | |
| 	{CmdIncreaseLoan,                        0}, /*  51 */
 | |
| 	{CmdDecreaseLoan,                        0}, /*  52 */
 | |
| 
 | |
| 	{CmdWantEnginePreview,                   0}, /*  53 */
 | |
| 
 | |
| 	{CmdNameVehicle,                         0}, /*  54 */
 | |
| 	{CmdRenameEngine,                        0}, /*  55 */
 | |
| 
 | |
| 	{CmdChangeCompanyName,                   0}, /*  56 */
 | |
| 	{CmdChangePresidentName,                 0}, /*  57 */
 | |
| 
 | |
| 	{CmdRenameStation,                       0}, /*  58 */
 | |
| 
 | |
| 	{CmdSellAircraft,                        0}, /*  59 */
 | |
| 	{CmdStartStopAircraft,                   0}, /*  60 */
 | |
| 
 | |
| 	{CmdBuildAircraft,                       0}, /*  61 */
 | |
| 	{CmdSendAircraftToHangar,                0}, /*  62 */
 | |
| 	{NULL,                                   0}, /*  63 */
 | |
| 	{CmdRefitAircraft,                       0}, /*  64 */
 | |
| 
 | |
| 	{CmdPlaceSign,                           0}, /*  65 */
 | |
| 	{CmdRenameSign,                          0}, /*  66 */
 | |
| 
 | |
| 	{CmdBuildRoadVeh,                        0}, /*  67 */
 | |
| 	{CmdStartStopRoadVeh,                    0}, /*  68 */
 | |
| 	{CmdSellRoadVeh,                         0}, /*  69 */
 | |
| 	{CmdSendRoadVehToDepot,                  0}, /*  70 */
 | |
| 	{CmdTurnRoadVeh,                         0}, /*  71 */
 | |
| 	{NULL,                                   0}, /*  72 */
 | |
| 
 | |
| 	{CmdPause,                      CMD_SERVER}, /*  73 */
 | |
| 
 | |
| 	{CmdBuyShareInCompany,                   0}, /*  74 */
 | |
| 	{CmdSellShareInCompany,                  0}, /*  75 */
 | |
| 	{CmdBuyCompany,                          0}, /*  76 */
 | |
| 
 | |
| 	{CmdBuildTown,                 CMD_OFFLINE}, /*  77 */
 | |
| 	{NULL,                                   0}, /*  78 */
 | |
| 	{NULL,                                   0}, /*  79 */
 | |
| 	{CmdRenameTown,                 CMD_SERVER}, /*  80 */
 | |
| 	{CmdDoTownAction,                        0}, /*  81 */
 | |
| 
 | |
| 	{CmdSetRoadDriveSide,           CMD_SERVER}, /*  82 */
 | |
| 	{NULL,                                   0}, /*  83 */
 | |
| 	{NULL,                                   0}, /*  84 */
 | |
| 	{CmdChangeDifficultyLevel,      CMD_SERVER}, /*  85 */
 | |
| 
 | |
| 	{CmdStartStopShip,                       0}, /*  86 */
 | |
| 	{CmdSellShip,                            0}, /*  87 */
 | |
| 	{CmdBuildShip,                           0}, /*  88 */
 | |
| 	{CmdSendShipToDepot,                     0}, /*  89 */
 | |
| 	{NULL,                                   0}, /*  90 */
 | |
| 	{CmdRefitShip,                           0}, /*  91 */
 | |
| 
 | |
| 	{NULL,                                   0}, /*  92 */
 | |
| 	{NULL,                                   0}, /*  93 */
 | |
| 	{NULL,                                   0}, /*  94 */
 | |
| 	{NULL,                                   0}, /*  95 */
 | |
| 	{NULL,                                   0}, /*  96 */
 | |
| 	{NULL,                                   0}, /*  97 */
 | |
| 	{NULL,                                   0}, /*  98 */
 | |
| 
 | |
| 	{CmdCloneOrder,                          0}, /*  99 */
 | |
| 
 | |
| 	{CmdClearArea,                           0}, /* 100 */
 | |
| 	{NULL,                                   0}, /* 101 */
 | |
| 
 | |
| 	{CmdMoneyCheat,                CMD_OFFLINE}, /* 102 */
 | |
| 	{CmdBuildCanal,                          0}, /* 103 */
 | |
| 	{CmdPlayerCtrl,                          0}, /* 104 */
 | |
| 
 | |
| 	{CmdLevelLand,                           0}, /* 105 */
 | |
| 
 | |
| 	{CmdRefitRailVehicle,                    0}, /* 106 */
 | |
| 	{CmdRestoreOrderIndex,                   0}, /* 107 */
 | |
| 	{CmdBuildLock,                           0}, /* 108 */
 | |
| 	{NULL,                                   0}, /* 109 */
 | |
| 	{CmdBuildSignalTrack,                    0}, /* 110 */
 | |
| 	{CmdRemoveSignalTrack,                   0}, /* 111 */
 | |
| 	{NULL,                                   0}, /* 112 */
 | |
| 	{CmdGiveMoney,                           0}, /* 113 */
 | |
| 	{CmdChangePatchSetting,         CMD_SERVER}, /* 114 */
 | |
| 	{CmdReplaceVehicle,                      0}, /* 115 */
 | |
| 	{CmdCloneVehicle,						 0}, /* 116 */
 | |
| };
 | |
| 
 | |
| /* This function range-checks a cmd, and checks if the cmd is not NULL */
 | |
| bool IsValidCommand(uint cmd)
 | |
| {
 | |
| 	cmd &= 0xFF;
 | |
| 
 | |
| 	return
 | |
| 		cmd < lengthof(_command_proc_table) &&
 | |
| 		_command_proc_table[cmd].proc != NULL;
 | |
| }
 | |
| 
 | |
| byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
 | |
| 
 | |
| 
 | |
| static int _docommand_recursive;
 | |
| 
 | |
| int32 DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
 | |
| {
 | |
| 	int32 res;
 | |
| 	CommandProc *proc;
 | |
| 
 | |
| 	/* Do not even think about executing out-of-bounds tile-commands */
 | |
| 	if (tile >= MapSize()) {
 | |
| 		_cmd_text = NULL;
 | |
| 		return CMD_ERROR;
 | |
| 	}
 | |
| 
 | |
| 	proc = _command_proc_table[procc].proc;
 | |
| 
 | |
| 	if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID;
 | |
| 
 | |
| 	_docommand_recursive++;
 | |
| 
 | |
| 	// only execute the test call if it's toplevel, or we're not execing.
 | |
| 	if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
 | |
| 		res = proc(tile, flags & ~DC_EXEC, p1, p2);
 | |
| 		if (CmdFailed(res)) {
 | |
| 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
 | |
| 			goto error;
 | |
| 		}
 | |
| 
 | |
| 		if (_docommand_recursive == 1) {
 | |
| 			if (!(flags&DC_QUERY_COST) && res != 0 && !CheckPlayerHasMoney(res))
 | |
| 				goto error;
 | |
| 		}
 | |
| 
 | |
| 		if (!(flags & DC_EXEC)) {
 | |
| 			_docommand_recursive--;
 | |
| 			_cmd_text = NULL;
 | |
| 			return res;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* Execute the command here. All cost-relevant functions set the expenses type
 | |
| 	 * themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
 | |
| 	res = proc(tile, flags, p1, p2);
 | |
| 	if (CmdFailed(res)) {
 | |
| 		if (res & 0xFFFF) _error_message = res & 0xFFFF;
 | |
| error:
 | |
| 		_docommand_recursive--;
 | |
| 		_cmd_text = NULL;
 | |
| 		return CMD_ERROR;
 | |
| 	}
 | |
| 
 | |
| 	// if toplevel, subtract the money.
 | |
| 	if (--_docommand_recursive == 0) {
 | |
| 		SubtractMoneyFromPlayer(res);
 | |
| 		// XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player
 | |
| 		if (tile != 0 && _current_player < MAX_PLAYERS) {
 | |
| 			GetPlayer(_current_player)->last_build_coordinate = tile;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	_cmd_text = NULL;
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| int32 GetAvailableMoneyForCommand(void)
 | |
| {
 | |
| 	PlayerID pid = _current_player;
 | |
| 	if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
 | |
| 	return GetPlayer(pid)->player_money;
 | |
| }
 | |
| 
 | |
| // toplevel network safe docommand function for the current player. must not be called recursively.
 | |
| // the callback is called when the command succeeded or failed.
 | |
| bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
 | |
| {
 | |
| 	int32 res = 0,res2;
 | |
| 	CommandProc *proc;
 | |
| 	uint32 flags;
 | |
| 	bool notest;
 | |
| 	StringID error_part1;
 | |
| 
 | |
| 	int x = TileX(tile) * TILE_SIZE;
 | |
| 	int y = TileY(tile) * TILE_SIZE;
 | |
| 
 | |
| 	/* Do not even think about executing out-of-bounds tile-commands */
 | |
| 	if (tile >= MapSize()) {
 | |
| 		_cmd_text = NULL;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	assert(_docommand_recursive == 0);
 | |
| 
 | |
| 	_error_message = INVALID_STRING_ID;
 | |
| 	error_part1 = GB(cmd, 16, 16);
 | |
| 	_additional_cash_required = 0;
 | |
| 
 | |
| 	/** Spectator has no rights except for the dedicated server which
 | |
| 	 * is a spectator but is the server, so can do anything */
 | |
| 	if (_current_player == OWNER_SPECTATOR && !_network_dedicated) {
 | |
| 		ShowErrorMessage(_error_message, error_part1, x, y);
 | |
| 		_cmd_text = NULL;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	flags = 0;
 | |
| 	if (cmd & CMD_AUTO) flags |= DC_AUTO;
 | |
| 	if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
 | |
| 
 | |
| 	// get pointer to command handler
 | |
| 	assert((cmd & 0xFF) < lengthof(_command_proc_table));
 | |
| 	proc = _command_proc_table[cmd & 0xFF].proc;
 | |
| 	if (proc == NULL) {
 | |
| 		_cmd_text = NULL;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	// Some commands have a different output in dryrun than the realrun
 | |
| 	//  e.g.: if you demolish a whole town, the dryrun would say okay.
 | |
| 	//  but by really destroying, your rating drops and at a certain point
 | |
| 	//  it will fail. so res and res2 are different
 | |
| 	// CMD_REMOVE_ROAD: This command has special local authority
 | |
| 	// restrictions which may cause the test run to fail (the previous
 | |
| 	// road fragments still stay there and the town won't let you
 | |
| 	// disconnect the road system), but the exec will succeed and this
 | |
| 	// fact will trigger an assertion failure. --pasky
 | |
| 	notest =
 | |
| 		(cmd & 0xFF) == CMD_CLEAR_AREA ||
 | |
| 		(cmd & 0xFF) == CMD_CONVERT_RAIL ||
 | |
| 		(cmd & 0xFF) == CMD_LEVEL_LAND ||
 | |
| 		(cmd & 0xFF) == CMD_REMOVE_ROAD ||
 | |
| 		(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
 | |
| 
 | |
| 	_docommand_recursive = 1;
 | |
| 
 | |
| 	// cost estimation only?
 | |
| 	if (_shift_pressed && IsLocalPlayer() && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
 | |
| 		// estimate the cost.
 | |
| 		res = proc(tile, flags, p1, p2);
 | |
| 		if (CmdFailed(res)) {
 | |
| 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
 | |
| 			ShowErrorMessage(_error_message, error_part1, x, y);
 | |
| 		} else {
 | |
| 			ShowEstimatedCostOrIncome(res, x, y);
 | |
| 		}
 | |
| 
 | |
| 		_docommand_recursive = 0;
 | |
| 		_cmd_text = NULL;
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
 | |
| 		// first test if the command can be executed.
 | |
| 		res = proc(tile, flags, p1, p2);
 | |
| 		if (CmdFailed(res)) {
 | |
| 			if (res & 0xFFFF) _error_message = res & 0xFFFF;
 | |
| 			goto show_error;
 | |
| 		}
 | |
| 		// no money? Only check if notest is off
 | |
| 		if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
 | |
| 	}
 | |
| 
 | |
| #ifdef ENABLE_NETWORK
 | |
| 	/** If we are in network, and the command is not from the network
 | |
| 	 * send it to the command-queue and abort execution
 | |
| 	 * If we are a dedicated server temporarily switch local player, otherwise
 | |
| 	 * the other parties won't be able to execute our command and will desync.
 | |
| 	 * @todo Rewrite dedicated server to something more than a dirty hack!
 | |
| 	 */
 | |
| 	if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
 | |
| 		if (_network_dedicated) _local_player = 0;
 | |
| 		NetworkSend_Command(tile, p1, p2, cmd, callback);
 | |
| 		if (_network_dedicated) _local_player = OWNER_SPECTATOR;
 | |
| 		_docommand_recursive = 0;
 | |
| 		_cmd_text = NULL;
 | |
| 		return true;
 | |
| 	}
 | |
| #endif /* ENABLE_NETWORK */
 | |
| 
 | |
| 	// update last build coordinate of player.
 | |
| 	if ( tile != 0 && _current_player < MAX_PLAYERS) GetPlayer(_current_player)->last_build_coordinate = tile;
 | |
| 
 | |
| 	/* Actually try and execute the command. If no cost-type is given
 | |
| 	 * use the construction one */
 | |
| 	_yearly_expenses_type = EXPENSES_CONSTRUCTION;
 | |
| 	res2 = proc(tile, flags|DC_EXEC, p1, p2);
 | |
| 
 | |
| 	// If notest is on, it means the result of the test can be different than
 | |
| 	//   the real command.. so ignore the test
 | |
| 	if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
 | |
| 		assert(res == res2); // sanity check
 | |
| 	} else {
 | |
| 		if (CmdFailed(res2)) {
 | |
| 			if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
 | |
| 			goto show_error;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	SubtractMoneyFromPlayer(res2);
 | |
| 
 | |
| 	if (IsLocalPlayer() && _game_mode != GM_EDITOR) {
 | |
| 		if (res2 != 0)
 | |
| 			ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
 | |
| 		if (_additional_cash_required) {
 | |
| 			SetDParam(0, _additional_cash_required);
 | |
| 			ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x,y);
 | |
| 			if (res2 == 0) goto callb_err;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	_docommand_recursive = 0;
 | |
| 
 | |
| 	if (callback) callback(true, tile, p1, p2);
 | |
| 	_cmd_text = NULL;
 | |
| 	return true;
 | |
| 
 | |
| show_error:
 | |
| 	// show error message if the command fails?
 | |
| 	if (IsLocalPlayer() && error_part1 != 0) {
 | |
| 		ShowErrorMessage(_error_message, error_part1, x,y);
 | |
| 	}
 | |
| 
 | |
| callb_err:
 | |
| 	_docommand_recursive = 0;
 | |
| 
 | |
| 	if (callback) callback(false, tile, p1, p2);
 | |
| 	_cmd_text = NULL;
 | |
| 	return false;
 | |
| }
 | 
