--- a/src/economy.cpp Thu Apr 19 14:48:10 2007 +0000
+++ b/src/economy.cpp Tue Jun 12 11:56:35 2007 +0000
@@ -6,6 +6,7 @@
#include "openttd.h"
#include "currency.h"
#include "functions.h"
+#include "landscape.h"
#include "strings.h" // XXX InjectDParam()
#include "table/strings.h"
#include "table/sprites.h"
@@ -254,6 +255,41 @@
{
Town *t;
PlayerID old = _current_player;
+
+ assert(old_player != new_player);
+
+ {
+ Player *p;
+ uint i;
+
+ /* See if the old_player had shares in other companies */
+ _current_player = old_player;
+ FOR_ALL_PLAYERS(p) {
+ for (i = 0; i < 4; i++) {
+ if (p->share_owners[i] == old_player) {
+ /* Sell his shares */
+ int32 res = DoCommand(0, p->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
+ /* Because we are in a DoCommand, we can't just execute an other one and
+ * expect the money to be removed. We need to do it ourself! */
+ SubtractMoneyFromPlayer(res);
+ }
+ }
+ }
+
+ /* Sell all the shares that people have on this company */
+ p = GetPlayer(old_player);
+ for (i = 0; i < 4; i++) {
+ _current_player = p->share_owners[i];
+ if (_current_player != PLAYER_SPECTATOR) {
+ /* Sell the shares */
+ int32 res = DoCommand(0, old_player, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
+ /* Because we are in a DoCommand, we can't just execute an other one and
+ * expect the money to be removed. We need to do it ourself! */
+ SubtractMoneyFromPlayer(res);
+ }
+ }
+ }
+
_current_player = old_player;
/* Temporarily increase the player's money, to be sure that
@@ -346,25 +382,6 @@
/* Change color of existing windows */
if (new_player != PLAYER_SPECTATOR) ChangeWindowOwner(old_player, new_player);
- {
- Player *p;
- uint i;
-
- /* Check for shares */
- FOR_ALL_PLAYERS(p) {
- for (i = 0; i < 4; i++) {
- /* 'Sell' the share if this player has any */
- if (p->share_owners[i] == _current_player) {
- p->share_owners[i] = PLAYER_SPECTATOR;
- }
- }
- }
- p = GetPlayer(_current_player);
- /* Sell all the shares that people have on this company */
- for (i = 0; i < 4; i++)
- p->share_owners[i] = PLAYER_SPECTATOR;
- }
-
_current_player = old;
MarkWholeScreenDirty();
@@ -965,6 +982,23 @@
const CargoSpec *cs = GetCargo(cargo_type);
byte f;
+ /* Use callback to calculate cargo profit, if available */
+ if (HASBIT(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
+ uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
+ uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
+ if (callback != CALLBACK_FAILED) {
+ int result = GB(callback, 0, 14);
+
+ /* Simulate a 15 bit signed value */
+ if (HASBIT(callback, 14)) result = 0x4000 - result;
+
+ /* "The result should be a signed multiplier that gets multiplied
+ * by the amount of cargo moved and the price factor, then gets
+ * divided by 8192." */
+ return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
+ }
+ }
+
/* zero the distance if it's the bank and very short transport. */
if (_opt.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10)
dist = 0;
@@ -1520,6 +1554,7 @@
/** Acquire shares in an opposing company.
* @param tile unused
+ * @param flags type of operation
* @param p1 player to buy the shares from
* @param p2 unused
*/
@@ -1565,6 +1600,7 @@
/** Sell shares in an opposing company.
* @param tile unused
+ * @param flags type of operation
* @param p1 player to sell the shares from
* @param p2 unused
*/
@@ -1600,18 +1636,23 @@
* that company.
* @todo currently this only works for AI players
* @param tile unused
+ * @param flags type of operation
* @param p1 player/company to buy up
* @param p2 unused
*/
int32 CmdBuyCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
Player *p;
+ PlayerID pid = (PlayerID)p1;
/* Disable takeovers in multiplayer games */
- if (!IsValidPlayer((PlayerID)p1) || _networking) return CMD_ERROR;
+ if (!IsValidPlayer(pid) || _networking) return CMD_ERROR;
+
+ /* Do not allow players to take over themselves */
+ if (pid == _current_player) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_OTHER);
- p = GetPlayer((PlayerID)p1);
+ p = GetPlayer(pid);
if (!p->is_ai) return CMD_ERROR;