2005-07-24 15:12:37 +01:00
/* $Id$ */
2008-05-06 16:11:33 +01:00
/** @file command.cpp Handling of commands. */
2007-02-23 11:50:43 +00:00
2004-08-09 18:04:08 +01:00
# include "stdafx.h"
2005-06-02 20:30:21 +01:00
# include "openttd.h"
2007-04-12 14:07:15 +01:00
# include "landscape.h"
2007-12-19 23:26:02 +00:00
# include "tile_map.h"
2004-08-09 18:04:08 +01:00
# include "gui.h"
2007-12-21 21:50:46 +00:00
# include "command_func.h"
2007-01-02 17:34:03 +00:00
# include "network/network.h"
2005-07-21 23:15:02 +01:00
# include "variables.h"
(svn r5946) -Add: merged the TGP branch to mainline. TGP adds:
- New optional landscape generator (TerraGenesis Perlin)
- Load heightmaps (either BMP or PNG)
- Progress dialog while generating worlds (no longer a 'hanging' screen)
- New dialogs for NewGame, Create Scenario and Play Heightmap
- Easier to configure your landscape
- More things to configure (tree-placer, ..)
- Speedup of world generation
- New console command 'restart': restart the map EXACTLY as it was when you
first started it (needs a game made after or with this commit)
- New console command 'getseed': get the seed of your map and share it with
others (of course only works with generated maps)
- Many new, world generation related, things
- Many internal cleanups and rewrites
Many tnx to those people who helped making this:
Belugas, DaleStan, glx, KUDr, RichK67, Rubidium, and TrueLight (alfabetic)
Many tnx to those who helped testing:
Arnau, Bjarni, and tokai (alfabetic)
And to all other people who helped testing and sending comments / bugs
Stats: 673 lines changed, 3534 new lines, 79 new strings
2006-08-19 11:00:30 +01:00
# include "genworld.h"
2007-09-22 13:59:43 +01:00
# include "newgrf_storage.h"
2007-12-21 19:49:27 +00:00
# include "strings_func.h"
2007-12-23 10:56:02 +00:00
# include "gfx_func.h"
2007-12-25 11:26:07 +00:00
# include "functions.h"
2008-01-09 17:47:05 +00:00
# include "town.h"
2008-01-11 00:30:32 +00:00
# include "date_func.h"
# include "debug.h"
2008-09-30 21:51:04 +01:00
# include "company_func.h"
# include "company_base.h"
2008-01-16 01:18:15 +00:00
# include "signal_func.h"
2004-08-09 18:04:08 +01:00
2008-01-13 01:21:35 +00:00
# include "table/strings.h"
2008-01-13 21:41:24 +00:00
StringID _error_message ;
2007-09-10 16:21:14 +01:00
/**
* Helper macro to define the header of all command handler macros .
*
* This macro create the function header for a given command handler function , as
* all command handler functions got the parameters from the # CommandProc callback
* type .
*
* @ param yyyy The desired function name of the new command handler function .
*/
2008-12-28 14:37:19 +00:00
# define DEF_COMMAND(yyyy) CommandCost yyyy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
2004-08-09 18:04:08 +01:00
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 ) ;
2005-01-30 15:57:38 +00:00
DEF_COMMAND ( CmdBuildSingleSignal ) ;
DEF_COMMAND ( CmdRemoveSingleSignal ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdTerraformLand ) ;
DEF_COMMAND ( CmdPurchaseLandArea ) ;
DEF_COMMAND ( CmdSellLandArea ) ;
DEF_COMMAND ( CmdBuildTunnel ) ;
DEF_COMMAND ( CmdBuildTrainDepot ) ;
2004-11-14 13:07:07 +00:00
DEF_COMMAND ( CmdBuildTrainWaypoint ) ;
DEF_COMMAND ( CmdRenameWaypoint ) ;
DEF_COMMAND ( CmdRemoveTrainWaypoint ) ;
2004-08-09 18:04:08 +01:00
2005-01-29 19:41:44 +00:00
DEF_COMMAND ( CmdBuildRoadStop ) ;
2007-02-14 16:37:16 +00:00
DEF_COMMAND ( CmdRemoveRoadStop ) ;
2004-08-09 18:04:08 +01:00
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 ( CmdSellRailWagon ) ;
2005-05-12 01:18:30 +01:00
DEF_COMMAND ( CmdSendTrainToDepot ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdForceTrainProceed ) ;
DEF_COMMAND ( CmdReverseTrainDirection ) ;
DEF_COMMAND ( CmdModifyOrder ) ;
2007-06-04 20:32:45 +01:00
DEF_COMMAND ( CmdSkipToOrder ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdDeleteOrder ) ;
DEF_COMMAND ( CmdInsertOrder ) ;
2006-01-05 21:35:54 +00:00
DEF_COMMAND ( CmdChangeServiceInt ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdRestoreOrderIndex ) ;
DEF_COMMAND ( CmdBuildIndustry ) ;
DEF_COMMAND ( CmdBuildCompanyHQ ) ;
2008-09-30 21:39:50 +01:00
DEF_COMMAND ( CmdSetCompanyManagerFace ) ;
DEF_COMMAND ( CmdSetCompanyColor ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdIncreaseLoan ) ;
DEF_COMMAND ( CmdDecreaseLoan ) ;
DEF_COMMAND ( CmdWantEnginePreview ) ;
2008-09-15 23:58:41 +01:00
DEF_COMMAND ( CmdRenameVehicle ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdRenameEngine ) ;
2008-09-15 23:58:41 +01:00
DEF_COMMAND ( CmdRenameCompany ) ;
DEF_COMMAND ( CmdRenamePresident ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdRenameStation ) ;
DEF_COMMAND ( CmdSellAircraft ) ;
DEF_COMMAND ( CmdBuildAircraft ) ;
DEF_COMMAND ( CmdSendAircraftToHangar ) ;
DEF_COMMAND ( CmdRefitAircraft ) ;
DEF_COMMAND ( CmdPlaceSign ) ;
DEF_COMMAND ( CmdRenameSign ) ;
DEF_COMMAND ( CmdBuildRoadVeh ) ;
DEF_COMMAND ( CmdSellRoadVeh ) ;
DEF_COMMAND ( CmdSendRoadVehToDepot ) ;
DEF_COMMAND ( CmdTurnRoadVeh ) ;
2006-06-09 08:45:26 +01:00
DEF_COMMAND ( CmdRefitRoadVeh ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdPause ) ;
DEF_COMMAND ( CmdBuyShareInCompany ) ;
DEF_COMMAND ( CmdSellShareInCompany ) ;
DEF_COMMAND ( CmdBuyCompany ) ;
DEF_COMMAND ( CmdBuildTown ) ;
DEF_COMMAND ( CmdRenameTown ) ;
DEF_COMMAND ( CmdDoTownAction ) ;
DEF_COMMAND ( CmdSetRoadDriveSide ) ;
2004-12-04 17:54:56 +00:00
DEF_COMMAND ( CmdChangePatchSetting ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdSellShip ) ;
DEF_COMMAND ( CmdBuildShip ) ;
DEF_COMMAND ( CmdSendShipToDepot ) ;
DEF_COMMAND ( CmdRefitShip ) ;
2006-10-03 15:52:39 +01:00
DEF_COMMAND ( CmdOrderRefit ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdCloneOrder ) ;
DEF_COMMAND ( CmdClearArea ) ;
2004-12-04 17:54:56 +00:00
DEF_COMMAND ( CmdGiveMoney ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdMoneyCheat ) ;
DEF_COMMAND ( CmdBuildCanal ) ;
2004-09-01 22:54:12 +01:00
DEF_COMMAND ( CmdBuildLock ) ;
2004-08-09 18:04:08 +01:00
2008-09-30 21:39:50 +01:00
DEF_COMMAND ( CmdCompanyCtrl ) ;
2004-08-09 18:04:08 +01:00
DEF_COMMAND ( CmdLevelLand ) ;
DEF_COMMAND ( CmdRefitRailVehicle ) ;
2005-01-30 15:57:38 +00:00
DEF_COMMAND ( CmdBuildSignalTrack ) ;
DEF_COMMAND ( CmdRemoveSignalTrack ) ;
2004-08-15 21:23:42 +01:00
2006-09-28 08:02:55 +01:00
DEF_COMMAND ( CmdSetAutoReplace ) ;
2004-12-27 18:18:44 +00:00
2005-07-31 14:08:08 +01:00
DEF_COMMAND ( CmdCloneVehicle ) ;
2008-08-15 14:57:43 +01:00
DEF_COMMAND ( CmdStartStopVehicle ) ;
2006-09-26 20:20:35 +01:00
DEF_COMMAND ( CmdMassStartStopVehicle ) ;
2008-08-16 15:02:20 +01:00
DEF_COMMAND ( CmdAutoreplaceVehicle ) ;
2006-09-27 23:44:39 +01:00
DEF_COMMAND ( CmdDepotSellAllVehicles ) ;
2006-09-28 15:17:08 +01:00
DEF_COMMAND ( CmdDepotMassAutoReplace ) ;
2005-07-31 14:08:08 +01:00
2007-05-19 10:40:18 +01:00
DEF_COMMAND ( CmdCreateGroup ) ;
DEF_COMMAND ( CmdRenameGroup ) ;
DEF_COMMAND ( CmdDeleteGroup ) ;
DEF_COMMAND ( CmdAddVehicleGroup ) ;
DEF_COMMAND ( CmdAddSharedVehicleGroup ) ;
DEF_COMMAND ( CmdRemoveAllVehiclesGroup ) ;
2007-05-22 20:48:11 +01:00
DEF_COMMAND ( CmdSetGroupReplaceProtection ) ;
2007-06-08 19:59:29 +01:00
DEF_COMMAND ( CmdMoveOrder ) ;
2007-06-20 20:17:22 +01:00
DEF_COMMAND ( CmdChangeTimetable ) ;
DEF_COMMAND ( CmdSetVehicleOnTime ) ;
2007-06-25 21:55:43 +01:00
DEF_COMMAND ( CmdAutofillTimetable ) ;
2007-09-10 16:21:14 +01:00
# undef DEF_COMMAND
/**
* The master command table
*
* This table contains all possible CommandProc functions with
* the flags which belongs to it . The indizes are the same
* as the value from the CMD_ * enums .
*/
2005-05-14 20:25:18 +01:00
static const Command _command_proc_table [ ] = {
2009-01-07 14:45:07 +00:00
{ CmdBuildRailroadTrack , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_RAILROAD_TRACK */
{ CmdRemoveRailroadTrack , CMD_AUTO } , /* CMD_REMOVE_RAILROAD_TRACK */
{ CmdBuildSingleRail , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_SINGLE_RAIL */
{ CmdRemoveSingleRail , CMD_AUTO } , /* CMD_REMOVE_SINGLE_RAIL */
{ CmdLandscapeClear , 0 } , /* CMD_LANDSCAPE_CLEAR */
{ CmdBuildBridge , CMD_AUTO } , /* CMD_BUILD_BRIDGE */
{ CmdBuildRailroadStation , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_RAILROAD_STATION */
{ CmdBuildTrainDepot , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_TRAIN_DEPOT */
{ CmdBuildSingleSignal , CMD_AUTO } , /* CMD_BUILD_SIGNALS */
{ CmdRemoveSingleSignal , CMD_AUTO } , /* CMD_REMOVE_SIGNALS */
{ CmdTerraformLand , CMD_AUTO } , /* CMD_TERRAFORM_LAND */
{ CmdPurchaseLandArea , CMD_NO_WATER | CMD_AUTO } , /* CMD_PURCHASE_LAND_AREA */
{ CmdSellLandArea , 0 } , /* CMD_SELL_LAND_AREA */
{ CmdBuildTunnel , CMD_AUTO } , /* CMD_BUILD_TUNNEL */
{ CmdRemoveFromRailroadStation , 0 } , /* CMD_REMOVE_FROM_RAILROAD_STATION */
{ CmdConvertRail , 0 } , /* CMD_CONVERT_RAILD */
{ CmdBuildTrainWaypoint , 0 } , /* CMD_BUILD_TRAIN_WAYPOINT */
{ CmdRenameWaypoint , 0 } , /* CMD_RENAME_WAYPOINT */
{ CmdRemoveTrainWaypoint , 0 } , /* CMD_REMOVE_TRAIN_WAYPOINT */
{ CmdBuildRoadStop , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_ROAD_STOP */
{ CmdRemoveRoadStop , 0 } , /* CMD_REMOVE_ROAD_STOP */
{ CmdBuildLongRoad , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_LONG_ROAD */
{ CmdRemoveLongRoad , CMD_NO_TEST | CMD_AUTO } , /* CMD_REMOVE_LONG_ROAD; towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed. */
{ CmdBuildRoad , 0 } , /* CMD_BUILD_ROAD */
{ CmdRemoveRoad , 0 } , /* CMD_REMOVE_ROAD */
{ CmdBuildRoadDepot , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_ROAD_DEPOT */
{ CmdBuildAirport , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_AIRPORT */
{ CmdBuildDock , CMD_AUTO } , /* CMD_BUILD_DOCK */
{ CmdBuildShipDepot , CMD_AUTO } , /* CMD_BUILD_SHIP_DEPOT */
{ CmdBuildBuoy , CMD_AUTO } , /* CMD_BUILD_BUOY */
{ CmdPlantTree , CMD_AUTO } , /* CMD_PLANT_TREE */
{ CmdBuildRailVehicle , 0 } , /* CMD_BUILD_RAIL_VEHICLE */
{ CmdMoveRailVehicle , 0 } , /* CMD_MOVE_RAIL_VEHICLE */
{ CmdSellRailWagon , 0 } , /* CMD_SELL_RAIL_WAGON */
{ CmdSendTrainToDepot , 0 } , /* CMD_SEND_TRAIN_TO_DEPOT */
{ CmdForceTrainProceed , 0 } , /* CMD_FORCE_TRAIN_PROCEED */
{ CmdReverseTrainDirection , 0 } , /* CMD_REVERSE_TRAIN_DIRECTION */
{ CmdModifyOrder , 0 } , /* CMD_MODIFY_ORDER */
{ CmdSkipToOrder , 0 } , /* CMD_SKIP_TO_ORDER */
{ CmdDeleteOrder , 0 } , /* CMD_DELETE_ORDER */
{ CmdInsertOrder , 0 } , /* CMD_INSERT_ORDER */
{ CmdChangeServiceInt , 0 } , /* CMD_CHANGE_SERVICE_INT */
{ CmdBuildIndustry , 0 } , /* CMD_BUILD_INDUSTRY */
{ CmdBuildCompanyHQ , CMD_NO_WATER | CMD_AUTO } , /* CMD_BUILD_COMPANY_HQ */
{ CmdSetCompanyManagerFace , 0 } , /* CMD_SET_COMPANY_MANAGER_FACE */
{ CmdSetCompanyColor , 0 } , /* CMD_SET_COMPANY_COLOR */
{ CmdIncreaseLoan , 0 } , /* CMD_INCREASE_LOAN */
{ CmdDecreaseLoan , 0 } , /* CMD_DECREASE_LOAN */
{ CmdWantEnginePreview , 0 } , /* CMD_WANT_ENGINE_PREVIEW */
{ CmdRenameVehicle , 0 } , /* CMD_RENAME_VEHICLE */
{ CmdRenameEngine , 0 } , /* CMD_RENAME_ENGINE */
{ CmdRenameCompany , 0 } , /* CMD_RENAME_COMPANY */
{ CmdRenamePresident , 0 } , /* CMD_RENAME_PRESIDENT */
{ CmdRenameStation , 0 } , /* CMD_RENAME_STATION */
{ CmdSellAircraft , 0 } , /* CMD_SELL_AIRCRAFT */
{ CmdBuildAircraft , 0 } , /* CMD_BUILD_AIRCRAFT */
{ CmdSendAircraftToHangar , 0 } , /* CMD_SEND_AIRCRAFT_TO_HANGAR */
{ CmdRefitAircraft , 0 } , /* CMD_REFIT_AIRCRAFT */
{ CmdPlaceSign , 0 } , /* CMD_PLACE_SIGN */
{ CmdRenameSign , 0 } , /* CMD_RENAME_SIGN */
{ CmdBuildRoadVeh , 0 } , /* CMD_BUILD_ROAD_VEH */
{ CmdSellRoadVeh , 0 } , /* CMD_SELL_ROAD_VEH */
{ CmdSendRoadVehToDepot , 0 } , /* CMD_SEND_ROADVEH_TO_DEPOT */
{ CmdTurnRoadVeh , 0 } , /* CMD_TURN_ROADVEH */
{ CmdRefitRoadVeh , 0 } , /* CMD_REFIT_ROAD_VEH */
{ CmdPause , CMD_SERVER } , /* CMD_PAUSE */
{ CmdBuyShareInCompany , 0 } , /* CMD_BUY_SHARE_IN_COMPANY */
{ CmdSellShareInCompany , 0 } , /* CMD_SELL_SHARE_IN_COMPANY */
{ CmdBuyCompany , 0 } , /* CMD_BUY_COMANY */
{ CmdBuildTown , CMD_OFFLINE } , /* CMD_BUILD_TOWN */
{ CmdRenameTown , CMD_SERVER } , /* CMD_RENAME_TOWN */
{ CmdDoTownAction , 0 } , /* CMD_DO_TOWN_ACTION */
{ CmdSetRoadDriveSide , CMD_SERVER } , /* CMD_SET_ROAD_DRIVE_SIDE */
{ CmdSellShip , 0 } , /* CMD_SELL_SHIP */
{ CmdBuildShip , 0 } , /* CMD_BUILD_SHIP */
{ CmdSendShipToDepot , 0 } , /* CMD_SEND_SHIP_TO_DEPOT */
{ CmdRefitShip , 0 } , /* CMD_REFIT_SHIP */
{ CmdOrderRefit , 0 } , /* CMD_ORDER_REFIT */
{ CmdCloneOrder , 0 } , /* CMD_CLONE_ORDER */
{ CmdClearArea , CMD_NO_TEST } , /* CMD_CLEAR_AREA; destroying multi-tile houses makes town rating differ between test and execution */
{ CmdMoneyCheat , CMD_OFFLINE } , /* CMD_MONEY_CHEAT */
{ CmdBuildCanal , CMD_AUTO } , /* CMD_BUILD_CANAL */
{ CmdCompanyCtrl , 0 } , /* CMD_COMPANY_CTRL */
{ CmdLevelLand , CMD_NO_TEST | CMD_AUTO } , /* CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once */
{ CmdRefitRailVehicle , 0 } , /* CMD_REFIT_RAIL_VEHICLE */
{ CmdRestoreOrderIndex , 0 } , /* CMD_RESTORE_ORDER_INDEX */
{ CmdBuildLock , CMD_AUTO } , /* CMD_BUILD_LOCK */
{ CmdBuildSignalTrack , CMD_AUTO } , /* CMD_BUILD_SIGNAL_TRACK */
{ CmdRemoveSignalTrack , CMD_AUTO } , /* CMD_REMOVE_SIGNAL_TRACK */
{ CmdGiveMoney , 0 } , /* CMD_GIVE_MONEY */
{ CmdChangePatchSetting , CMD_SERVER } , /* CMD_CHANGE_PATCH_SETTING */
{ CmdSetAutoReplace , 0 } , /* CMD_SET_AUTOREPLACE */
{ CmdCloneVehicle , CMD_NO_TEST } , /* CMD_CLONE_VEHICLE; NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost */
{ CmdStartStopVehicle , 0 } , /* CMD_START_STOP_VEHICLE */
{ CmdMassStartStopVehicle , 0 } , /* CMD_MASS_START_STOP */
{ CmdAutoreplaceVehicle , 0 } , /* CMD_AUTOREPLACE_VEHICLE */
{ CmdDepotSellAllVehicles , 0 } , /* CMD_DEPOT_SELL_ALL_VEHICLES */
{ CmdDepotMassAutoReplace , 0 } , /* CMD_DEPOT_MASS_AUTOREPLACE */
{ CmdCreateGroup , 0 } , /* CMD_CREATE_GROUP */
{ CmdDeleteGroup , 0 } , /* CMD_DELETE_GROUP */
{ CmdRenameGroup , 0 } , /* CMD_RENAME_GROUP */
{ CmdAddVehicleGroup , 0 } , /* CMD_ADD_VEHICLE_GROUP */
{ CmdAddSharedVehicleGroup , 0 } , /* CMD_ADD_SHARE_VEHICLE_GROUP */
{ CmdRemoveAllVehiclesGroup , 0 } , /* CMD_REMOVE_ALL_VEHICLES_GROUP */
{ CmdSetGroupReplaceProtection , 0 } , /* CMD_SET_GROUP_REPLACE_PROTECTION */
{ CmdMoveOrder , 0 } , /* CMD_MOVE_ORDER */
{ CmdChangeTimetable , 0 } , /* CMD_CHANGE_TIMETABLE */
{ CmdSetVehicleOnTime , 0 } , /* CMD_SET_VEHICLE_ON_TIME */
{ CmdAutofillTimetable , 0 } , /* CMD_AUTOFILL_TIMETABLE */
2004-08-09 18:04:08 +01:00
} ;
2007-09-10 16:21:14 +01:00
/*!
* This function range - checks a cmd , and checks if the cmd is not NULL
*
* @ param cmd The integervalue of a command
* @ return true if the command is valid ( and got a CommandProc function )
*/
2008-10-14 19:49:21 +01:00
bool IsValidCommand ( uint32 cmd )
2005-01-05 14:39:48 +00:00
{
2009-01-07 13:26:48 +00:00
cmd & = CMD_ID_MASK ;
2005-01-05 14:39:48 +00:00
2005-11-15 09:47:25 +00:00
return
cmd < lengthof ( _command_proc_table ) & &
_command_proc_table [ cmd ] . proc ! = NULL ;
2005-01-05 14:39:48 +00:00
}
2007-09-10 16:21:14 +01:00
/*!
2009-01-07 13:26:48 +00:00
* This function mask the parameter with CMD_ID_MASK and returns
2007-09-10 16:21:14 +01:00
* the flags which belongs to the given command .
*
* @ param cmd The integer value of the command
* @ return The flags for this command
*/
2008-10-14 19:49:21 +01:00
byte GetCommandFlags ( uint32 cmd )
2006-06-10 09:37:41 +01:00
{
2008-10-14 19:49:21 +01:00
assert ( IsValidCommand ( cmd ) ) ;
2009-01-07 13:26:48 +00:00
return _command_proc_table [ cmd & CMD_ID_MASK ] . flags ;
2006-06-10 09:37:41 +01:00
}
2005-05-14 20:25:18 +01:00
2008-01-09 17:47:05 +00:00
static int _docommand_recursive = 0 ;
2005-08-07 11:03:14 +01:00
2009-01-08 14:55:28 +00:00
/**
* Shorthand for calling the long DoCommand with a container .
*
* @ param container Container with ( almost ) all information
* @ param flags Flags for the command and how to execute the command
* @ see CommandProc
* @ return the cost
*/
CommandCost DoCommand ( const CommandContainer * container , uint32 flags )
{
2009-01-08 16:35:45 +00:00
return DoCommand ( container - > tile , container - > p1 , container - > p2 , flags , container - > cmd & CMD_ID_MASK , container - > text ) ;
2009-01-08 14:55:28 +00:00
}
2007-09-10 16:21:14 +01:00
/*!
* This function executes a given command with the parameters from the # CommandProc parameter list .
* Depending on the flags parameter it execute or test a command .
*
* @ param tile The tile to apply the command on ( for the # CommandProc )
* @ param p1 Additional data for the command ( for the # CommandProc )
* @ param p2 Additional data for the command ( for the # CommandProc )
* @ param flags Flags for the command and how to execute the command
2008-12-28 14:37:19 +00:00
* @ param cmd The command - id to execute ( a value of the CMD_ * enums )
2007-09-10 16:21:14 +01:00
* @ see CommandProc
2009-01-08 14:55:28 +00:00
* @ return the cost
2007-09-10 16:21:14 +01:00
*/
2008-12-28 14:37:19 +00:00
CommandCost DoCommand ( TileIndex tile , uint32 p1 , uint32 p2 , uint32 flags , uint32 cmd , const char * text )
2004-08-09 18:04:08 +01:00
{
2007-06-18 11:48:15 +01:00
CommandCost res ;
2004-09-10 20:02:27 +01:00
2005-05-07 11:26:45 +01:00
/* Do not even think about executing out-of-bounds tile-commands */
2008-12-28 14:37:19 +00:00
if ( ! IsValidTile ( tile ) ) return CMD_ERROR ;
2005-05-07 11:26:45 +01:00
2008-12-28 14:37:19 +00:00
CommandProc * proc = _command_proc_table [ cmd ] . proc ;
2004-08-09 18:04:08 +01:00
2005-12-13 21:21:57 +00:00
if ( _docommand_recursive = = 0 ) _error_message = INVALID_STRING_ID ;
2004-08-09 18:04:08 +01:00
_docommand_recursive + + ;
2007-02-23 11:50:43 +00:00
/* only execute the test call if it's toplevel, or we're not execing. */
2008-02-04 22:44:05 +00:00
if ( _docommand_recursive = = 1 | | ! ( flags & DC_EXEC ) ) {
2008-01-09 17:47:05 +00:00
SetTownRatingTestMode ( true ) ;
2008-12-28 14:37:19 +00:00
res = proc ( tile , flags & ~ DC_EXEC , p1 , p2 , text ) ;
2008-01-09 17:47:05 +00:00
SetTownRatingTestMode ( false ) ;
2005-04-14 12:17:36 +01:00
if ( CmdFailed ( res ) ) {
2007-06-18 20:53:50 +01:00
res . SetGlobalErrorMessage ( ) ;
2004-08-09 18:04:08 +01:00
goto error ;
}
2006-06-10 09:37:41 +01:00
if ( _docommand_recursive = = 1 & &
! ( flags & DC_QUERY_COST ) & &
2008-02-09 15:07:31 +00:00
! ( flags & DC_BANKRUPT ) & &
2007-06-18 20:53:50 +01:00
res . GetCost ( ) ! = 0 & &
2008-09-30 21:39:50 +01:00
! CheckCompanyHasMoney ( res ) ) {
2006-06-10 09:37:41 +01:00
goto error ;
2004-08-09 18:04:08 +01:00
}
if ( ! ( flags & DC_EXEC ) ) {
_docommand_recursive - - ;
return res ;
}
}
2005-01-04 17:11:03 +00:00
/* Execute the command here. All cost-relevant functions set the expenses type
2008-01-09 16:55:48 +00:00
* themselves to the cost object at some point */
2008-12-28 14:37:19 +00:00
res = proc ( tile , flags , p1 , p2 , text ) ;
2005-04-14 12:17:36 +01:00
if ( CmdFailed ( res ) ) {
2007-06-18 20:53:50 +01:00
res . SetGlobalErrorMessage ( ) ;
2004-08-09 18:04:08 +01:00
error :
_docommand_recursive - - ;
return CMD_ERROR ;
}
2007-02-23 11:50:43 +00:00
/* if toplevel, subtract the money. */
2008-02-09 15:07:31 +00:00
if ( - - _docommand_recursive = = 0 & & ! ( flags & DC_BANKRUPT ) ) {
2008-09-30 21:39:50 +01:00
SubtractMoneyFromCompany ( res ) ;
2008-12-28 14:37:19 +00:00
/* XXX - Old AI hack which doesn't use DoCommandP; update last build coord of company */
2008-09-30 21:39:50 +01:00
if ( tile ! = 0 & & IsValidCompanyID ( _current_company ) ) {
GetCompany ( _current_company ) - > last_build_coordinate = tile ;
2005-12-18 22:48:45 +00:00
}
2004-08-09 18:04:08 +01:00
}
return res ;
}
2007-09-10 16:21:14 +01:00
/*!
* This functions returns the money which can be used to execute a command .
2008-09-30 21:39:50 +01:00
* This is either the money of the current company or INT64_MAX if there
* is no such a company " at the moment " like the server itself .
2007-09-10 16:21:14 +01:00
*
2008-09-30 21:39:50 +01:00
* @ return The available money of a company or INT64_MAX
2007-09-10 16:21:14 +01:00
*/
2007-06-21 15:32:27 +01:00
Money GetAvailableMoneyForCommand ( )
2004-08-09 18:04:08 +01:00
{
2008-09-30 21:39:50 +01:00
CompanyID company = _current_company ;
if ( ! IsValidCompanyID ( company ) ) return INT64_MAX ;
return GetCompany ( company ) - > money ;
2004-08-09 18:04:08 +01:00
}
2009-01-08 14:55:28 +00:00
/**
* Shortcut for the long DoCommandP when having a container with the data .
* @ param container the container with information .
* @ param my_cmd indicator if the command is from a company or server ( to display error messages for a user )
* @ return true if the command succeeded , else false
*/
bool DoCommandP ( const CommandContainer * container , bool my_cmd )
{
return DoCommandP ( container - > tile , container - > p1 , container - > p2 , container - > cmd , container - > callback , container - > text , my_cmd ) ;
}
2007-09-10 16:21:14 +01:00
/*!
2008-09-30 21:39:50 +01:00
* Toplevel network safe docommand function for the current company . Must not be called recursively .
2007-09-10 16:21:14 +01:00
* The callback is called when the command succeeded or failed . The parameters
* tile , p1 and p2 are from the # CommandProc function . The paramater cmd is the command to execute .
2008-09-30 21:39:50 +01:00
* The parameter my_cmd is used to indicate if the command is from a company or the server .
2007-09-10 16:21:14 +01:00
*
* @ param tile The tile to perform a command on ( see # CommandProc )
* @ param p1 Additional data for the command ( see # CommandProc )
* @ param p2 Additional data for the command ( see # CommandProc )
* @ param cmd The command to execute ( a CMD_ * value )
2008-12-28 14:37:19 +00:00
* @ param callback A callback function to call after the command is finished
* @ param text The text to pass
2008-09-30 21:39:50 +01:00
* @ param my_cmd indicator if the command is from a company or server ( to display error messages for a user )
2007-09-10 16:21:14 +01:00
* @ return true if the command succeeded , else false
*/
2008-12-28 14:37:19 +00:00
bool DoCommandP ( TileIndex tile , uint32 p1 , uint32 p2 , uint32 cmd , CommandCallback * callback , const char * text , bool my_cmd )
2004-08-09 18:04:08 +01:00
{
2009-01-07 13:31:09 +00:00
assert ( _docommand_recursive = = 0 ) ;
2004-08-09 18:04:08 +01:00
2005-05-07 11:26:45 +01:00
/* Do not even think about executing out-of-bounds tile-commands */
2008-12-28 14:37:19 +00:00
if ( ! IsValidTile ( tile ) ) return false ;
2005-05-07 11:26:45 +01:00
2009-01-07 13:31:09 +00:00
CommandCost res , res2 ;
int x = TileX ( tile ) * TILE_SIZE ;
int y = TileY ( tile ) * TILE_SIZE ;
2004-08-09 18:04:08 +01:00
_error_message = INVALID_STRING_ID ;
2009-01-07 13:31:09 +00:00
StringID error_part1 = GB ( cmd , 16 , 16 ) ;
2004-08-09 18:04:08 +01:00
_additional_cash_required = 0 ;
2006-11-10 17:52:51 +00:00
/** Spectator has no rights except for the (dedicated) server which
* is / can be a spectator but as the server it can do anything */
2008-09-30 21:39:50 +01:00
if ( _current_company = = COMPANY_SPECTATOR & & ! _network_server ) {
2007-07-10 21:59:41 +01:00
if ( my_cmd ) ShowErrorMessage ( _error_message , error_part1 , x , y ) ;
2004-08-09 18:04:08 +01:00
return false ;
}
2007-02-23 11:50:43 +00:00
/* get pointer to command handler */
2009-01-07 13:26:48 +00:00
byte cmd_id = cmd & CMD_ID_MASK ;
assert ( cmd_id < lengthof ( _command_proc_table ) ) ;
2009-01-07 13:31:09 +00:00
CommandProc * proc = _command_proc_table [ cmd_id ] . proc ;
2008-12-28 14:37:19 +00:00
if ( proc = = NULL ) return false ;
2004-08-09 18:04:08 +01:00
2009-01-07 13:31:09 +00:00
/* Flags get send to the DoCommand */
uint32 flags = 0 ;
/* Command flags are used internally */
uint cmd_flags = GetCommandFlags ( cmd ) ;
2009-01-07 14:45:07 +00:00
if ( cmd_flags & CMD_NO_WATER ) flags | = DC_NO_WATER ;
2009-01-07 13:31:09 +00:00
if ( cmd_flags & CMD_AUTO ) flags | = DC_AUTO ;
bool notest = ( cmd_flags & CMD_NO_TEST ) ! = 0 ;
2008-01-03 23:54:23 +00:00
2004-08-09 18:04:08 +01:00
_docommand_recursive = 1 ;
2007-02-23 11:50:43 +00:00
/* cost estimation only? */
2007-01-10 14:52:10 +00:00
if ( ! IsGeneratingWorld ( ) & &
_shift_pressed & &
2008-09-30 21:39:50 +01:00
IsLocalCompany ( ) & &
2009-01-07 14:58:43 +00:00
! ( cmd & CMD_NETWORK_COMMAND ) & &
2009-01-07 13:26:48 +00:00
cmd_id ! = CMD_PAUSE ) {
2007-02-23 11:50:43 +00:00
/* estimate the cost. */
2008-01-29 14:02:18 +00:00
SetTownRatingTestMode ( true ) ;
2008-12-28 14:37:19 +00:00
res = proc ( tile , flags , p1 , p2 , text ) ;
2008-01-29 14:02:18 +00:00
SetTownRatingTestMode ( false ) ;
2005-04-14 12:17:36 +01:00
if ( CmdFailed ( res ) ) {
2007-06-18 20:53:50 +01:00
res . SetGlobalErrorMessage ( ) ;
2006-03-12 10:15:36 +00:00
ShowErrorMessage ( _error_message , error_part1 , x , y ) ;
2004-08-09 18:04:08 +01:00
} else {
2007-06-18 20:53:50 +01:00
ShowEstimatedCostOrIncome ( res . GetCost ( ) , x , y ) ;
2004-08-09 18:04:08 +01:00
}
_docommand_recursive = 0 ;
2007-09-22 13:59:43 +01:00
ClearStorageChanges ( false ) ;
2004-08-09 18:04:08 +01:00
return false ;
}
2004-09-10 20:02:27 +01:00
2004-12-04 17:54:56 +00:00
if ( ! ( ( cmd & CMD_NO_TEST_IF_IN_NETWORK ) & & _networking ) ) {
2007-02-23 11:50:43 +00:00
/* first test if the command can be executed. */
2008-01-09 17:47:05 +00:00
SetTownRatingTestMode ( true ) ;
2008-12-28 14:37:19 +00:00
res = proc ( tile , flags , p1 , p2 , text ) ;
2008-01-09 17:47:05 +00:00
SetTownRatingTestMode ( false ) ;
2005-04-14 12:17:36 +01:00
if ( CmdFailed ( res ) ) {
2007-06-18 20:53:50 +01:00
res . SetGlobalErrorMessage ( ) ;
2004-08-09 18:04:08 +01:00
goto show_error ;
}
2007-02-23 11:50:43 +00:00
/* no money? Only check if notest is off */
2008-09-30 21:39:50 +01:00
if ( ! notest & & res . GetCost ( ) ! = 0 & & ! CheckCompanyHasMoney ( res ) ) goto show_error ;
2004-08-09 18:04:08 +01:00
}
2004-12-04 17:54:56 +00:00
# ifdef ENABLE_NETWORK
2005-05-17 21:52:52 +01:00
/** If we are in network, and the command is not from the network
* send it to the command - queue and abort execution
2008-09-30 21:39:50 +01:00
* If we are a dedicated server temporarily switch local company , otherwise
2005-05-17 21:52:52 +01:00
* the other parties won ' t be able to execute our command and will desync .
2006-11-10 17:52:51 +00:00
* We also need to do this if the server ' s company has gone bankrupt
* @ todo Rewrite ( dedicated ) server to something more than a dirty hack !
2005-05-17 21:52:52 +01:00
*/
2004-12-04 17:54:56 +00:00
if ( _networking & & ! ( cmd & CMD_NETWORK_COMMAND ) ) {
2008-10-07 21:57:41 +01:00
CompanyID bck = _local_company ;
if ( _network_dedicated | | ( _network_server & & bck = = COMPANY_SPECTATOR ) ) _local_company = COMPANY_FIRST ;
2009-01-07 15:27:19 +00:00
NetworkSend_Command ( tile , p1 , p2 , cmd & ~ CMD_FLAGS_MASK , callback , text ) ;
2008-10-07 21:57:41 +01:00
if ( _network_dedicated | | ( _network_server & & bck = = COMPANY_SPECTATOR ) ) _local_company = bck ;
2004-12-04 17:54:56 +00:00
_docommand_recursive = 0 ;
2007-09-22 13:59:43 +01:00
ClearStorageChanges ( false ) ;
2004-12-04 17:54:56 +00:00
return true ;
2004-08-09 18:04:08 +01:00
}
2004-12-04 17:54:56 +00:00
# endif /* ENABLE_NETWORK */
2008-12-29 21:50:25 +00:00
DEBUG ( desync , 1 , " cmd: %08x; %08x; %1x; %06x; %08x; %08x; %04x; %s \n " , _date , _date_fract , ( int ) _current_company , tile , p1 , p2 , cmd & ~ CMD_NETWORK_COMMAND , text ) ;
2004-08-09 18:04:08 +01:00
2008-09-30 21:39:50 +01:00
/* update last build coordinate of company. */
if ( tile ! = 0 & & IsValidCompanyID ( _current_company ) ) {
GetCompany ( _current_company ) - > last_build_coordinate = tile ;
2006-06-10 09:37:41 +01:00
}
2004-08-09 18:04:08 +01:00
2005-01-04 17:11:03 +00:00
/* Actually try and execute the command. If no cost-type is given
* use the construction one */
2008-12-28 14:37:19 +00:00
res2 = proc ( tile , flags | DC_EXEC , p1 , p2 , text ) ;
2004-09-10 20:02:27 +01:00
2007-02-23 11:50:43 +00:00
/* If notest is on, it means the result of the test can be different than
* the real command . . so ignore the test */
2004-12-14 18:13:02 +00:00
if ( ! notest & & ! ( ( cmd & CMD_NO_TEST_IF_IN_NETWORK ) & & _networking ) ) {
2007-06-18 20:53:50 +01:00
assert ( res . GetCost ( ) = = res2 . GetCost ( ) & & CmdFailed ( res ) = = CmdFailed ( res2 ) ) ; // sanity check
2004-08-09 18:04:08 +01:00
} else {
2005-04-15 22:37:56 +01:00
if ( CmdFailed ( res2 ) ) {
2007-06-18 20:53:50 +01:00
res . SetGlobalErrorMessage ( ) ;
2004-08-09 18:04:08 +01:00
goto show_error ;
}
}
2008-09-30 21:39:50 +01:00
SubtractMoneyFromCompany ( res2 ) ;
2004-08-09 18:04:08 +01:00
2008-01-16 01:18:15 +00:00
/* update signals if needed */
UpdateSignalsInBuffer ( ) ;
2008-09-30 21:39:50 +01:00
if ( IsLocalCompany ( ) & & _game_mode ! = GM_EDITOR ) {
2007-08-31 18:43:29 +01:00
if ( res2 . GetCost ( ) ! = 0 & & tile ! = 0 ) ShowCostOrIncomeAnimation ( x , y , GetSlopeZ ( x , y ) , res2 . GetCost ( ) ) ;
2007-06-21 15:32:27 +01:00
if ( _additional_cash_required ! = 0 ) {
2007-06-21 18:25:17 +01:00
SetDParam ( 0 , _additional_cash_required ) ;
2007-07-10 21:59:41 +01:00
if ( my_cmd ) ShowErrorMessage ( STR_0003_NOT_ENOUGH_CASH_REQUIRES , error_part1 , x , y ) ;
2007-06-18 20:53:50 +01:00
if ( res2 . GetCost ( ) = = 0 ) goto callb_err ;
2004-08-09 18:04:08 +01:00
}
}
_docommand_recursive = 0 ;
2004-09-10 20:02:27 +01:00
2004-08-09 18:04:08 +01:00
if ( callback ) callback ( true , tile , p1 , p2 ) ;
2007-09-22 13:59:43 +01:00
ClearStorageChanges ( true ) ;
2004-08-09 18:04:08 +01:00
return true ;
show_error :
2007-02-23 11:50:43 +00:00
/* show error message if the command fails? */
2008-09-30 21:39:50 +01:00
if ( IsLocalCompany ( ) & & error_part1 ! = 0 & & my_cmd ) {
2007-04-18 23:10:36 +01:00
ShowErrorMessage ( _error_message , error_part1 , x , y ) ;
2006-03-12 10:15:36 +00:00
}
2004-08-09 18:04:08 +01:00
callb_err :
_docommand_recursive = 0 ;
2004-09-10 20:02:27 +01:00
2004-08-09 18:04:08 +01:00
if ( callback ) callback ( false , tile , p1 , p2 ) ;
2007-09-22 13:59:43 +01:00
ClearStorageChanges ( false ) ;
2004-08-09 18:04:08 +01:00
return false ;
}
2008-04-07 21:02:36 +01:00
CommandCost CommandCost : : AddCost ( CommandCost ret )
{
this - > AddCost ( ret . cost ) ;
if ( this - > success & & ! ret . success ) {
this - > message = ret . message ;
this - > success = false ;
}
return * this ;
}