# misc_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: misc_cmd.cpp 14347 2008-09-16 20:29:09Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "command_func.h"
    00008 #include "economy_func.h"
    00009 #include "gui.h"
    00010 #include "window_func.h"
    00011 #include "textbuf_gui.h"
    00012 #include "network/network.h"
    00013 #include "variables.h"
    00014 #include "livery.h"
    00015 #include "player_face.h"
    00016 #include "strings_func.h"
    00017 #include "gfx_func.h"
    00018 #include "functions.h"
    00019 #include "vehicle_func.h"
    00020 #include "string_func.h"
    00021 #include "player_func.h"
    00022 #include "player_base.h"
    00023 #include "player_gui.h"
    00024 #include "settings_type.h"
    00025
    00026 #include "table/strings.h"
    00027
    00034 CommandCost CmdSetPlayerFace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00035 {
    00036   PlayerFace pf = (PlayerFace)p2;
    00037
    00038   if (!IsValidPlayerFace(pf)) return CMD_ERROR;
    00039
    00040   if (flags & DC_EXEC) {
    00041     GetPlayer(_current_player)->face = pf;
    00042     MarkWholeScreenDirty();
    00043   }
    00044   return CommandCost();
    00045 }
    00046
    00055 CommandCost CmdSetPlayerColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00056 {
    00057   Player *p, *pp;
    00058   byte colour;
    00059   LiveryScheme scheme = (LiveryScheme)GB(p1, 0, 8);
    00060   byte state = GB(p1, 8, 2);
    00061
    00062   if (p2 >= 16) return CMD_ERROR; // max 16 colours
    00063   colour = p2;
    00064
    00065   if (scheme >= LS_END || state >= 3) return CMD_ERROR;
    00066
    00067   p = GetPlayer(_current_player);
    00068
    00069   /* Ensure no two companies have the same primary colour */
    00070   if (scheme == LS_DEFAULT && state == 0) {
    00071     FOR_ALL_PLAYERS(pp) {
    00072       if (pp->is_active && pp != p && pp->player_color == colour) return CMD_ERROR;
    00073     }
    00074   }
    00075
    00076   if (flags & DC_EXEC) {
    00077     switch (state) {
    00078       case 0:
    00079         p->livery[scheme].colour1 = colour;
    00080
    00081         /* If setting the first colour of the default scheme, adjust the
    00082          * original and cached player colours too. */
    00083         if (scheme == LS_DEFAULT) {
    00084           _player_colors[_current_player] = colour;
    00085           p->player_color = colour;
    00086         }
    00087         break;
    00088
    00089       case 1:
    00090         p->livery[scheme].colour2 = colour;
    00091         break;
    00092
    00093       case 2:
    00094         p->livery[scheme].in_use = colour != 0;
    00095
    00096         /* Now handle setting the default scheme's in_use flag.
    00097          * This is different to the other schemes, as it signifies if any
    00098          * scheme is active at all. If this flag is not set, then no
    00099          * processing of vehicle types occurs at all, and only the default
    00100          * colours will be used. */
    00101
    00102         /* If enabling a scheme, set the default scheme to be in use too */
    00103         if (colour != 0) {
    00104           p->livery[LS_DEFAULT].in_use = true;
    00105           break;
    00106         }
    00107
    00108         /* Else loop through all schemes to see if any are left enabled.
    00109          * If not, disable the default scheme too. */
    00110         p->livery[LS_DEFAULT].in_use = false;
    00111         for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
    00112           if (p->livery[scheme].in_use) {
    00113             p->livery[LS_DEFAULT].in_use = true;
    00114             break;
    00115           }
    00116         }
    00117         break;
    00118
    00119       default:
    00120         break;
    00121     }
    00122     ResetVehicleColorMap();
    00123     MarkWholeScreenDirty();
    00124   }
    00125   return CommandCost();
    00126 }
    00127
    00135 CommandCost CmdIncreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00136 {
    00137   Player *p = GetPlayer(_current_player);
    00138
    00139   if (p->current_loan >= _economy.max_loan) {
    00140     SetDParam(0, _economy.max_loan);
    00141     return_cmd_error(STR_702B_MAXIMUM_PERMITTED_LOAN);
    00142   }
    00143
    00144   Money loan;
    00145   switch (p2) {
    00146     default: return CMD_ERROR; // Invalid method
    00147     case 0: // Take some extra loan
    00148       loan = (IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI;
    00149       break;
    00150     case 1: // Take a loan as big as possible
    00151       loan = _economy.max_loan - p->current_loan;
    00152       break;
    00153   }
    00154
    00155   /* Overflow protection */
    00156   if (p->player_money + p->current_loan + loan < p->player_money) return CMD_ERROR;
    00157
    00158   if (flags & DC_EXEC) {
    00159     p->player_money += loan;
    00160     p->current_loan += loan;
    00161     InvalidatePlayerWindows(p);
    00162   }
    00163
    00164   return CommandCost(EXPENSES_OTHER);
    00165 }
    00166
    00174 CommandCost CmdDecreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00175 {
    00176   Player *p = GetPlayer(_current_player);
    00177
    00178   if (p->current_loan == 0) return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED);
    00179
    00180   Money loan;
    00181   switch (p2) {
    00182     default: return CMD_ERROR; // Invalid method
    00183     case 0: // Pay back one step
    00184       loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _patches.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI);
    00185       break;
    00186     case 1: // Pay back as much as possible
    00187       loan = max(min(p->current_loan, p->player_money), (Money)LOAN_INTERVAL);
    00188       loan -= loan % LOAN_INTERVAL;
    00189       break;
    00190   }
    00191
    00192   if (p->player_money < loan) {
    00193     SetDParam(0, loan);
    00194     return_cmd_error(STR_702E_REQUIRED);
    00195   }
    00196
    00197   if (flags & DC_EXEC) {
    00198     p->player_money -= loan;
    00199     p->current_loan -= loan;
    00200     InvalidatePlayerWindows(p);
    00201   }
    00202   return CommandCost();
    00203 }
    00204
    00205 static bool IsUniqueCompanyName(const char *name)
    00206 {
    00207   const Player *p;
    00208   char buf[512];
    00209
    00210   FOR_ALL_PLAYERS(p) {
    00211     if (!p->is_active) continue;
    00212     SetDParam(0, p->index);
    00213     GetString(buf, STR_COMPANY_NAME, lastof(buf));
    00214     if (strcmp(buf, name) == 0) return false;
    00215   }
    00216
    00217   return true;
    00218 }
    00219
    00226 CommandCost CmdChangeCompanyName(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00227 {
    00228   if (StrEmpty(_cmd_text) || strlen(_cmd_text) > MAX_LENGTH_COMPANY_NAME) return CMD_ERROR;
    00229
    00230   if (!IsUniqueCompanyName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
    00231
    00232   if (flags & DC_EXEC) {
    00233     Player *p = GetPlayer(_current_player);
    00234     free(p->name);
    00235     p->name = strdup(_cmd_text);
    00236     MarkWholeScreenDirty();
    00237   }
    00238
    00239   return CommandCost();
    00240 }
    00241
    00242 static bool IsUniquePresidentName(const char *name)
    00243 {
    00244   const Player *p;
    00245   char buf[512];
    00246
    00247   FOR_ALL_PLAYERS(p) {
    00248     if (!p->is_active) continue;
    00249     SetDParam(0, p->index);
    00250     GetString(buf, STR_PLAYER_NAME, lastof(buf));
    00251     if (strcmp(buf, name) == 0) return false;
    00252   }
    00253
    00254   return true;
    00255 }
    00256
    00263 CommandCost CmdChangePresidentName(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00264 {
    00265   if (StrEmpty(_cmd_text) || strlen(_cmd_text) > MAX_LENGTH_PRESIDENT_NAME) return CMD_ERROR;
    00266
    00267   if (!IsUniquePresidentName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
    00268
    00269   if (flags & DC_EXEC) {
    00270     Player *p = GetPlayer(_current_player);
    00271     free(p->president_name);
    00272     p->president_name = strdup(_cmd_text);
    00273
    00274     if (p->name_1 == STR_SV_UNNAMED && p->name == NULL) {
    00275       char buf[80];
    00276
    00277       snprintf(buf, lengthof(buf), "%s Transport", _cmd_text);
    00278       _cmd_text = buf;
    00279       DoCommand(0, 0, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME);
    00280     }
    00281     MarkWholeScreenDirty();
    00282   }
    00283
    00284   return CommandCost();
    00285 }
    00286
    00293 static void AskUnsafeUnpauseCallback(Window *w, bool confirmed)
    00294 {
    00295   DoCommandP(0, confirmed ? 0 : 1, 0, NULL, CMD_PAUSE);
    00296 }
    00297
    00307 CommandCost CmdPause(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00308 {
    00309   if (flags & DC_EXEC) {
    00310     _pause_game += (p1 == 0) ? -1 : 1;
    00311
    00312     switch (_pause_game) {
    00313       case -4:
    00314       case -1:
    00315         _pause_game = 0;
    00316         break;
    00317       case -3:
    00318         ShowQuery(
    00319           STR_NEWGRF_UNPAUSE_WARNING_TITLE,
    00320           STR_NEWGRF_UNPAUSE_WARNING,
    00321           NULL,
    00322           AskUnsafeUnpauseCallback
    00323         );
    00324         break;
    00325
    00326       default: break;
    00327     }
    00328
    00329     InvalidateWindow(WC_STATUS_BAR, 0);
    00330     InvalidateWindow(WC_MAIN_TOOLBAR, 0);
    00331   }
    00332   return CommandCost();
    00333 }
    00334
    00343 CommandCost CmdMoneyCheat(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00344 {
    00345 #ifndef _DEBUG
    00346   if (_networking) return CMD_ERROR;
    00347 #endif
    00348   return CommandCost(EXPENSES_OTHER, -(int32)p1);
    00349 }
    00350
    00360 CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00361 {
    00362   if (!_patches.give_money) return CMD_ERROR;
    00363
    00364   const Player *p = GetPlayer(_current_player);
    00365   CommandCost amount(EXPENSES_OTHER, min((Money)p1, (Money)20000000LL));
    00366
    00367   /* You can only transfer funds that is in excess of your loan */
    00368   if (p->player_money - p->current_loan < amount.GetCost() || amount.GetCost() <= 0) return CMD_ERROR;
    00369   if (!_networking || !IsValidPlayer((PlayerID)p2)) return CMD_ERROR;
    00370
    00371   if (flags & DC_EXEC) {
    00372     /* Add money to player */
    00373     PlayerID old_cp = _current_player;
    00374     _current_player = (PlayerID)p2;
    00375     SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
    00376     _current_player = old_cp;
    00377   }
    00378
    00379   /* Subtract money from local-player */
    00380   return amount;
    00381 }
    00382
    00393 CommandCost CmdChangeDifficultyLevel(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    00394 {
    00395   if (p1 != (uint32)-1L && ((int32)p1 >= GAME_DIFFICULTY_NUM || (int32)p1 < 0)) return CMD_ERROR;
    00396
    00397   if (flags & DC_EXEC) {
    00398     if (p1 != (uint32)-1L) {
    00399       ((GDType*)&_opt_ptr->diff)[p1] = p2;
    00400       _opt_ptr->diff_level = 3; // custom difficulty level
    00401     } else {
    00402       _opt_ptr->diff_level = p2;
    00403     }
    00404
    00405     /* If we are a network-client, update the difficult setting (if it is open).
    00406      * Use this instead of just dirtying the window because we need to load in
    00407      * the new difficulty settings */
    00408     if (_networking && !_network_server && FindWindowById(WC_GAME_OPTIONS, 0) != NULL)
    00409       ShowGameDifficulty();
    00410   }
    00411   return CommandCost();
    00412 }