src/misc_cmd.cpp
changeset 10207 c291a21b304e
parent 10151 0dd6c35bf0cc
child 10208 72c00af5c95d
equal deleted inserted replaced
10206:0050610c0368 10207:c291a21b304e
    23 #include "player_gui.h"
    23 #include "player_gui.h"
    24 #include "settings_type.h"
    24 #include "settings_type.h"
    25 
    25 
    26 #include "table/strings.h"
    26 #include "table/strings.h"
    27 
    27 
    28 /** Change the player's face.
    28 /** Change the company manager's face.
    29  * @param tile unused
    29  * @param tile unused
    30  * @param flags operation to perform
    30  * @param flags operation to perform
    31  * @param p1 unused
    31  * @param p1 unused
    32  * @param p2 face bitmasked
    32  * @param p2 face bitmasked
    33  */
    33  */
    34 CommandCost CmdSetPlayerFace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    34 CommandCost CmdSetCompanyManagerFace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    35 {
    35 {
    36 	PlayerFace pf = (PlayerFace)p2;
    36 	CompanyManagerFace cmf = (CompanyManagerFace)p2;
    37 
    37 
    38 	if (!IsValidPlayerIDFace(pf)) return CMD_ERROR;
    38 	if (!IsValidCompanyManagerFace(cmf)) return CMD_ERROR;
    39 
    39 
    40 	if (flags & DC_EXEC) {
    40 	if (flags & DC_EXEC) {
    41 		GetPlayer(_current_player)->face = pf;
    41 		GetCompany(_current_company)->face = cmf;
    42 		MarkWholeScreenDirty();
    42 		MarkWholeScreenDirty();
    43 	}
    43 	}
    44 	return CommandCost();
    44 	return CommandCost();
    45 }
    45 }
    46 
    46 
    47 /** Change the player's company-colour
    47 /** Change the company's company-colour
    48  * @param tile unused
    48  * @param tile unused
    49  * @param flags operation to perform
    49  * @param flags operation to perform
    50  * @param p1 bitstuffed:
    50  * @param p1 bitstuffed:
    51  * p1 bits 0-7 scheme to set
    51  * p1 bits 0-7 scheme to set
    52  * p1 bits 8-9 set in use state or first/second colour
    52  * p1 bits 8-9 set in use state or first/second colour
    53  * @param p2 new colour for vehicles, property, etc.
    53  * @param p2 new colour for vehicles, property, etc.
    54  */
    54  */
    55 CommandCost CmdSetPlayerColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    55 CommandCost CmdSetCompanyColor(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
    56 {
    56 {
    57 	if (p2 >= 16) return CMD_ERROR; // max 16 colours
    57 	if (p2 >= 16) return CMD_ERROR; // max 16 colours
    58 
    58 
    59 	byte colour = p2;
    59 	byte colour = p2;
    60 
    60 
    61 	LiveryScheme scheme = (LiveryScheme)GB(p1, 0, 8);
    61 	LiveryScheme scheme = (LiveryScheme)GB(p1, 0, 8);
    62 	byte state = GB(p1, 8, 2);
    62 	byte state = GB(p1, 8, 2);
    63 
    63 
    64 	if (scheme >= LS_END || state >= 3) return CMD_ERROR;
    64 	if (scheme >= LS_END || state >= 3) return CMD_ERROR;
    65 
    65 
    66 	Player *p = GetPlayer(_current_player);
    66 	Company *c = GetCompany(_current_company);
    67 
    67 
    68 	/* Ensure no two companies have the same primary colour */
    68 	/* Ensure no two companies have the same primary colour */
    69 	if (scheme == LS_DEFAULT && state == 0) {
    69 	if (scheme == LS_DEFAULT && state == 0) {
    70 		const Player *pp;
    70 		const Company *cc;
    71 		FOR_ALL_PLAYERS(pp) {
    71 		FOR_ALL_COMPANIES(cc) {
    72 			if (pp != p && pp->player_color == colour) return CMD_ERROR;
    72 			if (cc != c && cc->colour == colour) return CMD_ERROR;
    73 		}
    73 		}
    74 	}
    74 	}
    75 
    75 
    76 	if (flags & DC_EXEC) {
    76 	if (flags & DC_EXEC) {
    77 		switch (state) {
    77 		switch (state) {
    78 			case 0:
    78 			case 0:
    79 				p->livery[scheme].colour1 = colour;
    79 				c->livery[scheme].colour1 = colour;
    80 
    80 
    81 				/* If setting the first colour of the default scheme, adjust the
    81 				/* If setting the first colour of the default scheme, adjust the
    82 				 * original and cached player colours too. */
    82 				 * original and cached company colours too. */
    83 				if (scheme == LS_DEFAULT) {
    83 				if (scheme == LS_DEFAULT) {
    84 					_player_colors[_current_player] = colour;
    84 					_company_colours[_current_company] = colour;
    85 					p->player_color = colour;
    85 					c->colour = colour;
    86 				}
    86 				}
    87 				break;
    87 				break;
    88 
    88 
    89 			case 1:
    89 			case 1:
    90 				p->livery[scheme].colour2 = colour;
    90 				c->livery[scheme].colour2 = colour;
    91 				break;
    91 				break;
    92 
    92 
    93 			case 2:
    93 			case 2:
    94 				p->livery[scheme].in_use = colour != 0;
    94 				c->livery[scheme].in_use = colour != 0;
    95 
    95 
    96 				/* Now handle setting the default scheme's in_use flag.
    96 				/* Now handle setting the default scheme's in_use flag.
    97 				 * This is different to the other schemes, as it signifies if any
    97 				 * This is different to the other schemes, as it signifies if any
    98 				 * scheme is active at all. If this flag is not set, then no
    98 				 * scheme is active at all. If this flag is not set, then no
    99 				 * processing of vehicle types occurs at all, and only the default
    99 				 * processing of vehicle types occurs at all, and only the default
   100 				 * colours will be used. */
   100 				 * colours will be used. */
   101 
   101 
   102 				/* If enabling a scheme, set the default scheme to be in use too */
   102 				/* If enabling a scheme, set the default scheme to be in use too */
   103 				if (colour != 0) {
   103 				if (colour != 0) {
   104 					p->livery[LS_DEFAULT].in_use = true;
   104 					c->livery[LS_DEFAULT].in_use = true;
   105 					break;
   105 					break;
   106 				}
   106 				}
   107 
   107 
   108 				/* Else loop through all schemes to see if any are left enabled.
   108 				/* Else loop through all schemes to see if any are left enabled.
   109 				 * If not, disable the default scheme too. */
   109 				 * If not, disable the default scheme too. */
   110 				p->livery[LS_DEFAULT].in_use = false;
   110 				c->livery[LS_DEFAULT].in_use = false;
   111 				for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
   111 				for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
   112 					if (p->livery[scheme].in_use) {
   112 					if (c->livery[scheme].in_use) {
   113 						p->livery[LS_DEFAULT].in_use = true;
   113 						c->livery[LS_DEFAULT].in_use = true;
   114 						break;
   114 						break;
   115 					}
   115 					}
   116 				}
   116 				}
   117 				break;
   117 				break;
   118 
   118 
   132  * @param p2 when 0: loans LOAN_INTERVAL
   132  * @param p2 when 0: loans LOAN_INTERVAL
   133  *           when 1: loans the maximum loan permitting money (press CTRL),
   133  *           when 1: loans the maximum loan permitting money (press CTRL),
   134  */
   134  */
   135 CommandCost CmdIncreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   135 CommandCost CmdIncreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   136 {
   136 {
   137 	Player *p = GetPlayer(_current_player);
   137 	Company *c = GetCompany(_current_company);
   138 
   138 
   139 	if (p->current_loan >= _economy.max_loan) {
   139 	if (c->current_loan >= _economy.max_loan) {
   140 		SetDParam(0, _economy.max_loan);
   140 		SetDParam(0, _economy.max_loan);
   141 		return_cmd_error(STR_702B_MAXIMUM_PERMITTED_LOAN);
   141 		return_cmd_error(STR_702B_MAXIMUM_PERMITTED_LOAN);
   142 	}
   142 	}
   143 
   143 
   144 	Money loan;
   144 	Money loan;
   145 	switch (p2) {
   145 	switch (p2) {
   146 		default: return CMD_ERROR; // Invalid method
   146 		default: return CMD_ERROR; // Invalid method
   147 		case 0: // Take some extra loan
   147 		case 0: // Take some extra loan
   148 			loan = (IsHumanPlayer(_current_player) || _settings_game.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI;
   148 			loan = (IsHumanCompany(_current_company) || _settings_game.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI;
   149 			break;
   149 			break;
   150 		case 1: // Take a loan as big as possible
   150 		case 1: // Take a loan as big as possible
   151 			loan = _economy.max_loan - p->current_loan;
   151 			loan = _economy.max_loan - c->current_loan;
   152 			break;
   152 			break;
   153 	}
   153 	}
   154 
   154 
   155 	/* Overflow protection */
   155 	/* Overflow protection */
   156 	if (p->player_money + p->current_loan + loan < p->player_money) return CMD_ERROR;
   156 	if (c->money + c->current_loan + loan < c->money) return CMD_ERROR;
   157 
   157 
   158 	if (flags & DC_EXEC) {
   158 	if (flags & DC_EXEC) {
   159 		p->player_money += loan;
   159 		c->money        += loan;
   160 		p->current_loan += loan;
   160 		c->current_loan += loan;
   161 		InvalidatePlayerWindows(p);
   161 		InvalidateCompanyWindows(c);
   162 	}
   162 	}
   163 
   163 
   164 	return CommandCost(EXPENSES_OTHER);
   164 	return CommandCost(EXPENSES_OTHER);
   165 }
   165 }
   166 
   166 
   171  * @param p2 when 0: pays back LOAN_INTERVAL
   171  * @param p2 when 0: pays back LOAN_INTERVAL
   172  *           when 1: pays back the maximum loan permitting money (press CTRL),
   172  *           when 1: pays back the maximum loan permitting money (press CTRL),
   173  */
   173  */
   174 CommandCost CmdDecreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   174 CommandCost CmdDecreaseLoan(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   175 {
   175 {
   176 	Player *p = GetPlayer(_current_player);
   176 	Company *c = GetCompany(_current_company);
   177 
   177 
   178 	if (p->current_loan == 0) return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED);
   178 	if (c->current_loan == 0) return_cmd_error(STR_702D_LOAN_ALREADY_REPAYED);
   179 
   179 
   180 	Money loan;
   180 	Money loan;
   181 	switch (p2) {
   181 	switch (p2) {
   182 		default: return CMD_ERROR; // Invalid method
   182 		default: return CMD_ERROR; // Invalid method
   183 		case 0: // Pay back one step
   183 		case 0: // Pay back one step
   184 			loan = min(p->current_loan, (Money)(IsHumanPlayer(_current_player) || _settings_game.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI);
   184 			loan = min(c->current_loan, (Money)(IsHumanCompany(_current_company) || _settings_game.ai.ainew_active) ? LOAN_INTERVAL : LOAN_INTERVAL_OLD_AI);
   185 			break;
   185 			break;
   186 		case 1: // Pay back as much as possible
   186 		case 1: // Pay back as much as possible
   187 			loan = max(min(p->current_loan, p->player_money), (Money)LOAN_INTERVAL);
   187 			loan = max(min(c->current_loan, c->money), (Money)LOAN_INTERVAL);
   188 			loan -= loan % LOAN_INTERVAL;
   188 			loan -= loan % LOAN_INTERVAL;
   189 			break;
   189 			break;
   190 	}
   190 	}
   191 
   191 
   192 	if (p->player_money < loan) {
   192 	if (c->money < loan) {
   193 		SetDParam(0, loan);
   193 		SetDParam(0, loan);
   194 		return_cmd_error(STR_702E_REQUIRED);
   194 		return_cmd_error(STR_702E_REQUIRED);
   195 	}
   195 	}
   196 
   196 
   197 	if (flags & DC_EXEC) {
   197 	if (flags & DC_EXEC) {
   198 		p->player_money -= loan;
   198 		c->money        -= loan;
   199 		p->current_loan -= loan;
   199 		c->current_loan -= loan;
   200 		InvalidatePlayerWindows(p);
   200 		InvalidateCompanyWindows(c);
   201 	}
   201 	}
   202 	return CommandCost();
   202 	return CommandCost();
   203 }
   203 }
   204 
   204 
   205 static bool IsUniqueCompanyName(const char *name)
   205 static bool IsUniqueCompanyName(const char *name)
   206 {
   206 {
   207 	const Player *p;
   207 	const Company *c;
   208 	char buf[512];
   208 	char buf[512];
   209 
   209 
   210 	FOR_ALL_PLAYERS(p) {
   210 	FOR_ALL_COMPANIES(c) {
   211 		SetDParam(0, p->index);
   211 		SetDParam(0, c->index);
   212 		GetString(buf, STR_COMPANY_NAME, lastof(buf));
   212 		GetString(buf, STR_COMPANY_NAME, lastof(buf));
   213 		if (strcmp(buf, name) == 0) return false;
   213 		if (strcmp(buf, name) == 0) return false;
   214 	}
   214 	}
   215 
   215 
   216 	return true;
   216 	return true;
   230 		if (strlen(_cmd_text) >= MAX_LENGTH_COMPANY_NAME_BYTES) return CMD_ERROR;
   230 		if (strlen(_cmd_text) >= MAX_LENGTH_COMPANY_NAME_BYTES) return CMD_ERROR;
   231 		if (!IsUniqueCompanyName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
   231 		if (!IsUniqueCompanyName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
   232 	}
   232 	}
   233 
   233 
   234 	if (flags & DC_EXEC) {
   234 	if (flags & DC_EXEC) {
   235 		Player *p = GetPlayer(_current_player);
   235 		Company *c = GetCompany(_current_company);
   236 		free(p->name);
   236 		free(c->name);
   237 		p->name = reset ? NULL : strdup(_cmd_text);
   237 		c->name = reset ? NULL : strdup(_cmd_text);
   238 		MarkWholeScreenDirty();
   238 		MarkWholeScreenDirty();
   239 	}
   239 	}
   240 
   240 
   241 	return CommandCost();
   241 	return CommandCost();
   242 }
   242 }
   243 
   243 
   244 static bool IsUniquePresidentName(const char *name)
   244 static bool IsUniquePresidentName(const char *name)
   245 {
   245 {
   246 	const Player *p;
   246 	const Company *c;
   247 	char buf[512];
   247 	char buf[512];
   248 
   248 
   249 	FOR_ALL_PLAYERS(p) {
   249 	FOR_ALL_COMPANIES(c) {
   250 		SetDParam(0, p->index);
   250 		SetDParam(0, c->index);
   251 		GetString(buf, STR_PLAYER_NAME, lastof(buf));
   251 		GetString(buf, STR_PLAYER_NAME, lastof(buf));
   252 		if (strcmp(buf, name) == 0) return false;
   252 		if (strcmp(buf, name) == 0) return false;
   253 	}
   253 	}
   254 
   254 
   255 	return true;
   255 	return true;
   269 		if (strlen(_cmd_text) >= MAX_LENGTH_PRESIDENT_NAME_BYTES) return CMD_ERROR;
   269 		if (strlen(_cmd_text) >= MAX_LENGTH_PRESIDENT_NAME_BYTES) return CMD_ERROR;
   270 		if (!IsUniquePresidentName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
   270 		if (!IsUniquePresidentName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
   271 	}
   271 	}
   272 
   272 
   273 	if (flags & DC_EXEC) {
   273 	if (flags & DC_EXEC) {
   274 		Player *p = GetPlayer(_current_player);
   274 		Company *c = GetCompany(_current_company);
   275 		free(p->president_name);
   275 		free(c->president_name);
   276 
   276 
   277 		if (reset) {
   277 		if (reset) {
   278 			p->president_name = NULL;
   278 			c->president_name = NULL;
   279 		} else {
   279 		} else {
   280 			p->president_name = strdup(_cmd_text);
   280 			c->president_name = strdup(_cmd_text);
   281 
   281 
   282 			if (p->name_1 == STR_SV_UNNAMED && p->name == NULL) {
   282 			if (c->name_1 == STR_SV_UNNAMED && c->name == NULL) {
   283 				char buf[80];
   283 				char buf[80];
   284 
   284 
   285 				snprintf(buf, lengthof(buf), "%s Transport", _cmd_text);
   285 				snprintf(buf, lengthof(buf), "%s Transport", _cmd_text);
   286 				_cmd_text = buf;
   286 				_cmd_text = buf;
   287 				DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY);
   287 				DoCommand(0, 0, 0, DC_EXEC, CMD_RENAME_COMPANY);
   356 	if (_networking) return CMD_ERROR;
   356 	if (_networking) return CMD_ERROR;
   357 #endif
   357 #endif
   358 	return CommandCost(EXPENSES_OTHER, -(int32)p1);
   358 	return CommandCost(EXPENSES_OTHER, -(int32)p1);
   359 }
   359 }
   360 
   360 
   361 /** Transfer funds (money) from one player to another.
   361 /** Transfer funds (money) from one company to another.
   362  * To prevent abuse in multiplayer games you can only send money to other
   362  * To prevent abuse in multiplayer games you can only send money to other
   363  * players if you have paid off your loan (either explicitely, or implicitely
   363  * companies if you have paid off your loan (either explicitely, or implicitely
   364  * given the fact that you have more money than loan).
   364  * given the fact that you have more money than loan).
   365  * @param tile unused
   365  * @param tile unused
   366  * @param flags operation to perform
   366  * @param flags operation to perform
   367  * @param p1 the amount of money to transfer; max 20.000.000
   367  * @param p1 the amount of money to transfer; max 20.000.000
   368  * @param p2 the player to transfer the money to
   368  * @param p2 the company to transfer the money to
   369  */
   369  */
   370 CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   370 CommandCost CmdGiveMoney(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   371 {
   371 {
   372 	if (!_settings_game.economy.give_money) return CMD_ERROR;
   372 	if (!_settings_game.economy.give_money) return CMD_ERROR;
   373 
   373 
   374 	const Player *p = GetPlayer(_current_player);
   374 	const Company *c = GetCompany(_current_company);
   375 	CommandCost amount(EXPENSES_OTHER, min((Money)p1, (Money)20000000LL));
   375 	CommandCost amount(EXPENSES_OTHER, min((Money)p1, (Money)20000000LL));
   376 
   376 
   377 	/* You can only transfer funds that is in excess of your loan */
   377 	/* You can only transfer funds that is in excess of your loan */
   378 	if (p->player_money - p->current_loan < amount.GetCost() || amount.GetCost() <= 0) return CMD_ERROR;
   378 	if (c->money - c->current_loan < amount.GetCost() || amount.GetCost() <= 0) return CMD_ERROR;
   379 	if (!_networking || !IsValidPlayerID((PlayerID)p2)) return CMD_ERROR;
   379 	if (!_networking || !IsValidCompanyID((CompanyID)p2)) return CMD_ERROR;
   380 
   380 
   381 	if (flags & DC_EXEC) {
   381 	if (flags & DC_EXEC) {
   382 		/* Add money to player */
   382 		/* Add money to company */
   383 		PlayerID old_cp = _current_player;
   383 		CompanyID old_company = _current_company;
   384 		_current_player = (PlayerID)p2;
   384 		_current_company = (CompanyID)p2;
   385 		SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
   385 		SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -amount.GetCost()));
   386 		_current_player = old_cp;
   386 		_current_company = old_company;
   387 	}
   387 	}
   388 
   388 
   389 	/* Subtract money from local-player */
   389 	/* Subtract money from local-company */
   390 	return amount;
   390 	return amount;
   391 }
   391 }