tron@2186: /* $Id$ */ tron@2186: belugas@6123: /** @file command.cpp */ belugas@6123: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@507: #include "table/strings.h" rubidium@7266: #include "strings.h" tron@2163: #include "functions.h" maedhros@6453: #include "landscape.h" tron@679: #include "map.h" truelight@0: #include "gui.h" truelight@0: #include "command.h" truelight@0: #include "player.h" rubidium@5469: #include "network/network.h" tron@2159: #include "variables.h" truelight@4300: #include "genworld.h" rubidium@7609: #include "newgrf_storage.h" truelight@0: rubidium@7559: const char *_cmd_text = NULL; tron@1820: rubidium@7559: /** rubidium@7559: * Helper macro to define the header of all command handler macros. rubidium@7559: * rubidium@7559: * This macro create the function header for a given command handler function, as rubidium@7559: * all command handler functions got the parameters from the #CommandProc callback rubidium@7559: * type. rubidium@7559: * rubidium@7559: * @param yyyy The desired function name of the new command handler function. rubidium@7559: */ rubidium@6943: #define DEF_COMMAND(yyyy) CommandCost yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: truelight@0: DEF_COMMAND(CmdBuildRailroadTrack); truelight@0: DEF_COMMAND(CmdRemoveRailroadTrack); truelight@0: DEF_COMMAND(CmdBuildSingleRail); truelight@0: DEF_COMMAND(CmdRemoveSingleRail); truelight@0: truelight@0: DEF_COMMAND(CmdLandscapeClear); truelight@0: truelight@0: DEF_COMMAND(CmdBuildBridge); truelight@0: truelight@0: DEF_COMMAND(CmdBuildRailroadStation); truelight@0: DEF_COMMAND(CmdRemoveFromRailroadStation); truelight@0: DEF_COMMAND(CmdConvertRail); truelight@0: darkvater@1227: DEF_COMMAND(CmdBuildSingleSignal); darkvater@1227: DEF_COMMAND(CmdRemoveSingleSignal); truelight@0: truelight@0: DEF_COMMAND(CmdTerraformLand); truelight@0: truelight@0: DEF_COMMAND(CmdPurchaseLandArea); truelight@0: DEF_COMMAND(CmdSellLandArea); truelight@0: truelight@0: DEF_COMMAND(CmdBuildTunnel); truelight@0: truelight@0: DEF_COMMAND(CmdBuildTrainDepot); darkvater@395: DEF_COMMAND(CmdBuildTrainWaypoint); darkvater@395: DEF_COMMAND(CmdRenameWaypoint); darkvater@395: DEF_COMMAND(CmdRemoveTrainWaypoint); truelight@0: celestar@1217: DEF_COMMAND(CmdBuildRoadStop); rubidium@6012: DEF_COMMAND(CmdRemoveRoadStop); truelight@0: truelight@0: DEF_COMMAND(CmdBuildLongRoad); truelight@0: DEF_COMMAND(CmdRemoveLongRoad); truelight@0: DEF_COMMAND(CmdBuildRoad); truelight@0: DEF_COMMAND(CmdRemoveRoad); truelight@0: truelight@0: DEF_COMMAND(CmdBuildRoadDepot); truelight@0: truelight@0: DEF_COMMAND(CmdBuildAirport); truelight@0: truelight@0: DEF_COMMAND(CmdBuildDock); truelight@0: truelight@0: DEF_COMMAND(CmdBuildShipDepot); truelight@0: truelight@0: DEF_COMMAND(CmdBuildBuoy); truelight@0: truelight@0: DEF_COMMAND(CmdPlantTree); truelight@0: truelight@0: DEF_COMMAND(CmdBuildRailVehicle); truelight@0: DEF_COMMAND(CmdMoveRailVehicle); truelight@0: truelight@0: DEF_COMMAND(CmdStartStopTrain); truelight@0: truelight@0: DEF_COMMAND(CmdSellRailWagon); truelight@0: Darkvater@1794: DEF_COMMAND(CmdSendTrainToDepot); truelight@0: DEF_COMMAND(CmdForceTrainProceed); truelight@0: DEF_COMMAND(CmdReverseTrainDirection); truelight@0: truelight@0: DEF_COMMAND(CmdModifyOrder); rubidium@6794: DEF_COMMAND(CmdSkipToOrder); truelight@0: DEF_COMMAND(CmdDeleteOrder); truelight@0: DEF_COMMAND(CmdInsertOrder); tron@2819: DEF_COMMAND(CmdChangeServiceInt); truelight@0: DEF_COMMAND(CmdRestoreOrderIndex); truelight@0: truelight@0: DEF_COMMAND(CmdBuildIndustry); truelight@0: truelight@0: DEF_COMMAND(CmdBuildCompanyHQ); truelight@0: DEF_COMMAND(CmdSetPlayerFace); truelight@0: DEF_COMMAND(CmdSetPlayerColor); truelight@0: truelight@0: DEF_COMMAND(CmdIncreaseLoan); truelight@0: DEF_COMMAND(CmdDecreaseLoan); truelight@0: truelight@0: DEF_COMMAND(CmdWantEnginePreview); truelight@0: truelight@0: DEF_COMMAND(CmdNameVehicle); truelight@0: DEF_COMMAND(CmdRenameEngine); truelight@0: truelight@0: DEF_COMMAND(CmdChangeCompanyName); truelight@0: DEF_COMMAND(CmdChangePresidentName); truelight@0: truelight@0: DEF_COMMAND(CmdRenameStation); truelight@0: truelight@0: DEF_COMMAND(CmdSellAircraft); truelight@0: DEF_COMMAND(CmdStartStopAircraft); truelight@0: DEF_COMMAND(CmdBuildAircraft); truelight@0: DEF_COMMAND(CmdSendAircraftToHangar); truelight@0: DEF_COMMAND(CmdRefitAircraft); truelight@0: truelight@0: DEF_COMMAND(CmdPlaceSign); truelight@0: DEF_COMMAND(CmdRenameSign); truelight@0: truelight@0: DEF_COMMAND(CmdBuildRoadVeh); truelight@0: DEF_COMMAND(CmdStartStopRoadVeh); truelight@0: DEF_COMMAND(CmdSellRoadVeh); truelight@0: DEF_COMMAND(CmdSendRoadVehToDepot); truelight@0: DEF_COMMAND(CmdTurnRoadVeh); peter1138@3990: DEF_COMMAND(CmdRefitRoadVeh); truelight@0: truelight@0: DEF_COMMAND(CmdPause); truelight@0: truelight@0: DEF_COMMAND(CmdBuyShareInCompany); truelight@0: DEF_COMMAND(CmdSellShareInCompany); truelight@0: DEF_COMMAND(CmdBuyCompany); truelight@0: truelight@0: DEF_COMMAND(CmdBuildTown); truelight@0: truelight@0: DEF_COMMAND(CmdRenameTown); truelight@0: DEF_COMMAND(CmdDoTownAction); truelight@0: truelight@0: DEF_COMMAND(CmdSetRoadDriveSide); truelight@0: truelight@0: DEF_COMMAND(CmdChangeDifficultyLevel); truelight@543: DEF_COMMAND(CmdChangePatchSetting); truelight@0: truelight@0: DEF_COMMAND(CmdStartStopShip); truelight@0: DEF_COMMAND(CmdSellShip); truelight@0: DEF_COMMAND(CmdBuildShip); truelight@0: DEF_COMMAND(CmdSendShipToDepot); truelight@0: DEF_COMMAND(CmdRefitShip); truelight@0: bjarni@4712: DEF_COMMAND(CmdOrderRefit); truelight@0: DEF_COMMAND(CmdCloneOrder); truelight@0: truelight@0: DEF_COMMAND(CmdClearArea); truelight@0: truelight@543: DEF_COMMAND(CmdGiveMoney); truelight@0: DEF_COMMAND(CmdMoneyCheat); truelight@0: DEF_COMMAND(CmdBuildCanal); darkvater@147: DEF_COMMAND(CmdBuildLock); truelight@0: truelight@0: DEF_COMMAND(CmdPlayerCtrl); truelight@0: truelight@0: DEF_COMMAND(CmdLevelLand); truelight@0: truelight@0: DEF_COMMAND(CmdRefitRailVehicle); truelight@0: darkvater@1227: DEF_COMMAND(CmdBuildSignalTrack); darkvater@1227: DEF_COMMAND(CmdRemoveSignalTrack); darkvater@58: peter1138@4661: DEF_COMMAND(CmdSetAutoReplace); truelight@812: bjarni@2244: DEF_COMMAND(CmdCloneVehicle); bjarni@4640: DEF_COMMAND(CmdMassStartStopVehicle); bjarni@4659: DEF_COMMAND(CmdDepotSellAllVehicles); bjarni@4662: DEF_COMMAND(CmdDepotMassAutoReplace); bjarni@2244: rubidium@6643: DEF_COMMAND(CmdCreateGroup); rubidium@6643: DEF_COMMAND(CmdRenameGroup); rubidium@6643: DEF_COMMAND(CmdDeleteGroup); rubidium@6643: DEF_COMMAND(CmdAddVehicleGroup); rubidium@6643: DEF_COMMAND(CmdAddSharedVehicleGroup); rubidium@6643: DEF_COMMAND(CmdRemoveAllVehiclesGroup); peter1138@6667: DEF_COMMAND(CmdSetGroupReplaceProtection); peter1138@6667: rubidium@6832: DEF_COMMAND(CmdMoveOrder); maedhros@6980: DEF_COMMAND(CmdChangeTimetable); maedhros@6980: DEF_COMMAND(CmdSetVehicleOnTime); maedhros@7066: DEF_COMMAND(CmdAutofillTimetable); rubidium@7559: #undef DEF_COMMAND Darkvater@1804: rubidium@7559: /** rubidium@7559: * The master command table rubidium@7559: * rubidium@7559: * This table contains all possible CommandProc functions with rubidium@7559: * the flags which belongs to it. The indizes are the same rubidium@7559: * as the value from the CMD_* enums. rubidium@7559: */ rubidium@7559: static const Command _command_proc_table[] = { rubidium@7559: {CmdBuildRailroadTrack, CMD_AUTO}, /* 0, CMD_BUILD_RAILROAD_TRACK */ rubidium@7559: {CmdRemoveRailroadTrack, CMD_AUTO}, /* 1, CMD_REMOVE_RAILROAD_TRACK */ rubidium@7559: {CmdBuildSingleRail, CMD_AUTO}, /* 2, CMD_BUILD_SINGLE_RAIL */ rubidium@7559: {CmdRemoveSingleRail, CMD_AUTO}, /* 3, CMD_REMOVE_SINGLE_RAIL */ rubidium@7559: {CmdLandscapeClear, 0}, /* 4, CMD_LANDSCAPE_CLEAR */ rubidium@7559: {CmdBuildBridge, CMD_AUTO}, /* 5, CMD_BUILD_BRIDGE */ rubidium@7559: {CmdBuildRailroadStation, CMD_AUTO}, /* 6, CMD_BUILD_RAILROAD_STATION */ rubidium@7559: {CmdBuildTrainDepot, CMD_AUTO}, /* 7, CMD_BUILD_TRAIN_DEPOT */ rubidium@7559: {CmdBuildSingleSignal, CMD_AUTO}, /* 8, CMD_BUILD_SIGNALS */ rubidium@7559: {CmdRemoveSingleSignal, CMD_AUTO}, /* 9, CMD_REMOVE_SIGNALS */ rubidium@7559: {CmdTerraformLand, CMD_AUTO}, /* 10, CMD_TERRAFORM_LAND */ rubidium@7559: {CmdPurchaseLandArea, CMD_AUTO}, /* 11, CMD_PURCHASE_LAND_AREA */ rubidium@7559: {CmdSellLandArea, 0}, /* 12, CMD_SELL_LAND_AREA */ rubidium@7559: {CmdBuildTunnel, CMD_AUTO}, /* 13, CMD_BUILD_TUNNEL */ rubidium@7559: {CmdRemoveFromRailroadStation, 0}, /* 14, CMD_REMOVE_FROM_RAILROAD_STATION */ rubidium@7559: {CmdConvertRail, 0}, /* 15, CMD_CONVERT_RAILD */ rubidium@7559: {CmdBuildTrainWaypoint, 0}, /* 16, CMD_BUILD_TRAIN_WAYPOINT */ rubidium@7559: {CmdRenameWaypoint, 0}, /* 17, CMD_RENAME_WAYPOINT */ rubidium@7559: {CmdRemoveTrainWaypoint, 0}, /* 18, CMD_REMOVE_TRAIN_WAYPOINT */ rubidium@7559: {NULL, 0}, /* 19, unused */ rubidium@7559: {NULL, 0}, /* 20, unused */ rubidium@7559: {CmdBuildRoadStop, CMD_AUTO}, /* 21, CMD_BUILD_ROAD_STOP */ rubidium@7559: {CmdRemoveRoadStop, 0}, /* 22, CMD_REMOVE_ROAD_STOP */ rubidium@7559: {CmdBuildLongRoad, CMD_AUTO}, /* 23, CMD_BUILD_LONG_ROAD */ rubidium@7559: {CmdRemoveLongRoad, CMD_AUTO}, /* 24, CMD_REMOVE_LONG_ROAD */ rubidium@7559: {CmdBuildRoad, 0}, /* 25, CMD_BUILD_ROAD */ rubidium@7559: {CmdRemoveRoad, 0}, /* 26, CMD_REMOVE_ROAD */ rubidium@7559: {CmdBuildRoadDepot, CMD_AUTO}, /* 27, CMD_BUILD_ROAD_DEPOT */ rubidium@7559: {NULL, 0}, /* 28, unused */ rubidium@7559: {CmdBuildAirport, CMD_AUTO}, /* 29, CMD_BUILD_AIRPORT */ rubidium@7559: {CmdBuildDock, CMD_AUTO}, /* 30, CMD_BUILD_DOCK */ rubidium@7559: {CmdBuildShipDepot, CMD_AUTO}, /* 31, CMD_BUILD_SHIP_DEPOT */ rubidium@7559: {CmdBuildBuoy, CMD_AUTO}, /* 32, CMD_BUILD_BUOY */ rubidium@7559: {CmdPlantTree, CMD_AUTO}, /* 33, CMD_PLANT_TREE */ rubidium@7559: {CmdBuildRailVehicle, 0}, /* 34, CMD_BUILD_RAIL_VEHICLE */ rubidium@7559: {CmdMoveRailVehicle, 0}, /* 35, CMD_MOVE_RAIL_VEHICLE */ rubidium@7559: {CmdStartStopTrain, 0}, /* 36, CMD_START_STOP_TRAIN */ rubidium@7559: {NULL, 0}, /* 37, unused */ rubidium@7559: {CmdSellRailWagon, 0}, /* 38, CMD_SELL_RAIL_WAGON */ rubidium@7559: {CmdSendTrainToDepot, 0}, /* 39, CMD_SEND_TRAIN_TO_DEPOT */ rubidium@7559: {CmdForceTrainProceed, 0}, /* 40, CMD_FORCE_TRAIN_PROCEED */ rubidium@7559: {CmdReverseTrainDirection, 0}, /* 41, CMD_REVERSE_TRAIN_DIRECTION */ Darkvater@1804: rubidium@7559: {CmdModifyOrder, 0}, /* 42, CMD_MODIFY_ORDER */ rubidium@7559: {CmdSkipToOrder, 0}, /* 43, CMD_SKIP_TO_ORDER */ rubidium@7559: {CmdDeleteOrder, 0}, /* 44, CMD_DELETE_ORDER */ rubidium@7559: {CmdInsertOrder, 0}, /* 45, CMD_INSERT_ORDER */ Darkvater@1804: rubidium@7559: {CmdChangeServiceInt, 0}, /* 46, CMD_CHANGE_SERVICE_INT */ rubidium@7559: rubidium@7559: {CmdBuildIndustry, 0}, /* 47, CMD_BUILD_INDUSTRY */ rubidium@7559: {CmdBuildCompanyHQ, CMD_AUTO}, /* 48, CMD_BUILD_COMPANY_HQ */ rubidium@7559: {CmdSetPlayerFace, 0}, /* 49, CMD_SET_PLAYER_FACE */ rubidium@7559: {CmdSetPlayerColor, 0}, /* 50, CMD_SET_PLAYER_COLOR */ rubidium@7559: rubidium@7559: {CmdIncreaseLoan, 0}, /* 51, CMD_INCREASE_LOAN */ rubidium@7559: {CmdDecreaseLoan, 0}, /* 52, CMD_DECREASE_LOAN */ rubidium@7559: rubidium@7559: {CmdWantEnginePreview, 0}, /* 53, CMD_WANT_ENGINE_PREVIEW */ rubidium@7559: rubidium@7559: {CmdNameVehicle, 0}, /* 54, CMD_NAME_VEHICLE */ rubidium@7559: {CmdRenameEngine, 0}, /* 55, CMD_RENAME_ENGINE */ rubidium@7559: rubidium@7559: {CmdChangeCompanyName, 0}, /* 56, CMD_CHANGE_COMPANY_NAME */ rubidium@7559: {CmdChangePresidentName, 0}, /* 57, CMD_CHANGE_PRESIDENT_NAME */ rubidium@7559: rubidium@7559: {CmdRenameStation, 0}, /* 58, CMD_RENAME_STATION */ rubidium@7559: rubidium@7559: {CmdSellAircraft, 0}, /* 59, CMD_SELL_AIRCRAFT */ rubidium@7559: {CmdStartStopAircraft, 0}, /* 60, CMD_START_STOP_AIRCRAFT */ rubidium@7559: rubidium@7559: {CmdBuildAircraft, 0}, /* 61, CMD_BUILD_AIRCRAFT */ rubidium@7559: {CmdSendAircraftToHangar, 0}, /* 62, CMD_SEND_AIRCRAFT_TO_HANGAR */ rubidium@7559: {NULL, 0}, /* 63, unused */ rubidium@7559: {CmdRefitAircraft, 0}, /* 64, CMD_REFIT_AIRCRAFT */ rubidium@7559: rubidium@7559: {CmdPlaceSign, 0}, /* 65, CMD_PLACE_SIGN */ rubidium@7559: {CmdRenameSign, 0}, /* 66, CMD_RENAME_SIGN */ rubidium@7559: rubidium@7559: {CmdBuildRoadVeh, 0}, /* 67, CMD_BUILD_ROAD_VEH */ rubidium@7559: {CmdStartStopRoadVeh, 0}, /* 68, CMD_START_STOP_ROADVEH */ rubidium@7559: {CmdSellRoadVeh, 0}, /* 69, CMD_SELL_ROAD_VEH */ rubidium@7559: {CmdSendRoadVehToDepot, 0}, /* 70, CMD_SEND_ROADVEH_TO_DEPOT */ rubidium@7559: {CmdTurnRoadVeh, 0}, /* 71, CMD_TURN_ROADVEH */ rubidium@7559: {CmdRefitRoadVeh, 0}, /* 72, CMD_REFIT_ROAD_VEH */ rubidium@7559: rubidium@7559: {CmdPause, CMD_SERVER}, /* 73, CMD_PAUSE */ rubidium@7559: rubidium@7559: {CmdBuyShareInCompany, 0}, /* 74, CMD_BUY_SHARE_IN_COMPANY */ rubidium@7559: {CmdSellShareInCompany, 0}, /* 75, CMD_SELL_SHARE_IN_COMPANY */ rubidium@7559: {CmdBuyCompany, 0}, /* 76, CMD_BUY_COMANY */ rubidium@7559: rubidium@7559: {CmdBuildTown, CMD_OFFLINE}, /* 77, CMD_BUILD_TOWN */ rubidium@7559: {NULL, 0}, /* 78, unused */ rubidium@7559: {NULL, 0}, /* 79, unused */ rubidium@7559: {CmdRenameTown, CMD_SERVER}, /* 80, CMD_RENAME_TOWN */ rubidium@7559: {CmdDoTownAction, 0}, /* 81, CMD_DO_TOWN_ACTION */ rubidium@7559: rubidium@7559: {CmdSetRoadDriveSide, CMD_SERVER}, /* 82, CMD_SET_ROAD_DRIVE_SIDE */ rubidium@7559: {NULL, 0}, /* 83, unused */ rubidium@7559: {NULL, 0}, /* 84, unused */ rubidium@7559: {CmdChangeDifficultyLevel, CMD_SERVER}, /* 85, CMD_CHANGE_DIFFICULTY_LEVEL */ rubidium@7559: rubidium@7559: {CmdStartStopShip, 0}, /* 86, CMD_START_STOP_SHIP */ rubidium@7559: {CmdSellShip, 0}, /* 87, CMD_SELL_SHIP */ rubidium@7559: {CmdBuildShip, 0}, /* 88, CMD_BUILD_SHIP */ rubidium@7559: {CmdSendShipToDepot, 0}, /* 89, CMD_SEND_SHIP_TO_DEPOT */ rubidium@7559: {NULL, 0}, /* 90, unused */ rubidium@7559: {CmdRefitShip, 0}, /* 91, CMD_REFIT_SHIP */ rubidium@7559: rubidium@7559: {NULL, 0}, /* 92, unused */ rubidium@7559: {NULL, 0}, /* 93, unused */ rubidium@7559: {NULL, 0}, /* 94, unused */ rubidium@7559: {NULL, 0}, /* 95, unused */ rubidium@7559: {NULL, 0}, /* 96, unused */ rubidium@7559: {NULL, 0}, /* 97, unused */ rubidium@7559: rubidium@7559: {CmdOrderRefit, 0}, /* 98, CMD_ORDER_REFIT */ rubidium@7559: {CmdCloneOrder, 0}, /* 99, CMD_CLONE_ORDER */ rubidium@7559: rubidium@7559: {CmdClearArea, 0}, /* 100, CMD_CLEAR_AREA */ rubidium@7559: {NULL, 0}, /* 101, unused */ rubidium@7559: rubidium@7559: {CmdMoneyCheat, CMD_OFFLINE}, /* 102, CMD_MONEY_CHEAT */ rubidium@7559: {CmdBuildCanal, CMD_AUTO}, /* 103, CMD_BUILD_CANAL */ rubidium@7559: {CmdPlayerCtrl, 0}, /* 104, CMD_PLAYER_CTRL */ rubidium@7559: rubidium@7559: {CmdLevelLand, CMD_AUTO}, /* 105, CMD_LEVEL_LAND */ rubidium@7559: rubidium@7559: {CmdRefitRailVehicle, 0}, /* 106, CMD_REFIT_RAIL_VEHICLE */ rubidium@7559: {CmdRestoreOrderIndex, 0}, /* 107, CMD_RESTORE_ORDER_INDEX */ rubidium@7559: {CmdBuildLock, CMD_AUTO}, /* 108, CMD_BUILD_LOCK */ rubidium@7559: {NULL, 0}, /* 109, unused */ rubidium@7559: {CmdBuildSignalTrack, CMD_AUTO}, /* 110, CMD_BUILD_SIGNAL_TRACK */ rubidium@7559: {CmdRemoveSignalTrack, CMD_AUTO}, /* 111, CMD_REMOVE_SIGNAL_TRACK */ rubidium@7559: {NULL, 0}, /* 112, unused */ rubidium@7559: {CmdGiveMoney, 0}, /* 113, CMD_GIVE_MONEY */ rubidium@7559: {CmdChangePatchSetting, CMD_SERVER}, /* 114, CMD_CHANGE_PATCH_SETTING */ rubidium@7559: {CmdSetAutoReplace, 0}, /* 115, CMD_SET_AUTOREPLACE */ rubidium@7559: {CmdCloneVehicle, 0}, /* 116, CMD_CLONE_VEHICLE */ rubidium@7559: {CmdMassStartStopVehicle, 0}, /* 117, CMD_MASS_START_STOP */ rubidium@7559: {CmdDepotSellAllVehicles, 0}, /* 118, CMD_DEPOT_SELL_ALL_VEHICLES */ rubidium@7559: {CmdDepotMassAutoReplace, 0}, /* 119, CMD_DEPOT_MASS_AUTOREPLACE */ rubidium@7559: {CmdCreateGroup, 0}, /* 120, CMD_CREATE_GROUP */ rubidium@7559: {CmdDeleteGroup, 0}, /* 121, CMD_DELETE_GROUP */ rubidium@7559: {CmdRenameGroup, 0}, /* 122, CMD_RENAME_GROUP */ rubidium@7559: {CmdAddVehicleGroup, 0}, /* 123, CMD_ADD_VEHICLE_GROUP */ rubidium@7559: {CmdAddSharedVehicleGroup, 0}, /* 124, CMD_ADD_SHARE_VEHICLE_GROUP */ rubidium@7559: {CmdRemoveAllVehiclesGroup, 0}, /* 125, CMD_REMOVE_ALL_VEHICLES_GROUP */ rubidium@7559: {CmdSetGroupReplaceProtection, 0}, /* 126, CMD_SET_GROUP_REPLACE_PROTECTION */ rubidium@7559: {CmdMoveOrder, 0}, /* 127, CMD_MOVE_ORDER */ rubidium@7559: {CmdChangeTimetable, 0}, /* 128, CMD_CHANGE_TIMETABLE */ rubidium@7559: {CmdSetVehicleOnTime, 0}, /* 129, CMD_SET_VEHICLE_ON_TIME */ rubidium@7559: {CmdAutofillTimetable, 0}, /* 130, CMD_AUTOFILL_TIMETABLE */ truelight@0: }; truelight@0: rubidium@7559: /*! rubidium@7559: * This function range-checks a cmd, and checks if the cmd is not NULL rubidium@7559: * rubidium@7559: * @param cmd The integervalue of a command rubidium@7559: * @return true if the command is valid (and got a CommandProc function) rubidium@7559: */ tron@959: bool IsValidCommand(uint cmd) truelight@903: { tron@2645: cmd &= 0xFF; truelight@903: tron@2645: return tron@2645: cmd < lengthof(_command_proc_table) && tron@2645: _command_proc_table[cmd].proc != NULL; truelight@903: } truelight@903: rubidium@7559: /*! rubidium@7559: * This function mask the parameter with 0xFF and returns rubidium@7559: * the flags which belongs to the given command. rubidium@7559: * rubidium@7559: * @param cmd The integer value of the command rubidium@7559: * @return The flags for this command rubidium@7559: * @bug integervalues which are less equals 0xFF and greater than the rubidium@7559: * size of _command_proc_table can result in an index out of bounce rubidium@7559: * error (which doesn't happend anyway). Check function #IsValidCommand(). (Progman) rubidium@7559: */ tron@4000: byte GetCommandFlags(uint cmd) tron@4000: { tron@4000: return _command_proc_table[cmd & 0xFF].flags; tron@4000: } Darkvater@1804: tron@2304: static int _docommand_recursive; tron@2304: rubidium@7559: /*! rubidium@7559: * This function executes a given command with the parameters from the #CommandProc parameter list. rubidium@7559: * Depending on the flags parameter it execute or test a command. rubidium@7559: * rubidium@7559: * @param tile The tile to apply the command on (for the #CommandProc) rubidium@7559: * @param p1 Additional data for the command (for the #CommandProc) rubidium@7559: * @param p2 Additional data for the command (for the #CommandProc) rubidium@7559: * @param flags Flags for the command and how to execute the command rubidium@7559: * @param procc The command-id to execute (a value of the CMD_* enums) rubidium@7559: * @see CommandProc rubidium@7559: */ rubidium@6943: CommandCost DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc) truelight@0: { rubidium@6943: CommandCost res; truelight@0: CommandProc *proc; truelight@193: Darkvater@1776: /* Do not even think about executing out-of-bounds tile-commands */ rubidium@6630: if (tile >= MapSize() || IsTileType(tile, MP_VOID)) { tron@1820: _cmd_text = NULL; tron@1820: return CMD_ERROR; tron@1820: } Darkvater@1776: Darkvater@1804: proc = _command_proc_table[procc].proc; truelight@0: Darkvater@2749: if (_docommand_recursive == 0) _error_message = INVALID_STRING_ID; truelight@0: truelight@0: _docommand_recursive++; truelight@0: belugas@6123: /* only execute the test call if it's toplevel, or we're not execing. */ truelight@0: if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) { tron@3491: res = proc(tile, flags & ~DC_EXEC, p1, p2); tron@1691: if (CmdFailed(res)) { rubidium@6950: res.SetGlobalErrorMessage(); truelight@0: goto error; truelight@0: } truelight@0: tron@4000: if (_docommand_recursive == 1 && tron@4000: !(flags & DC_QUERY_COST) && rubidium@6950: res.GetCost() != 0 && tron@4000: !CheckPlayerHasMoney(res)) { tron@4000: goto error; truelight@0: } truelight@0: truelight@0: if (!(flags & DC_EXEC)) { truelight@0: _docommand_recursive--; tron@1820: _cmd_text = NULL; truelight@0: return res; truelight@0: } truelight@0: } truelight@0: darkvater@889: /* Execute the command here. All cost-relevant functions set the expenses type darkvater@889: * themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */ tron@3491: res = proc(tile, flags, p1, p2); tron@1691: if (CmdFailed(res)) { rubidium@6950: res.SetGlobalErrorMessage(); truelight@0: error: truelight@0: _docommand_recursive--; tron@1820: _cmd_text = NULL; truelight@0: return CMD_ERROR; truelight@0: } truelight@0: belugas@6123: /* if toplevel, subtract the money. */ truelight@0: if (--_docommand_recursive == 0) { truelight@0: SubtractMoneyFromPlayer(res); belugas@6123: /* XXX - Old AI hack which doesn't use DoCommandDP; update last build coord of player */ Darkvater@4850: if (tile != 0 && IsValidPlayer(_current_player)) { tron@3491: GetPlayer(_current_player)->last_build_coordinate = tile; Darkvater@2772: } truelight@0: } truelight@0: tron@1820: _cmd_text = NULL; truelight@0: return res; truelight@0: } truelight@0: rubidium@7559: /*! rubidium@7559: * This functions returns the money which can be used to execute a command. rubidium@7559: * This is either the money of the current player or INT64_MAX if there rubidium@7559: * is no such a player "at the moment" like the server itself. rubidium@7559: * rubidium@7559: * @return The available money of a player or INT64_MAX rubidium@7559: */ rubidium@6990: Money GetAvailableMoneyForCommand() truelight@0: { Darkvater@1794: PlayerID pid = _current_player; rubidium@6990: if (!IsValidPlayer(pid)) return INT64_MAX; celestar@1962: return GetPlayer(pid)->player_money; truelight@0: } truelight@0: rubidium@7559: /*! rubidium@7559: * Toplevel network safe docommand function for the current player. Must not be called recursively. rubidium@7559: * The callback is called when the command succeeded or failed. The parameters rubidium@7559: * tile, p1 and p2 are from the #CommandProc function. The paramater cmd is the command to execute. rubidium@7559: * The parameter my_cmd is used to indicate if the command is from a player or the server. rubidium@7559: * rubidium@7559: * @param tile The tile to perform a command on (see #CommandProc) rubidium@7559: * @param p1 Additional data for the command (see #CommandProc) rubidium@7559: * @param p2 Additional data for the command (see #CommandProc) rubidium@7559: * @param callback A callback function to call after the command is finished rubidium@7559: * @param cmd The command to execute (a CMD_* value) rubidium@7559: * @param my_cmd indicator if the command is from a player or server (to display error messages for a user) rubidium@7559: * @return true if the command succeeded, else false rubidium@7559: */ rubidium@7222: bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd, bool my_cmd) truelight@0: { rubidium@6950: CommandCost res, res2; truelight@0: CommandProc *proc; truelight@0: uint32 flags; truelight@0: bool notest; tron@3182: StringID error_part1; truelight@0: celestar@3421: int x = TileX(tile) * TILE_SIZE; celestar@3421: int y = TileY(tile) * TILE_SIZE; truelight@0: Darkvater@1776: /* Do not even think about executing out-of-bounds tile-commands */ rubidium@6630: if (tile >= MapSize() || IsTileType(tile, MP_VOID)) { tron@1820: _cmd_text = NULL; tron@1820: return false; tron@1820: } Darkvater@1776: truelight@193: assert(_docommand_recursive == 0); truelight@0: truelight@0: _error_message = INVALID_STRING_ID; tron@3182: error_part1 = GB(cmd, 16, 16); truelight@0: _additional_cash_required = 0; truelight@0: Darkvater@5067: /** Spectator has no rights except for the (dedicated) server which Darkvater@5067: * is/can be a spectator but as the server it can do anything */ Darkvater@5067: if (_current_player == PLAYER_SPECTATOR && !_network_server) { rubidium@7222: if (my_cmd) ShowErrorMessage(_error_message, error_part1, x, y); tron@1820: _cmd_text = NULL; truelight@0: return false; truelight@0: } truelight@0: truelight@0: flags = 0; truelight@0: if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER; truelight@0: belugas@6123: /* get pointer to command handler */ truelight@0: assert((cmd & 0xFF) < lengthof(_command_proc_table)); Darkvater@1804: proc = _command_proc_table[cmd & 0xFF].proc; Darkvater@1877: if (proc == NULL) { Darkvater@1877: _cmd_text = NULL; Darkvater@1877: return false; Darkvater@1877: } truelight@0: rubidium@7521: if (GetCommandFlags(cmd) & CMD_AUTO) flags |= DC_AUTO; rubidium@7521: belugas@6123: /* Some commands have a different output in dryrun than the realrun belugas@6123: * e.g.: if you demolish a whole town, the dryrun would say okay. belugas@6123: * but by really destroying, your rating drops and at a certain point belugas@6123: * it will fail. so res and res2 are different belugas@6123: * CMD_REMOVE_ROAD: This command has special local authority belugas@6123: * restrictions which may cause the test run to fail (the previous belugas@6123: * road fragments still stay there and the town won't let you belugas@6123: * disconnect the road system), but the exec will succeed and this maedhros@6546: * fact will trigger an assertion failure. --pasky maedhros@6546: * CMD_CLONE_VEHICLE: Both building new vehicles and refitting them can be maedhros@6546: * influenced by newgrf callbacks, which makes it impossible to accurately maedhros@6546: * estimate the cost of cloning a vehicle. */ truelight@193: notest = truelight@193: (cmd & 0xFF) == CMD_CLEAR_AREA || truelight@193: (cmd & 0xFF) == CMD_CONVERT_RAIL || truelight@0: (cmd & 0xFF) == CMD_LEVEL_LAND || Darkvater@1701: (cmd & 0xFF) == CMD_REMOVE_ROAD || maedhros@6546: (cmd & 0xFF) == CMD_REMOVE_LONG_ROAD || maedhros@6546: (cmd & 0xFF) == CMD_CLONE_VEHICLE; truelight@0: truelight@0: _docommand_recursive = 1; truelight@0: belugas@6123: /* cost estimation only? */ celestar@5580: if (!IsGeneratingWorld() && celestar@5580: _shift_pressed && celestar@5580: IsLocalPlayer() && celestar@5580: !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR)) && celestar@5580: (cmd & 0xFF) != CMD_PAUSE) { belugas@6123: /* estimate the cost. */ tron@3491: res = proc(tile, flags, p1, p2); tron@1691: if (CmdFailed(res)) { rubidium@6950: res.SetGlobalErrorMessage(); tron@3182: ShowErrorMessage(_error_message, error_part1, x, y); truelight@0: } else { rubidium@6950: ShowEstimatedCostOrIncome(res.GetCost(), x, y); truelight@0: } truelight@0: truelight@0: _docommand_recursive = 0; tron@1820: _cmd_text = NULL; rubidium@7609: ClearStorageChanges(false); truelight@0: return false; truelight@0: } truelight@0: truelight@193: truelight@543: if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) { belugas@6123: /* first test if the command can be executed. */ tron@3491: res = proc(tile, flags, p1, p2); tron@1691: if (CmdFailed(res)) { rubidium@6950: res.SetGlobalErrorMessage(); truelight@0: goto show_error; truelight@0: } belugas@6123: /* no money? Only check if notest is off */ rubidium@6950: if (!notest && res.GetCost() != 0 && !CheckPlayerHasMoney(res)) goto show_error; truelight@0: } truelight@0: truelight@543: #ifdef ENABLE_NETWORK Darkvater@1838: /** If we are in network, and the command is not from the network Darkvater@1838: * send it to the command-queue and abort execution Darkvater@1838: * If we are a dedicated server temporarily switch local player, otherwise Darkvater@1838: * the other parties won't be able to execute our command and will desync. Darkvater@5067: * We also need to do this if the server's company has gone bankrupt Darkvater@5067: * @todo Rewrite (dedicated) server to something more than a dirty hack! Darkvater@1838: */ truelight@543: if (_networking && !(cmd & CMD_NETWORK_COMMAND)) { Darkvater@5067: PlayerID pbck = _local_player; rubidium@5587: if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = PLAYER_FIRST; truelight@543: NetworkSend_Command(tile, p1, p2, cmd, callback); Darkvater@5067: if (_network_dedicated || (_network_server && pbck == PLAYER_SPECTATOR)) _local_player = pbck; truelight@543: _docommand_recursive = 0; tron@1820: _cmd_text = NULL; rubidium@7609: ClearStorageChanges(false); truelight@543: return true; truelight@0: } truelight@543: #endif /* ENABLE_NETWORK */ truelight@0: belugas@6123: /* update last build coordinate of player. */ Darkvater@4850: if (tile != 0 && IsValidPlayer(_current_player)) { tron@4000: GetPlayer(_current_player)->last_build_coordinate = tile; tron@4000: } truelight@0: darkvater@889: /* Actually try and execute the command. If no cost-type is given darkvater@889: * use the construction one */ darkvater@889: _yearly_expenses_type = EXPENSES_CONSTRUCTION; tron@4000: res2 = proc(tile, flags | DC_EXEC, p1, p2); truelight@193: belugas@6123: /* If notest is on, it means the result of the test can be different than belugas@6123: * the real command.. so ignore the test */ truelight@652: if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) { rubidium@6950: assert(res.GetCost() == res2.GetCost() && CmdFailed(res) == CmdFailed(res2)); // sanity check truelight@0: } else { Darkvater@1702: if (CmdFailed(res2)) { rubidium@6950: res.SetGlobalErrorMessage(); truelight@0: goto show_error; truelight@0: } truelight@0: } truelight@0: truelight@0: SubtractMoneyFromPlayer(res2); truelight@0: Darkvater@2425: if (IsLocalPlayer() && _game_mode != GM_EDITOR) { rubidium@7506: if (res2.GetCost() != 0 && tile != 0) ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2.GetCost()); rubidium@6990: if (_additional_cash_required != 0) { rubidium@7002: SetDParam(0, _additional_cash_required); rubidium@7222: if (my_cmd) ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, error_part1, x, y); rubidium@6950: if (res2.GetCost() == 0) goto callb_err; truelight@0: } truelight@0: } truelight@0: truelight@0: _docommand_recursive = 0; truelight@193: truelight@0: if (callback) callback(true, tile, p1, p2); tron@1820: _cmd_text = NULL; rubidium@7609: ClearStorageChanges(true); truelight@0: return true; truelight@0: truelight@0: show_error: belugas@6123: /* show error message if the command fails? */ rubidium@7222: if (IsLocalPlayer() && error_part1 != 0 && my_cmd) { rubidium@6491: ShowErrorMessage(_error_message, error_part1, x, y); tron@3182: } truelight@0: truelight@0: callb_err: truelight@0: _docommand_recursive = 0; truelight@193: truelight@0: if (callback) callback(false, tile, p1, p2); tron@1820: _cmd_text = NULL; rubidium@7609: ClearStorageChanges(false); truelight@0: return false; truelight@0: } rubidium@6950: rubidium@6950: rubidium@6950: CommandCost CommandCost::AddCost(CommandCost ret) rubidium@6950: { rubidium@6957: this->AddCost(ret.cost); rubidium@6950: if (this->success && !ret.success) { rubidium@6950: this->message = ret.message; rubidium@6950: this->success = false; rubidium@6950: } rubidium@6950: return *this; rubidium@6950: } rubidium@6950: rubidium@6953: CommandCost CommandCost::AddCost(Money cost) rubidium@6950: { rubidium@7763: this->cost += cost; rubidium@6950: return *this; rubidium@6950: } rubidium@6950: rubidium@6950: CommandCost CommandCost::MultiplyCost(int factor) rubidium@6950: { rubidium@7763: this->cost *= factor; rubidium@6950: return *this; rubidium@6950: } rubidium@6950: rubidium@6953: Money CommandCost::GetCost() const rubidium@6950: { rubidium@6950: return this->cost; rubidium@6950: } rubidium@6950: rubidium@6950: void CommandCost::SetGlobalErrorMessage() const rubidium@6950: { rubidium@6950: extern StringID _error_message; rubidium@6950: if (this->message != INVALID_STRING_ID) _error_message = this->message; rubidium@6950: } rubidium@6950: rubidium@6950: bool CommandCost::Succeeded() const rubidium@6950: { rubidium@6950: return this->success; rubidium@6950: } rubidium@6950: rubidium@6950: bool CommandCost::Failed() const rubidium@6950: { rubidium@6950: return !this->success; rubidium@6950: }