2005-07-24 15:12:37 +01:00
/* $Id$ */
2009-08-21 21:21:05 +01:00
/*
* This file is part of OpenTTD .
* OpenTTD is free software ; you can redistribute it and / or modify it under the terms of the GNU General Public License as published by the Free Software Foundation , version 2.
* OpenTTD is distributed in the hope that it will be useful , but WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
* See the GNU General Public License for more details . You should have received a copy of the GNU General Public License along with OpenTTD . If not , see < http : //www.gnu.org/licenses/>.
*/
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"
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"
(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"
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRailroadTrack ;
CommandProc CmdRemoveRailroadTrack ;
CommandProc CmdBuildSingleRail ;
CommandProc CmdRemoveSingleRail ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdLandscapeClear ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildBridge ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRailStation ;
CommandProc CmdRemoveFromRailStation ;
CommandProc CmdConvertRail ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildSingleSignal ;
CommandProc CmdRemoveSingleSignal ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdTerraformLand ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdPurchaseLandArea ;
CommandProc CmdSellLandArea ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildTunnel ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildTrainDepot ;
CommandProc CmdBuildRailWaypoint ;
CommandProc CmdRenameWaypoint ;
CommandProc CmdRemoveFromRailWaypoint ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRoadStop ;
CommandProc CmdRemoveRoadStop ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildLongRoad ;
CommandProc CmdRemoveLongRoad ;
CommandProc CmdBuildRoad ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRoadDepot ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildAirport ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildDock ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildShipDepot ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildBuoy ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdPlantTree ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRailVehicle ;
CommandProc CmdMoveRailVehicle ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdSellRailWagon ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdSendTrainToDepot ;
CommandProc CmdForceTrainProceed ;
CommandProc CmdReverseTrainDirection ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdModifyOrder ;
CommandProc CmdSkipToOrder ;
CommandProc CmdDeleteOrder ;
CommandProc CmdInsertOrder ;
CommandProc CmdChangeServiceInt ;
CommandProc CmdRestoreOrderIndex ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildIndustry ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildCompanyHQ ;
CommandProc CmdSetCompanyManagerFace ;
CommandProc CmdSetCompanyColour ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdIncreaseLoan ;
CommandProc CmdDecreaseLoan ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdWantEnginePreview ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdRenameVehicle ;
CommandProc CmdRenameEngine ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdRenameCompany ;
CommandProc CmdRenamePresident ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdRenameStation ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdSellAircraft ;
CommandProc CmdBuildAircraft ;
CommandProc CmdSendAircraftToHangar ;
CommandProc CmdRefitAircraft ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdPlaceSign ;
CommandProc CmdRenameSign ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildRoadVeh ;
CommandProc CmdSellRoadVeh ;
CommandProc CmdSendRoadVehToDepot ;
CommandProc CmdTurnRoadVeh ;
CommandProc CmdRefitRoadVeh ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdPause ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuyShareInCompany ;
CommandProc CmdSellShareInCompany ;
CommandProc CmdBuyCompany ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdFoundTown ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdRenameTown ;
CommandProc CmdDoTownAction ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdChangeSetting ;
CommandProc CmdChangeCompanySetting ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdSellShip ;
CommandProc CmdBuildShip ;
CommandProc CmdSendShipToDepot ;
CommandProc CmdRefitShip ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdOrderRefit ;
CommandProc CmdCloneOrder ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdClearArea ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdGiveMoney ;
CommandProc CmdMoneyCheat ;
CommandProc CmdBuildCanal ;
CommandProc CmdBuildLock ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdCompanyCtrl ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdLevelLand ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdRefitRailVehicle ;
2004-08-09 18:04:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdBuildSignalTrack ;
CommandProc CmdRemoveSignalTrack ;
2004-08-15 21:23:42 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdSetAutoReplace ;
2004-12-27 18:18:44 +00:00
2010-01-11 22:46:00 +00:00
CommandProc CmdCloneVehicle ;
CommandProc CmdStartStopVehicle ;
CommandProc CmdMassStartStopVehicle ;
CommandProc CmdAutoreplaceVehicle ;
CommandProc CmdDepotSellAllVehicles ;
CommandProc CmdDepotMassAutoReplace ;
2005-07-31 14:08:08 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdCreateGroup ;
CommandProc CmdRenameGroup ;
CommandProc CmdDeleteGroup ;
CommandProc CmdAddVehicleGroup ;
CommandProc CmdAddSharedVehicleGroup ;
CommandProc CmdRemoveAllVehiclesGroup ;
CommandProc CmdSetGroupReplaceProtection ;
2007-05-22 20:48:11 +01:00
2010-01-11 22:46:00 +00:00
CommandProc CmdMoveOrder ;
CommandProc CmdChangeTimetable ;
CommandProc CmdSetVehicleOnTime ;
CommandProc CmdAutofillTimetable ;
CommandProc CmdSetTimetableStart ;
2007-09-10 16:21:14 +01:00
/**
* The master command table
*
* This table contains all possible CommandProc functions with
2010-03-14 12:39:24 +00:00
* the flags which belongs to it . The indices are the same
2007-09-10 16:21:14 +01:00
* as the value from the CMD_ * enums .
*/
2005-05-14 20:25:18 +01:00
static const Command _command_proc_table [ ] = {
2009-03-15 00:32:18 +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
2009-07-29 23:32:20 +01:00
{ CmdBuildRailStation , CMD_NO_WATER | CMD_AUTO } , // CMD_BUILD_RAIL_STATION
2009-03-15 00:32:18 +00:00
{ CmdBuildTrainDepot , CMD_NO_WATER | CMD_AUTO } , // CMD_BUILD_TRAIN_DEPOT
{ CmdBuildSingleSignal , CMD_AUTO } , // CMD_BUILD_SIGNALS
{ CmdRemoveSingleSignal , CMD_AUTO } , // CMD_REMOVE_SIGNALS
{ CmdTerraformLand , CMD_ALL_TILES | 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
2009-07-29 23:32:20 +01:00
{ CmdRemoveFromRailStation , 0 } , // CMD_REMOVE_FROM_RAIL_STATION
2009-03-15 00:32:18 +00:00
{ CmdConvertRail , 0 } , // CMD_CONVERT_RAILD
2009-07-29 23:32:20 +01:00
{ CmdBuildRailWaypoint , 0 } , // CMD_BUILD_RAIL_WAYPOINT
2009-03-15 00:32:18 +00:00
{ CmdRenameWaypoint , 0 } , // CMD_RENAME_WAYPOINT
2009-07-29 23:32:20 +01:00
{ CmdRemoveFromRailWaypoint , 0 } , // CMD_REMOVE_FROM_RAIL_WAYPOINT
2009-03-15 00:32:18 +00:00
{ 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.
2010-01-31 20:28:36 +00:00
{ CmdBuildRoad , CMD_NO_WATER | CMD_AUTO } , // CMD_BUILD_ROAD
2009-03-15 00:32:18 +00:00
{ 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
{ CmdSetCompanyColour , 0 } , // CMD_SET_COMPANY_COLOUR
{ 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
2009-11-24 21:18:11 +00:00
{ CmdFoundTown , CMD_NO_TEST } , // CMD_FOUND_TOWN; founding random town can fail only in exec run
2009-03-15 00:32:18 +00:00
{ CmdRenameTown , CMD_SERVER } , // CMD_RENAME_TOWN
{ CmdDoTownAction , 0 } , // CMD_DO_TOWN_ACTION
{ 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 , CMD_SPECTATOR } , // CMD_COMPANY_CTRL
{ CmdLevelLand , CMD_ALL_TILES | 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
{ CmdChangeSetting , CMD_SERVER } , // CMD_CHANGE_SETTING
2009-05-26 12:40:14 +01:00
{ CmdChangeCompanySetting , 0 } , // CMD_CHANGE_COMPANY_SETTING
2009-03-15 00:32:18 +00:00
{ 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
2009-11-25 23:37:15 +00:00
{ CmdSetTimetableStart , 0 } , // CMD_SET_TIMETABLE_START
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
*/
2009-02-09 21:20:05 +00:00
CommandCost DoCommand ( const CommandContainer * container , DoCommandFlag flags )
2009-01-08 14:55:28 +00:00
{
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 )
2009-09-18 15:23:58 +01:00
* @ param text The text to pass
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
*/
2009-02-09 21:20:05 +00:00
CommandCost DoCommand ( TileIndex tile , uint32 p1 , uint32 p2 , DoCommandFlag 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 */
2009-01-21 02:31:55 +00:00
if ( tile ! = 0 & & ( tile > = MapSize ( ) | | ( ! IsValidTile ( tile ) & & ( flags & DC_ALL_TILES ) = = 0 ) ) ) return CMD_ERROR ;
2005-05-07 11:26:45 +01:00
2009-07-23 00:39:35 +01:00
/* Chop of any CMD_MSG or other flags; we don't need those here */
CommandProc * proc = _command_proc_table [ cmd & CMD_ID_MASK ] . proc ;
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 ) ;
2010-01-18 22:57:21 +00:00
if ( res . Failed ( ) ) {
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 ) & &
2010-03-14 12:58:51 +00:00
! CheckCompanyHasMoney ( res ) ) { // CheckCompanyHasMoney() modifies 'res' to an error if it fails.
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 ) ;
2010-01-18 22:57:21 +00:00
if ( res . Failed ( ) ) {
2004-08-09 18:04:08 +01:00
error :
_docommand_recursive - - ;
2010-03-14 12:58:51 +00:00
return res ;
2004-08-09 18:04:08 +01:00
}
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 ) ;
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 ;
2009-05-17 02:00:56 +01:00
if ( ! Company : : IsValidID ( company ) ) return INT64_MAX ;
2009-05-17 00:34:14 +01:00
return Company : : Get ( 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
2010-03-14 12:39:24 +00:00
* \ a tile , \ a p1 , and \ a p2 are from the # CommandProc function . The parameter \ a cmd is the command to execute .
* The parameter \ a 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 )
2010-03-14 12:39:24 +00:00
* @ return \ c true if the command succeeded , else \ c false .
2007-09-10 16:21:14 +01:00
*/
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
{
2010-01-11 20:39:38 +00:00
/* Cost estimation is generally only done when the
* local user presses shift while doing somthing .
* However , in case of incoming network commands ,
* map generation of the pause button we do want
* to execute . */
bool estimate_only = _shift_pressed & & IsLocalCompany ( ) & &
! IsGeneratingWorld ( ) & &
! ( cmd & CMD_NETWORK_COMMAND ) & &
( cmd & CMD_ID_MASK ) ! = CMD_PAUSE ;
2004-08-09 18:04:08 +01:00
2010-01-11 20:39:38 +00:00
/* We're only sending the command, so don't do
* fancy things for ' success ' . */
bool only_sending = _networking & & ! ( cmd & CMD_NETWORK_COMMAND ) ;
2009-01-07 13:31:09 +00:00
2010-01-11 20:39:38 +00:00
/* Where to show the message? */
2009-01-07 13:31:09 +00:00
int x = TileX ( tile ) * TILE_SIZE ;
int y = TileY ( tile ) * TILE_SIZE ;
2004-08-09 18:04:08 +01:00
2010-01-11 20:39:38 +00:00
CommandCost res = DoCommandPInternal ( tile , p1 , p2 , cmd , callback , text , my_cmd , estimate_only ) ;
2010-01-18 22:57:21 +00:00
if ( res . Failed ( ) ) {
2010-01-11 20:39:38 +00:00
/* Only show the error when it's for us. */
StringID error_part1 = GB ( cmd , 16 , 16 ) ;
if ( estimate_only | | ( IsLocalCompany ( ) & & error_part1 ! = 0 & & my_cmd ) ) {
2010-03-14 14:36:37 +00:00
ShowErrorMessage ( error_part1 , res . GetErrorMessage ( ) , WL_INFO , x , y ) ;
2010-01-11 20:39:38 +00:00
}
} else if ( estimate_only ) {
ShowEstimatedCostOrIncome ( res . GetCost ( ) , x , y ) ;
} else if ( ! only_sending & & res . GetCost ( ) ! = 0 & & tile ! = 0 & & IsLocalCompany ( ) & & _game_mode ! = GM_EDITOR ) {
/* Only show the cost animation when we did actually
* execute the command , i . e . we ' re not sending it to
* the server , when it has cost the local company
* something . Furthermore in the editor there is no
* concept of cost , so don ' t show it there either . */
ShowCostOrIncomeAnimation ( x , y , GetSlopeZ ( x , y ) , res . GetCost ( ) ) ;
}
if ( ! estimate_only & & ! only_sending & & callback ! = NULL ) {
callback ( res , tile , p1 , p2 ) ;
}
2010-01-18 22:57:21 +00:00
return res . Succeeded ( ) ;
2010-01-11 20:39:38 +00:00
}
/**
* Helper to deduplicate the code for returning .
* @ param cmd the command cost to return .
* @ param clear whether to keep the storage changes or not .
*/
# define return_dcpi(cmd, clear) { _docommand_recursive = 0; ClearStorageChanges(clear); return cmd; }
/*!
* Helper function for the toplevel network safe docommand function for the current company .
*
* @ 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 )
* @ param callback A callback function to call after the command is finished
* @ param text The text to pass
* @ param my_cmd indicator if the command is from a company or server ( to display error messages for a user )
* @ param estimate_only whether to give only the estimate or also execute the command
* @ return the command cost of this function .
*/
CommandCost DoCommandPInternal ( TileIndex tile , uint32 p1 , uint32 p2 , uint32 cmd , CommandCallback * callback , const char * text , bool my_cmd , bool estimate_only )
{
/* Prevent recursion; it gives a mess over the network */
assert ( _docommand_recursive = = 0 ) ;
_docommand_recursive = 1 ;
/* Reset the state. */
2004-08-09 18:04:08 +01:00
_additional_cash_required = 0 ;
2010-01-11 20:39:38 +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 ;
2010-01-11 20:39:38 +00:00
/* Shouldn't happen, but you never know when someone adds
* NULLs to the _command_proc_table . */
assert ( proc ! = NULL ) ;
2004-08-09 18:04:08 +01:00
2009-01-07 13:31:09 +00:00
/* Command flags are used internally */
uint cmd_flags = GetCommandFlags ( cmd ) ;
2009-01-12 15:27:39 +00:00
/* Flags get send to the DoCommand */
2009-02-09 21:20:05 +00:00
DoCommandFlag flags = CommandFlagsToDCFlags ( cmd_flags ) ;
2009-01-07 13:31:09 +00:00
2009-01-21 02:31:55 +00:00
/* Do not even think about executing out-of-bounds tile-commands */
2010-01-11 20:39:38 +00:00
if ( tile ! = 0 & & ( tile > = MapSize ( ) | | ( ! IsValidTile ( tile ) & & ( cmd_flags & CMD_ALL_TILES ) = = 0 ) ) ) return_dcpi ( CMD_ERROR , false ) ;
2009-01-21 02:31:55 +00:00
2009-05-26 22:24:11 +01:00
/* Always execute server and spectator commands as spectator */
if ( cmd_flags & ( CMD_SPECTATOR | CMD_SERVER ) ) _current_company = COMPANY_SPECTATOR ;
2009-05-26 22:55:49 +01:00
CompanyID old_company = _current_company ;
2009-05-26 20:23:02 +01:00
/* If the company isn't valid it may only do server command or start a new company!
* The server will ditch any server commands a client sends to it , so effectively
* this guards the server from executing functions for an invalid company . */
2009-06-02 13:57:47 +01:00
if ( _game_mode = = GM_NORMAL & & ( cmd_flags & ( CMD_SPECTATOR | CMD_SERVER ) ) = = 0 & & ! Company : : IsValidID ( _current_company ) ) {
2010-01-11 20:39:38 +00:00
return_dcpi ( CMD_ERROR , false ) ;
2009-05-26 20:23:02 +01:00
}
2009-02-04 16:57:40 +00:00
2010-01-11 20:39:38 +00:00
bool test_and_exec_can_differ = ( cmd_flags & CMD_NO_TEST ) ! = 0 ;
bool skip_test = _networking & & ( cmd & CMD_NO_TEST_IF_IN_NETWORK ) ! = 0 ;
/* Do we need to do a test run?
* Basically we need to always do this , except when
* the no - test - in - network flag is giving and we ' re
* in a network game ( e . g . restoring orders would
* fail this test because the first order does not
* exist yet when inserting the second , giving that
* a wrong insert location and ignoring the command
* and thus breaking restoring ) . However , when we
* just want to do cost estimation we don ' t care
* because it ' s only done once anyway . */
CommandCost res ;
if ( estimate_only | | ! skip_test ) {
/* Test the command. */
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 ) ;
2004-08-09 18:04:08 +01:00
2010-01-11 20:39:38 +00:00
/* Make sure we're not messing things up here. */
2009-02-07 18:09:30 +00:00
assert ( cmd_id = = CMD_COMPANY_CTRL | | old_company = = _current_company ) ;
2010-01-11 20:39:38 +00:00
/* If the command fails, we're doing an estimate
* or the player does not have enough money
* ( unless it ' s a command where the test and
* execution phase might return different costs )
* we bail out here . */
2010-01-18 22:57:21 +00:00
if ( res . Failed ( ) | | estimate_only | |
2010-01-11 20:39:38 +00:00
( ! test_and_exec_can_differ & & ! CheckCompanyHasMoney ( res ) ) ) {
return_dcpi ( res , false ) ;
2010-01-11 20:21:56 +00:00
}
2004-08-09 18:04:08 +01:00
}
2004-12-04 17:54:56 +00:00
# ifdef ENABLE_NETWORK
2009-05-26 20:23:02 +01:00
/*
* If we are in network , and the command is not from the network
2005-05-17 21:52:52 +01:00
* send it to the command - queue and abort execution
*/
2004-12-04 17:54:56 +00:00
if ( _networking & & ! ( cmd & CMD_NETWORK_COMMAND ) ) {
2010-01-11 20:32:32 +00:00
NetworkSend_Command ( tile , p1 , p2 , cmd & ~ CMD_FLAGS_MASK , callback , text , _current_company ) ;
2010-01-11 20:39:38 +00:00
/* Don't return anything special here; no error, no costs.
* This way it ' s not handled by DoCommand and only the
* actual execution of the command causes messages . Also
* reset the storages as we ' ve not executed the command . */
return_dcpi ( CommandCost ( ) , false ) ;
2004-08-09 18:04:08 +01:00
}
2004-12-04 17:54:56 +00:00
# endif /* ENABLE_NETWORK */
2010-04-11 10:54:44 +01:00
DEBUG ( desync , 1 , " cmd: %08x; %02x; %02x; %06x; %08x; %08x; %08x; \" %s \" " , _date , _date_fract , ( int ) _current_company , tile , p1 , p2 , cmd & ~ CMD_NETWORK_COMMAND , text ) ;
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 */
2010-01-11 20:39:38 +00:00
CommandCost res2 = proc ( tile , flags | DC_EXEC , p1 , p2 , text ) ;
2004-09-10 20:02:27 +01:00
2010-01-11 20:39:38 +00:00
/* Make sure nothing bad happened, like changing the current company. */
2009-02-07 18:09:30 +00:00
assert ( cmd_id = = CMD_COMPANY_CTRL | | old_company = = _current_company ) ;
2010-01-11 20:39:38 +00:00
/* If the test and execution can differ, or we skipped the test
* we have to check the return of the command . Otherwise we can
* check whether the test and execution have yielded the same
* result , i . e . cost and error state are the same . */
if ( ! test_and_exec_can_differ & & ! skip_test ) {
2010-01-18 22:57:21 +00:00
assert ( res . GetCost ( ) = = res2 . GetCost ( ) & & res . Failed ( ) = = res2 . Failed ( ) ) ; // sanity check
} else if ( res2 . Failed ( ) ) {
2010-01-11 20:39:38 +00:00
return_dcpi ( res2 , false ) ;
2004-08-09 18:04:08 +01:00
}
2010-01-11 20:39:38 +00:00
/* If we're needing more money and we haven't done
* anything yet , ask for the money ! */
if ( _additional_cash_required ! = 0 & & res2 . GetCost ( ) = = 0 ) {
SetDParam ( 0 , _additional_cash_required ) ;
return_dcpi ( CommandCost ( STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY ) , false ) ;
2004-08-09 18:04:08 +01:00
}
2010-01-11 20:39:38 +00:00
/* update last build coordinate of company. */
if ( tile ! = 0 ) {
Company * c = Company : : GetIfValid ( _current_company ) ;
if ( c ! = NULL ) c - > last_build_coordinate = tile ;
2006-03-12 10:15:36 +00:00
}
2004-08-09 18:04:08 +01:00
2010-01-11 20:39:38 +00:00
SubtractMoneyFromCompany ( res2 ) ;
/* update signals if needed */
UpdateSignalsInBuffer ( ) ;
2004-09-10 20:02:27 +01:00
2010-01-11 20:39:38 +00:00
return_dcpi ( res2 , true ) ;
2004-08-09 18:04:08 +01:00
}
2010-01-11 20:39:38 +00:00
# undef return_dcpi
2008-04-07 21:02:36 +01:00
2010-02-14 15:30:08 +00:00
/**
* Adds the cost of the given command return value to this cost .
* Also takes a possible error message when it is set .
* @ param ret The command to add the cost of .
*/
2010-02-14 15:44:21 +00:00
void CommandCost : : AddCost ( const CommandCost & ret )
2008-04-07 21:02:36 +01:00
{
this - > AddCost ( ret . cost ) ;
if ( this - > success & & ! ret . success ) {
this - > message = ret . message ;
this - > success = false ;
}
}