tron@2186: /* $Id$ */ tron@2186: truelight@0: #include "stdafx.h" Darkvater@1891: #include "openttd.h" tron@2163: #include "functions.h" tron@1317: #include "string.h" tron@507: #include "table/strings.h" truelight@0: #include "command.h" truelight@0: #include "player.h" truelight@0: #include "gfx.h" truelight@0: #include "window.h" Darkvater@1500: #include "gui.h" truelight@0: #include "economy.h" truelight@543: #include "network.h" tron@2159: #include "variables.h" peter1138@4603: #include "livery.h" truelight@0: Darkvater@1786: /** Change the player's face. tron@3491: * @param tile unused Darkvater@1786: * @param p1 unused Darkvater@1786: * @param p2 face bitmasked truelight@0: */ tron@3491: int32 CmdSetPlayerFace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { truelight@0: if (flags & DC_EXEC) { tron@1767: GetPlayer(_current_player)->face = p2; truelight@0: MarkWholeScreenDirty(); truelight@0: } truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1786: /** Change the player's company-colour tron@3491: * @param tile unused peter1138@4603: * @param p1 bitstuffed: peter1138@4603: * p1 bits 0-7 scheme to set peter1138@4603: * p1 bits 8-9 set in use state or first/second colour Darkvater@1786: * @param p2 new colour for vehicles, property, etc. truelight@0: */ tron@3491: int32 CmdSetPlayerColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { Darkvater@1786: Player *p, *pp; tron@2150: byte colour; peter1138@4603: LiveryScheme scheme = GB(p1, 0, 8); peter1138@4603: byte state = GB(p1, 8, 2); Darkvater@1878: Darkvater@1878: if (p2 >= 16) return CMD_ERROR; // max 16 colours tron@2150: colour = p2; truelight@0: peter1138@4603: if (scheme >= LS_END || state >= 3) return CMD_ERROR; peter1138@4603: tron@1767: p = GetPlayer(_current_player); truelight@0: peter1138@4603: /* Ensure no two companies have the same primary colour */ peter1138@4603: if (scheme == LS_DEFAULT && state == 0) { peter1138@4603: FOR_ALL_PLAYERS(pp) { peter1138@4603: if (pp->is_active && pp != p && pp->player_color == colour) return CMD_ERROR; peter1138@4603: } truelight@0: } truelight@193: truelight@0: if (flags & DC_EXEC) { peter1138@4603: switch (state) { peter1138@4603: case 0: peter1138@4603: p->livery[scheme].colour1 = colour; peter1138@4603: peter1138@4603: /* If setting the first colour of the default scheme, adjust the peter1138@4603: * original and cached player colours too. */ peter1138@4603: if (scheme == LS_DEFAULT) { peter1138@4603: _player_colors[_current_player] = colour; peter1138@4603: p->player_color = colour; peter1138@4603: } peter1138@4603: break; peter1138@4603: peter1138@4603: case 1: peter1138@4603: p->livery[scheme].colour2 = colour; peter1138@4603: break; peter1138@4603: peter1138@4603: case 2: peter1138@4603: p->livery[scheme].in_use = colour != 0; peter1138@4603: peter1138@4603: /* Now handle setting the default scheme's in_use flag. peter1138@4603: * This is different to the other schemes, as it signifies if any peter1138@4603: * scheme is active at all. If this flag is not set, then no peter1138@4603: * processing of vehicle types occurs at all, and only the default peter1138@4603: * colours will be used. */ peter1138@4603: peter1138@4603: /* If enabling a scheme, set the default scheme to be in use too */ peter1138@4603: if (colour != 0) { peter1138@4603: p->livery[LS_DEFAULT].in_use = true; peter1138@4603: break; peter1138@4603: } peter1138@4603: peter1138@4603: /* Else loop through all schemes to see if any are left enabled. peter1138@4603: * If not, disable the default scheme too. */ peter1138@4603: p->livery[LS_DEFAULT].in_use = false; peter1138@4603: for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { peter1138@4603: if (p->livery[scheme].in_use) { peter1138@4603: p->livery[LS_DEFAULT].in_use = true; peter1138@4603: break; peter1138@4603: } peter1138@4603: } peter1138@4603: break; peter1138@4603: peter1138@4603: default: peter1138@4603: break; peter1138@4603: } truelight@0: MarkWholeScreenDirty(); truelight@0: } truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1786: /** Increase the loan of your company. tron@3491: * @param tile unused Darkvater@1786: * @param p1 unused Darkvater@1786: * @param p2 when set, loans the maximum amount in one go (press CTRL) Darkvater@1786: */ tron@3491: int32 CmdIncreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { truelight@0: Player *p; truelight@0: tron@1767: p = GetPlayer(_current_player); truelight@0: truelight@0: if (p->current_loan >= _economy.max_loan) { tron@534: SetDParam(0, _economy.max_loan); truelight@0: return_cmd_error(STR_702B_MAXIMUM_PERMITTED_LOAN); truelight@0: } truelight@0: truelight@0: if (flags & DC_EXEC) { Darkvater@1786: /* Loan the maximum amount or not? */ Darkvater@4845: int32 loan = (p2) ? _economy.max_loan - p->current_loan : (IsHumanPlayer(_current_player) || _patches.ainew_active) ? 10000 : 50000; truelight@0: Darkvater@1786: p->money64 += loan; Darkvater@1786: p->current_loan += loan; truelight@0: UpdatePlayerMoney32(p); truelight@0: InvalidatePlayerWindows(p); truelight@0: } truelight@0: truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1786: /** Decrease the loan of your company. tron@3491: * @param tile unused Darkvater@1786: * @param p1 unused Darkvater@1786: * @param p2 when set, pays back the maximum loan permitting money (press CTRL) Darkvater@1786: */ tron@3491: int32 CmdDecreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { truelight@0: Player *p; Darkvater@1786: int32 loan; truelight@0: tron@1767: p = GetPlayer(_current_player); truelight@0: Darkvater@1786: if (p->current_loan == 0) return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED); truelight@0: Darkvater@1786: loan = p->current_loan; Darkvater@1786: Darkvater@1786: /* p2 is true while CTRL is pressed (repay all possible loan, or max money you have) Darkvater@1786: * Repay any loan in chunks of 10.000 pounds */ Darkvater@1786: if (p2) { Darkvater@1786: loan = min(loan, p->player_money); Darkvater@1786: loan = max(loan, 10000); Darkvater@1786: loan -= loan % 10000; Darkvater@1786: } else { Darkvater@4845: loan = min(loan, (IsHumanPlayer(_current_player) || _patches.ainew_active) ? 10000 : 50000); truelight@0: } truelight@0: Darkvater@1786: if (p->player_money < loan) { Darkvater@1786: SetDParam(0, loan); truelight@0: return_cmd_error(STR_702E_REQUIRED); truelight@0: } truelight@0: truelight@0: if (flags & DC_EXEC) { Darkvater@1786: p->money64 -= loan; Darkvater@1786: p->current_loan -= loan; truelight@0: UpdatePlayerMoney32(p); truelight@0: InvalidatePlayerWindows(p); truelight@0: } truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1786: /** Change the name of the company. tron@3491: * @param tile unused Darkvater@1786: * @param p1 unused Darkvater@1786: * @param p2 unused Darkvater@1786: */ tron@3491: int32 CmdChangeCompanyName(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { Darkvater@1787: StringID str; truelight@0: Player *p; truelight@0: Darkvater@1840: if (_cmd_text[0] == '\0') return CMD_ERROR; Darkvater@1840: tron@1820: str = AllocateNameUnique(_cmd_text, 4); Darkvater@1786: if (str == 0) return CMD_ERROR; truelight@193: truelight@0: if (flags & DC_EXEC) { celestar@1962: p = GetPlayer(_current_player); Darkvater@1787: DeleteName(p->name_1); truelight@0: p->name_1 = str; truelight@0: MarkWholeScreenDirty(); tron@4077: } else { truelight@0: DeleteName(str); tron@4077: } truelight@0: truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1786: /** Change the name of the president. tron@3491: * @param tile unused Darkvater@1786: * @param p1 unused Darkvater@1786: * @param p2 unused Darkvater@1786: */ tron@3491: int32 CmdChangePresidentName(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { Darkvater@1787: StringID str; truelight@0: Player *p; truelight@0: Darkvater@1840: if (_cmd_text[0] == '\0') return CMD_ERROR; Darkvater@1840: tron@1820: str = AllocateNameUnique(_cmd_text, 4); Darkvater@1786: if (str == 0) return CMD_ERROR; truelight@193: truelight@0: if (flags & DC_EXEC) { celestar@1962: p = GetPlayer(_current_player); Darkvater@1787: DeleteName(p->president_name_1); truelight@0: p->president_name_1 = str; truelight@0: truelight@0: if (p->name_1 == STR_SV_UNNAMED) { tron@1820: char buf[80]; tron@1820: tron@1820: snprintf(buf, lengthof(buf), "%s Transport", _cmd_text); tron@1820: _cmd_text = buf; tron@3491: DoCommand(0, 0, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME); truelight@193: } truelight@0: MarkWholeScreenDirty(); tron@4077: } else { truelight@0: DeleteName(str); tron@4077: } truelight@0: truelight@193: return 0; truelight@0: } truelight@0: Darkvater@1793: /** Pause/Unpause the game (server-only). Darkvater@1793: * Increase or decrease the pause counter. If the counter is zero, Darkvater@1793: * the game is unpaused. A counter is used instead of a boolean value Darkvater@1793: * to have more control over the game when saving/loading, etc. tron@3491: * @param tile unused Darkvater@1793: * @param p1 0 = decrease pause counter; 1 = increase pause counter Darkvater@1793: * @param p2 unused Darkvater@1793: */ tron@3491: int32 CmdPause(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { truelight@0: if (flags & DC_EXEC) { darkvater@1147: _pause += (p1 == 1) ? 1 : -1; darkvater@1147: if (_pause == (byte)-1) _pause = 0; truelight@0: InvalidateWindow(WC_STATUS_BAR, 0); truelight@0: InvalidateWindow(WC_MAIN_TOOLBAR, 0); truelight@0: } truelight@0: return 0; truelight@0: } truelight@0: Darkvater@1796: /** Change the financial flow of your company. Darkvater@1796: * This is normally only enabled in offline mode, but if there is a debug Darkvater@1796: * build, you can cheat (to test). tron@3491: * @param tile unused Darkvater@1796: * @param p1 the amount of money to receive (if negative), or spend (if positive) Darkvater@1796: * @param p2 unused Darkvater@1796: */ tron@3491: int32 CmdMoneyCheat(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { Darkvater@1796: #ifndef _DEBUG Darkvater@1796: if (_networking) return CMD_ERROR; Darkvater@1796: #endif truelight@193: SET_EXPENSES_TYPE(EXPENSES_OTHER); truelight@0: return (int32)p1; truelight@0: } truelight@0: Darkvater@1796: /** Transfer funds (money) from one player to another. rubidium@4434: * To prevent abuse in multiplayer games you can only send money to other Darkvater@1799: * players if you have paid off your loan (either explicitely, or implicitely Darkvater@1799: * given the fact that you have more money than loan). tron@3491: * @param tile unused Darkvater@1799: * @param p1 the amount of money to transfer; max 20.000.000 Darkvater@1796: * @param p2 the player to transfer the money to Darkvater@1796: */ tron@3491: int32 CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@543: { celestar@1962: const Player *p = GetPlayer(_current_player); Darkvater@1799: int32 amount = min((int32)p1, 20000000); Darkvater@1799: truelight@543: SET_EXPENSES_TYPE(EXPENSES_OTHER); truelight@543: Darkvater@1799: /* You can only transfer funds that is in excess of your loan */ Darkvater@1799: if (p->money64 - p->current_loan < amount || amount <= 0) return CMD_ERROR; Darkvater@4850: if (!_networking || !IsValidPlayer((PlayerID)p2)) return CMD_ERROR; truelight@813: truelight@543: if (flags & DC_EXEC) { Darkvater@1799: /* Add money to player */ Darkvater@1796: PlayerID old_cp = _current_player; truelight@543: _current_player = p2; Darkvater@1799: SubtractMoneyFromPlayer(-amount); truelight@543: _current_player = old_cp; truelight@543: } truelight@543: Darkvater@1799: /* Subtract money from local-player */ Darkvater@1799: return amount; truelight@543: } truelight@543: Darkvater@1793: /** Change difficulty level/settings (server-only). Darkvater@1793: * We cannot really check for valid values of p2 (too much work mostly); stored Darkvater@1793: * in file 'settings_gui.c' _game_setting_info[]; we'll just trust the server it knows Darkvater@1793: * what to do and does this correctly tron@3491: * @param tile unused Darkvater@1793: * @param p1 the difficulty setting being changed. If it is -1, the difficulty level Darkvater@1793: * itself is changed. The new value is inside p2 Darkvater@1793: * @param p2 new value for a difficulty setting or difficulty level Darkvater@1793: */ tron@3491: int32 CmdChangeDifficultyLevel(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) truelight@0: { Darkvater@1877: if (p1 != (uint32)-1L && ((int32)p1 >= GAME_DIFFICULTY_NUM || (int32)p1 < 0)) return CMD_ERROR; Darkvater@1793: truelight@0: if (flags & DC_EXEC) { truelight@0: if (p1 != (uint32)-1L) { Darkvater@1500: ((int*)&_opt_ptr->diff)[p1] = p2; Darkvater@1793: _opt_ptr->diff_level = 3; // custom difficulty level tron@4077: } else { Darkvater@1500: _opt_ptr->diff_level = p2; tron@4077: } Darkvater@1500: Darkvater@1793: /* If we are a network-client, update the difficult setting (if it is open). Darkvater@1793: * Use this instead of just dirtying the window because we need to load in Darkvater@1877: * the new difficulty settings */ truelight@543: if (_networking && !_network_server && FindWindowById(WC_GAME_OPTIONS, 0) != NULL) Darkvater@1500: ShowGameDifficulty(); truelight@0: } truelight@193: return 0; truelight@0: }