mirror of https://github.com/OpenTTD/OpenTTD
(svn r19646) [1.0] -Backport from trunk:
- Change: Log the _date and _date_fract in the desync log for saved games (r19638) - Fix: Do not allow building cacti outside of the desert or rain forest trees outside of the rain forest area. This to prevent people from thinking planting rain forest trees makes the rain forest bigger and thus adds more place to build a lumber mill [FS#3728] (r19644, r19635, r19634) - Fix: Industry generation failed for large maps and lots of industry types (r19643) - Fix: Desync when taking over companies (r19636) - Fix: Chat message caused glitch when rejoining a network game [FS#3757] (r19629)release/1.0
parent
7c3487501c
commit
4fada121bd
|
@ -177,3 +177,11 @@ OpenTTD not properly resizing with SDL on X [FS#3305]
|
|||
Window managers that are known to exhibit this behaviour are KDE's
|
||||
and GNOME's. With the XFCE's and LXDE's window managers the resize
|
||||
event is sent when the user releases the mouse.
|
||||
|
||||
Content files not properly extracted with zlib 1.2.3.5-1.2.4 [FS#3753]
|
||||
With zlib 1.2.3.5 up to and including 1.2.4 the function "gzeof",
|
||||
which tells when we read the whole file, is broken in such a way
|
||||
that OpenTTD thinks it has extracted and written the whole file
|
||||
while the last few hundred/thousand bytes are not extracted yet.
|
||||
This causes problems for everything that is downloaded from the
|
||||
online content system when using one of those versions of zlib.
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
{
|
||||
EnforcePrecondition(false, ::IsValidTile(tile));
|
||||
|
||||
return AIObject::DoCommand(tile, UINT_MAX, tile, CMD_PLANT_TREE);
|
||||
return AIObject::DoCommand(tile, TREE_INVALID, tile, CMD_PLANT_TREE);
|
||||
}
|
||||
|
||||
/* static */ bool AITile::PlantTreeRectangle(TileIndex tile, uint width, uint height)
|
||||
|
@ -258,7 +258,7 @@
|
|||
EnforcePrecondition(false, height >= 1 && height <= 20);
|
||||
TileIndex end_tile = tile + ::TileDiffXY(width - 1, height - 1);
|
||||
|
||||
return AIObject::DoCommand(tile, UINT_MAX, end_tile, CMD_PLANT_TREE);
|
||||
return AIObject::DoCommand(tile, TREE_INVALID, end_tile, CMD_PLANT_TREE);
|
||||
}
|
||||
|
||||
/* static */ bool AITile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
|
||||
|
|
|
@ -591,14 +591,11 @@ static void HandleBankruptcyTakeover(Company *c)
|
|||
|
||||
SetBit(c->bankrupt_asked, best->index);
|
||||
|
||||
if (IsInteractiveCompany(best->index)) {
|
||||
c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
|
||||
ShowBuyCompanyDialog(c->index);
|
||||
return;
|
||||
}
|
||||
|
||||
c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
|
||||
if (best->is_ai) {
|
||||
AI::NewEvent(best->index, new AIEventCompanyAskMerger(c->index, ClampToI32(c->bankrupt_value)));
|
||||
} else if (IsInteractiveCompany(best->index)) {
|
||||
ShowBuyCompanyDialog(c->index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ uint32 DoRandom(int line, const char *file)
|
|||
|
||||
uint DoRandomRange(uint max, int line, const char *file)
|
||||
{
|
||||
assert(max <= UINT16_MAX);
|
||||
return GB(DoRandom(line, file), 0, 16) * max >> 16;
|
||||
}
|
||||
#endif /* RANDOM_DEBUG */
|
||||
|
|
|
@ -99,8 +99,9 @@ void SetRandomSeed(uint32 seed);
|
|||
return _random.Next();
|
||||
}
|
||||
|
||||
static FORCEINLINE uint32 RandomRange(uint16 max)
|
||||
static FORCEINLINE uint32 RandomRange(uint max)
|
||||
{
|
||||
assert(max <= UINT16_MAX);
|
||||
return _random.Next(max);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1892,7 +1892,8 @@ void GenerateIndustries()
|
|||
|
||||
/* Add the remaining industries according to their probabilities */
|
||||
for (uint i = 0; i < total_amount; i++) {
|
||||
uint32 r = RandomRange(total_prob);
|
||||
/* RandomRange() can only deal with 16 bit, which is not enough here. */
|
||||
uint32 r = ((uint64)Random() * (uint64)total_prob) >> 32;
|
||||
IndustryType it = 0;
|
||||
while (it < NUM_INDUSTRYTYPES && r >= industry_probs[it]) {
|
||||
r -= industry_probs[it];
|
||||
|
|
|
@ -3508,6 +3508,7 @@ STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE :{WHITE}Can't bu
|
|||
|
||||
# Tree related errors
|
||||
STR_ERROR_TREE_ALREADY_HERE :{WHITE}... tree already here
|
||||
STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE :{WHITE}... wrong terrain for tree type
|
||||
STR_ERROR_CAN_T_PLANT_TREE_HERE :{WHITE}Can't plant tree here...
|
||||
|
||||
# Bridge related errors
|
||||
|
|
|
@ -116,14 +116,15 @@ void CDECL NetworkAddChatMessage(TextColour colour, uint8 duration, const char *
|
|||
|
||||
void NetworkInitChatMessage()
|
||||
{
|
||||
MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height;
|
||||
MAX_CHAT_MESSAGES = _settings_client.gui.network_chat_box_height;
|
||||
|
||||
_chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height);
|
||||
_chatmsg_box.x = 10;
|
||||
_chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL;
|
||||
_chatmsg_box.width = _settings_client.gui.network_chat_box_width;
|
||||
_chatmsg_box.height = _settings_client.gui.network_chat_box_height * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 2;
|
||||
_chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactoryBase::GetCurrentBlitter()->GetBytesPerPixel());
|
||||
_chatmsg_list = ReallocT(_chatmsg_list, _settings_client.gui.network_chat_box_height);
|
||||
_chatmsg_box.x = 10;
|
||||
_chatmsg_box.y = 3 * FONT_HEIGHT_NORMAL;
|
||||
_chatmsg_box.width = _settings_client.gui.network_chat_box_width;
|
||||
_chatmsg_box.height = _settings_client.gui.network_chat_box_height * (FONT_HEIGHT_NORMAL + NETWORK_CHAT_LINE_SPACING) + 2;
|
||||
_chatmessage_backup = ReallocT(_chatmessage_backup, _chatmsg_box.width * _chatmsg_box.height * BlitterFactoryBase::GetCurrentBlitter()->GetBytesPerPixel());
|
||||
_chatmessage_visible = false;
|
||||
|
||||
for (uint i = 0; i < MAX_CHAT_MESSAGES; i++) {
|
||||
_chatmsg_list[i].message[0] = '\0';
|
||||
|
|
|
@ -1882,7 +1882,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
|
|||
/* General tactic is to first save the game to memory, then use an available writer
|
||||
* to write it to file, either in threaded mode if possible, or single-threaded */
|
||||
if (mode == SL_SAVE) { // SAVE game
|
||||
DEBUG(desync, 1, "save: %s", filename);
|
||||
DEBUG(desync, 1, "save: %08x; %02x; %s", _date, _date_fract, filename);
|
||||
|
||||
_sl.write_bytes = WriteMem;
|
||||
_sl.excpt_uninit = UnInitMem;
|
||||
|
|
|
@ -336,7 +336,7 @@ void GenerateTrees()
|
|||
/** Plant a tree.
|
||||
* @param tile start tile of area-drag of tree plantation
|
||||
* @param flags type of operation
|
||||
* @param p1 tree type, -1 means random.
|
||||
* @param p1 tree type, TREE_INVALID means random.
|
||||
* @param p2 end tile of area-drag
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
|
@ -345,10 +345,11 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
{
|
||||
StringID msg = INVALID_STRING_ID;
|
||||
CommandCost cost(EXPENSES_OTHER);
|
||||
const byte tree_to_plant = GB(p1, 0, 8); // We cannot use Extract as min and max are climate specific.
|
||||
|
||||
if (p2 >= MapSize()) return CMD_ERROR;
|
||||
/* Check the tree type. It can be random or some valid value within the current climate */
|
||||
if (p1 != UINT_MAX && p1 - _tree_base_by_landscape[_settings_game.game_creation.landscape] >= _tree_count_by_landscape[_settings_game.game_creation.landscape]) return CMD_ERROR;
|
||||
/* Check the tree type within the current climate */
|
||||
if (tree_to_plant != TREE_INVALID && !IsInsideBS(tree_to_plant, _tree_base_by_landscape[_settings_game.game_creation.landscape], _tree_count_by_landscape[_settings_game.game_creation.landscape])) return CMD_ERROR;
|
||||
|
||||
TileArea ta(tile, p2);
|
||||
TILE_AREA_LOOP(tile, ta) {
|
||||
|
@ -374,12 +375,25 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
continue;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case MP_CLEAR:
|
||||
case MP_CLEAR: {
|
||||
if (IsBridgeAbove(tile)) {
|
||||
msg = STR_ERROR_SITE_UNSUITABLE;
|
||||
continue;
|
||||
}
|
||||
|
||||
TreeType treetype = (TreeType)tree_to_plant;
|
||||
/* Be a bit picky about which trees go where. */
|
||||
if (_settings_game.game_creation.landscape == LT_TROPIC && treetype != TREE_INVALID && (
|
||||
/* No cacti outside the desert */
|
||||
(treetype == TREE_CACTUS && GetTropicZone(tile) != TROPICZONE_DESERT) ||
|
||||
/* No rain forest trees outside the rain forest, except in the editor mode where it makes those tiles rain forest tile */
|
||||
(IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(tile) != TROPICZONE_RAINFOREST && _game_mode != GM_EDITOR) ||
|
||||
/* And no subtropical trees in the desert/rain forest */
|
||||
(IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(tile) != TROPICZONE_NORMAL))) {
|
||||
msg = STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsTileType(tile, MP_CLEAR)) {
|
||||
/* Remove fields or rocks. Note that the ground will get barrened */
|
||||
switch (GetRawClearGround(tile)) {
|
||||
|
@ -401,9 +415,6 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
TreeType treetype;
|
||||
|
||||
treetype = (TreeType)p1;
|
||||
if (treetype == TREE_INVALID) {
|
||||
treetype = GetRandomTreeType(tile, GB(Random(), 24, 8));
|
||||
if (treetype == TREE_INVALID) treetype = TREE_CACTUS;
|
||||
|
@ -414,11 +425,12 @@ CommandCost CmdPlantTree(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
MarkTileDirtyByTile(tile);
|
||||
|
||||
/* When planting rainforest-trees, set tropiczone to rainforest in editor. */
|
||||
if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS))
|
||||
if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) {
|
||||
SetTropicZone(tile, TROPICZONE_RAINFOREST);
|
||||
}
|
||||
}
|
||||
cost.AddCost(_price[PR_BUILD_TREES]);
|
||||
break;
|
||||
} break;
|
||||
|
||||
default:
|
||||
msg = STR_ERROR_SITE_UNSUITABLE;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "company_base.h"
|
||||
#include "command_func.h"
|
||||
#include "sound_func.h"
|
||||
#include "tree_map.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
|
@ -50,7 +51,7 @@ class BuildTreesWindow : public Window
|
|||
{
|
||||
uint16 base; ///< Base tree number used for drawing the window.
|
||||
uint16 count; ///< Number of different trees available.
|
||||
uint tree_to_plant; ///< Tree number to plant, \c UINT_MAX for a random tree.
|
||||
TreeType tree_to_plant; ///< Tree number to plant, \c TREE_INVALID for a random tree.
|
||||
|
||||
public:
|
||||
BuildTreesWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
|
||||
|
@ -105,13 +106,13 @@ public:
|
|||
if (widget - BTW_TYPE_11 >= this->count) break;
|
||||
|
||||
if (HandlePlacePushButton(this, widget, SPR_CURSOR_TREE, HT_RECT, NULL)) {
|
||||
this->tree_to_plant = this->base + widget - BTW_TYPE_11;
|
||||
this->tree_to_plant = (TreeType)(this->base + widget - BTW_TYPE_11);
|
||||
}
|
||||
break;
|
||||
|
||||
case BTW_TYPE_RANDOM: // tree of random type.
|
||||
if (HandlePlacePushButton(this, BTW_TYPE_RANDOM, SPR_CURSOR_TREE, HT_RECT, NULL)) {
|
||||
this->tree_to_plant = UINT_MAX;
|
||||
this->tree_to_plant = TREE_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -22,17 +22,15 @@
|
|||
* offsets from the grfs files. These points to the start of
|
||||
* the tree list for a landscape. See the TREE_COUNT_* enumerations
|
||||
* for the amount of different trees for a specific landscape.
|
||||
*
|
||||
* @note TREE_INVALID may be 0xFF according to the coding style, not -1 (Progman)
|
||||
*/
|
||||
enum TreeType {
|
||||
TREE_INVALID = -1, ///< An invalid tree
|
||||
TREE_TEMPERATE = 0x00, ///< temperate tree
|
||||
TREE_SUB_ARCTIC = 0x0C, ///< tree on a sub_arctic landscape
|
||||
TREE_RAINFOREST = 0x14, ///< tree on the 'green part' on a sub-tropical map
|
||||
TREE_CACTUS = 0x1B, ///< a catus for the 'desert part' on a sub-tropical map
|
||||
TREE_SUB_TROPICAL = 0x1C, ///< tree on a sub-tropical map, non-rainforest, non-desert
|
||||
TREE_TOYLAND = 0x20, ///< tree on a toyland map
|
||||
TREE_INVALID = 0xFF, ///< An invalid tree
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue