2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file misc_cmd.cpp Some misc functions that are better fitted in other files, but never got moved there... */
11 #include "command_func.h"
12 #include "economy_func.h"
13 #include "window_func.h"
14 #include "textbuf_gui.h"
15 #include "network/network.h"
16 #include "network/network_func.h"
17 #include "strings_func.h"
18 #include "company_func.h"
19 #include "company_gui.h"
20 #include "company_base.h"
22 #include "texteff.hpp"
23 #include "core/backup_type.hpp"
26 #include "table/strings.h"
28 #include "safeguards.h"
31 * Increase the loan of your company.
32 * @param flags operation to perform
33 * @param cmd when LoanCommand::Interval: loans LOAN_INTERVAL,
34 * when LoanCommand::Max: loans the maximum loan permitting money (press CTRL),
35 * when LoanCommand::Amount: loans the amount specified in \c amount
36 * @param amount amount to increase the loan with, multitude of LOAN_INTERVAL. Only used when cmd == LoanCommand::Amount.
37 * @return the cost of this operation or an error
39 CommandCost
CmdIncreaseLoan(DoCommandFlag flags
, LoanCommand cmd
, Money amount
)
41 Company
*c
= Company::Get(_current_company
);
42 Money max_loan
= c
->GetMaxLoan();
43 if (c
->current_loan
>= max_loan
) {
44 SetDParam(0, max_loan
);
45 return_cmd_error(STR_ERROR_MAXIMUM_PERMITTED_LOAN
);
50 default: return CMD_ERROR
; // Invalid method
51 case LoanCommand::Interval
: // Take some extra loan
54 case LoanCommand::Max
: // Take a loan as big as possible
55 loan
= max_loan
- c
->current_loan
;
57 case LoanCommand::Amount
: // Take the given amount of loan
59 if (loan
< LOAN_INTERVAL
|| c
->current_loan
+ loan
> max_loan
|| loan
% LOAN_INTERVAL
!= 0) return CMD_ERROR
;
63 /* In case adding the loan triggers the overflow protection of Money,
64 * we would essentially be losing money as taking and repaying the loan
65 * immediately would not get us back to the same bank balance anymore. */
66 if (c
->money
> Money::max() - loan
) return CMD_ERROR
;
68 if (flags
& DC_EXEC
) {
70 c
->current_loan
+= loan
;
71 InvalidateCompanyWindows(c
);
74 return CommandCost(EXPENSES_OTHER
);
78 * Decrease the loan of your company.
79 * @param flags operation to perform
80 * @param cmd when LoanCommand::Interval: pays back LOAN_INTERVAL,
81 * when LoanCommand::Max: pays back the maximum loan permitting money (press CTRL),
82 * when LoanCommand::Amount: pays back the amount specified in \c amount
83 * @param amount amount to decrease the loan with, multitude of LOAN_INTERVAL. Only used when cmd == LoanCommand::Amount.
84 * @return the cost of this operation or an error
86 CommandCost
CmdDecreaseLoan(DoCommandFlag flags
, LoanCommand cmd
, Money amount
)
88 Company
*c
= Company::Get(_current_company
);
90 if (c
->current_loan
== 0) return_cmd_error(STR_ERROR_LOAN_ALREADY_REPAYED
);
94 default: return CMD_ERROR
; // Invalid method
95 case LoanCommand::Interval
: // Pay back one step
96 loan
= std::min(c
->current_loan
, (Money
)LOAN_INTERVAL
);
98 case LoanCommand::Max
: // Pay back as much as possible
99 loan
= std::max(std::min(c
->current_loan
, GetAvailableMoneyForCommand()), (Money
)LOAN_INTERVAL
);
100 loan
-= loan
% LOAN_INTERVAL
;
102 case LoanCommand::Amount
: // Repay the given amount of loan
104 if (loan
% LOAN_INTERVAL
!= 0 || loan
< LOAN_INTERVAL
|| loan
> c
->current_loan
) return CMD_ERROR
; // Invalid amount to loan
108 if (GetAvailableMoneyForCommand() < loan
) {
110 return_cmd_error(STR_ERROR_CURRENCY_REQUIRED
);
113 if (flags
& DC_EXEC
) {
115 c
->current_loan
-= loan
;
116 InvalidateCompanyWindows(c
);
118 return CommandCost();
122 * Sets the max loan amount of your company. Does not respect the global loan setting.
123 * @param company the company ID.
124 * @param amount the new max loan amount, will be rounded down to the multitude of LOAN_INTERVAL. If set to COMPANY_MAX_LOAN_DEFAULT reset the max loan to default(global) value.
125 * @return zero cost or an error
127 CommandCost
CmdSetCompanyMaxLoan(DoCommandFlag flags
, CompanyID company
, Money amount
)
129 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
130 if (amount
!= COMPANY_MAX_LOAN_DEFAULT
) {
131 if (amount
< 0 || amount
> (Money
)MAX_LOAN_LIMIT
) return CMD_ERROR
;
134 Company
*c
= Company::GetIfValid(company
);
135 if (c
== nullptr) return CMD_ERROR
;
137 if (flags
& DC_EXEC
) {
138 /* Round the amount down to a multiple of LOAN_INTERVAL. */
139 if (amount
!= COMPANY_MAX_LOAN_DEFAULT
) amount
-= (int64_t)amount
% LOAN_INTERVAL
;
141 c
->max_loan
= amount
;
142 InvalidateCompanyWindows(c
);
144 return CommandCost();
148 * In case of an unsafe unpause, we want the
149 * user to confirm that it might crash.
150 * @param confirmed whether the user confirmed their action
152 static void AskUnsafeUnpauseCallback(Window
*, bool confirmed
)
155 Command
<CMD_PAUSE
>::Post(PM_PAUSED_ERROR
, false);
160 * Pause/Unpause the game (server-only).
161 * Set or unset a bit in the pause mode. If pause mode is zero the game is
162 * unpaused. A bitset is used instead of a boolean value/counter to have
163 * more control over the game when saving/loading, etc.
164 * @param flags operation to perform
165 * @param mode the pause mode to change
166 * @param pause true pauses, false unpauses this mode
167 * @return the cost of this operation or an error
169 CommandCost
CmdPause(DoCommandFlag flags
, PauseMode mode
, bool pause
)
172 case PM_PAUSED_SAVELOAD
:
173 case PM_PAUSED_ERROR
:
174 case PM_PAUSED_NORMAL
:
175 case PM_PAUSED_GAME_SCRIPT
:
176 case PM_PAUSED_LINK_GRAPH
:
180 case PM_PAUSED_ACTIVE_CLIENTS
:
181 if (!_networking
) return CMD_ERROR
;
184 default: return CMD_ERROR
;
186 if (flags
& DC_EXEC
) {
187 if (mode
== PM_PAUSED_NORMAL
&& _pause_mode
& PM_PAUSED_ERROR
) {
189 STR_NEWGRF_UNPAUSE_WARNING_TITLE
,
190 STR_NEWGRF_UNPAUSE_WARNING
,
192 AskUnsafeUnpauseCallback
195 PauseMode prev_mode
= _pause_mode
;
200 _pause_mode
&= ~mode
;
202 /* If the only remaining reason to be paused is that we saw a command during pause, unpause. */
203 if (_pause_mode
== PM_COMMAND_DURING_PAUSE
) {
204 _pause_mode
= PM_UNPAUSED
;
208 NetworkHandlePauseChange(prev_mode
, mode
);
211 SetWindowDirty(WC_STATUS_BAR
, 0);
212 SetWindowDirty(WC_MAIN_TOOLBAR
, 0);
214 return CommandCost();
218 * Change the financial flow of your company.
219 * @param amount the amount of money to receive (if positive), or spend (if negative)
220 * @return the cost of this operation or an error
222 CommandCost
CmdMoneyCheat(DoCommandFlag
, Money amount
)
224 return CommandCost(EXPENSES_OTHER
, -amount
);
228 * Change the bank bank balance of a company by inserting or removing money without affecting the loan.
229 * @param flags operation to perform
230 * @param tile tile to show text effect on (if not 0)
231 * @param delta the amount of money to receive (if positive), or spend (if negative)
232 * @param company the company ID.
233 * @param expenses_type the expenses type which should register the cost/income @see ExpensesType.
234 * @return zero cost or an error
236 CommandCost
CmdChangeBankBalance(DoCommandFlag flags
, TileIndex tile
, Money delta
, CompanyID company
, ExpensesType expenses_type
)
238 if (!Company::IsValidID(company
)) return CMD_ERROR
;
239 if (expenses_type
>= EXPENSES_END
) return CMD_ERROR
;
240 if (_current_company
!= OWNER_DEITY
) return CMD_ERROR
;
242 if (flags
& DC_EXEC
) {
243 /* Change company bank balance of company. */
244 Backup
<CompanyID
> cur_company(_current_company
, company
, FILE_LINE
);
245 SubtractMoneyFromCompany(CommandCost(expenses_type
, -delta
));
246 cur_company
.Restore();
249 ShowCostOrIncomeAnimation(TileX(tile
) * TILE_SIZE
, TileY(tile
) * TILE_SIZE
, GetTilePixelZ(tile
), -delta
);
253 /* This command doesn't cost anything for deity. */
254 CommandCost
zero_cost(expenses_type
, (Money
)0);