tree_cmd.c
changeset 2981 31760b6a88aa
parent 2968 b17821f292cb
child 3003 15a000f2b81d
equal deleted inserted replaced
2980:cd4b945c5517 2981:31760b6a88aa
     7 #include "table/sprites.h"
     7 #include "table/sprites.h"
     8 #include "table/tree_land.h"
     8 #include "table/tree_land.h"
     9 #include "functions.h"
     9 #include "functions.h"
    10 #include "map.h"
    10 #include "map.h"
    11 #include "tile.h"
    11 #include "tile.h"
       
    12 #include "tree.h"
    12 #include "viewport.h"
    13 #include "viewport.h"
    13 #include "command.h"
    14 #include "command.h"
    14 #include "town.h"
    15 #include "town.h"
    15 #include "sound.h"
    16 #include "sound.h"
    16 #include "variables.h"
    17 #include "variables.h"
    17 
    18 
    18 static int GetRandomTreeType(TileIndex tile, uint seed)
    19 static TreeType GetRandomTreeType(TileIndex tile, uint seed)
    19 {
    20 {
    20 	switch (_opt.landscape) {
    21 	switch (_opt.landscape) {
    21 		case LT_NORMAL:
    22 		case LT_NORMAL:
    22 			return seed * 12 >> 8;
    23 			return seed * TR_COUNT_TEMPERATE / 256 + TR_TEMPERATE;
    23 
    24 
    24 		case LT_HILLY:
    25 		case LT_HILLY:
    25 			return (seed >> 5) + 12;
    26 			return seed * TR_COUNT_SUB_ARCTIC / 256 + TR_SUB_ARCTIC;
    26 
    27 
    27 		case LT_DESERT:
    28 		case LT_DESERT:
    28 			switch (GetMapExtraBits(tile)) {
    29 			switch (GetMapExtraBits(tile)) {
    29 				case 0:  return (seed >> 6) + 28;
    30 				case 0:  return seed * TR_COUNT_SUB_TROPICAL / 256 + TR_SUB_TROPICAL;
    30 				case 1:  return (seed > 12) ? -1 : 27;
    31 				case 1:  return (seed > 12) ? TR_INVALID : TR_CACTUS;
    31 				default: return (seed * 7 >> 8) + 20;
    32 				default: return seed * TR_COUNT_RAINFOREST / 256 + TR_RAINFOREST;
    32 			}
    33 			}
    33 
    34 
    34 		default:
    35 		default:
    35 			return (seed * 9 >> 8) + 32;
    36 			return seed * TR_COUNT_TOYLAND / 256 + TR_TOYLAND;
    36 	}
    37 	}
    37 }
    38 }
    38 
    39 
    39 static void PlaceTree(TileIndex tile, uint32 r)
    40 static void PlaceTree(TileIndex tile, uint32 r)
    40 {
    41 {
    41 	int tree = GetRandomTreeType(tile, GB(r, 24, 8));
    42 	TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8));
    42 	byte m5;
    43 
    43 
    44 	if (tree != TR_INVALID) {
    44 	if (tree >= 0) {
       
    45 		SetTileType(tile, MP_TREES);
    45 		SetTileType(tile, MP_TREES);
    46 
    46 		SetTreeType(tile, tree);
    47 		m5 = GB(r, 16, 8);
    47 		SetFenceSE(tile, 0);
    48 		if (GB(m5, 0, 3) == 7) m5--; // there is no growth state 7
    48 		SetFenceSW(tile, 0);
    49 
    49 		SetTreeCount(tile, GB(r, 22, 2));
    50 		_m[tile].m5 = m5 & 0x07;	// growth state;
    50 		SetTreeGrowth(tile, min(GB(r, 16, 3), 6));
    51 		_m[tile].m5 |=  m5 & 0xC0;	// amount of trees
       
    52 
       
    53 		_m[tile].m3 = tree;		// set type of tree
       
    54 		_m[tile].m4 = 0;		// no hedge
       
    55 
    51 
    56 		// above snowline?
    52 		// above snowline?
    57 		if (_opt.landscape == LT_HILLY && GetTileZ(tile) > _opt.snow_line) {
    53 		if (_opt.landscape == LT_HILLY && GetTileZ(tile) > _opt.snow_line) {
    58 			_m[tile].m2 = 0xE0;	// set land type to snow
    54 			SetTreeGroundDensity(tile, TR_SNOW_DESERT, 3);
    59 			_m[tile].m2 |= GB(r, 24, 3); // randomize counter
    55 			SetTreeCounter(tile, GB(r, 24, 3));
    60 		} else {
    56 		} else {
    61 			_m[tile].m2 = GB(r, 24, 5); // randomize counter and ground
    57 			SetTreeGroundDensity(tile, GB(r, 28, 1), 0);
       
    58 			SetTreeCounter(tile, GB(r, 24, 4));
    62 		}
    59 		}
    63 	}
    60 	}
    64 }
    61 }
    65 
    62 
    66 static void DoPlaceMoreTrees(TileIndex tile)
    63 static void DoPlaceMoreTrees(TileIndex tile)
   163 			if (!EnsureNoVehicle(tile)) continue;
   160 			if (!EnsureNoVehicle(tile)) continue;
   164 
   161 
   165 			switch (GetTileType(tile)) {
   162 			switch (GetTileType(tile)) {
   166 				case MP_TREES:
   163 				case MP_TREES:
   167 					// no more space for trees?
   164 					// no more space for trees?
   168 					if (_game_mode != GM_EDITOR && (_m[tile].m5 & 0xC0) == 0xC0) {
   165 					if (_game_mode != GM_EDITOR && GetTreeCount(tile) != 3) {
   169 						_error_message = STR_2803_TREE_ALREADY_HERE;
   166 						_error_message = STR_2803_TREE_ALREADY_HERE;
   170 						continue;
   167 						continue;
   171 					}
   168 					}
   172 
   169 
   173 					if (flags & DC_EXEC) {
   170 					if (flags & DC_EXEC) {
   174 						_m[tile].m5 += 0x40;
   171 						AddTreeCount(tile, 1);
   175 						MarkTileDirtyByTile(tile);
   172 						MarkTileDirtyByTile(tile);
   176 					}
   173 					}
   177 					// 2x as expensive to add more trees to an existing tile
   174 					// 2x as expensive to add more trees to an existing tile
   178 					cost += _price.build_trees * 2;
   175 					cost += _price.build_trees * 2;
   179 					break;
   176 					break;
   189 						case CL_ROCKS:  cost += _price.clear_2; break;
   186 						case CL_ROCKS:  cost += _price.clear_2; break;
   190 						default: break;
   187 						default: break;
   191 					}
   188 					}
   192 
   189 
   193 					if (flags & DC_EXEC) {
   190 					if (flags & DC_EXEC) {
   194 						int treetype;
   191 						TreeType treetype;
   195 						int m2;
       
   196 
   192 
   197 						if (_game_mode != GM_EDITOR && _current_player < MAX_PLAYERS) {
   193 						if (_game_mode != GM_EDITOR && _current_player < MAX_PLAYERS) {
   198 							Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
   194 							Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
   199 							if (t != NULL)
   195 							if (t != NULL)
   200 								ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM);
   196 								ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM);
   201 						}
   197 						}
   202 
   198 
       
   199 						treetype = p1;
       
   200 						if (treetype == TR_INVALID) {
       
   201 							treetype = GetRandomTreeType(tile, GB(Random(), 24, 8));
       
   202 							if (treetype == TR_INVALID) treetype = TR_CACTUS;
       
   203 						}
       
   204 
   203 						switch (GetClearGround(tile)) {
   205 						switch (GetClearGround(tile)) {
   204 							case CL_ROUGH: m2 = 16; break;
   206 							case CL_ROUGH: SetTreeGroundDensity(tile, TR_ROUGH, 0); break;
   205 							case CL_SNOW:  m2 = GetClearDensity(tile) << 6 | 0x20; break;
   207 							case CL_SNOW:  SetTreeGroundDensity(tile, TR_SNOW_DESERT, GetClearDensity(tile)); break;
   206 							default:       m2 = 0; break;
   208 							default:       SetTreeGroundDensity(tile, TR_GRASS, 0); break;
   207 						}
   209 						}
   208 
   210 						SetTreeCounter(tile, 0);
   209 						treetype = p1;
   211 
   210 						if (treetype == -1) {
   212 						SetTileType(tile, MP_TREES);
   211 							treetype = GetRandomTreeType(tile, GB(Random(), 24, 8));
   213 						SetTreeType(tile, treetype);
   212 							if (treetype == -1) treetype = 27;
   214 						SetFenceSE(tile, 0);
   213 						}
   215 						SetFenceSW(tile, 0);
   214 
   216 						SetTreeCount(tile, 0);
   215 						ModifyTile(tile,
   217 						SetTreeGrowth(tile, _game_mode == GM_EDITOR ? 3 : 0);
   216 							MP_SETTYPE(MP_TREES) |
   218 
   217 							MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5,
   219 						if (_game_mode == GM_EDITOR && IS_INT_INSIDE(treetype, TR_RAINFOREST, TR_CACTUS))
   218 							m2, /* map2 */
       
   219 							treetype, /* map3lo */
       
   220 							_game_mode == GM_EDITOR ? 3 : 0 /* map5 */
       
   221 						);
       
   222 
       
   223 						if (_game_mode == GM_EDITOR && IS_BYTE_INSIDE(treetype, 0x14, 0x1B))
       
   224 							SetMapExtraBits(tile, 2);
   220 							SetMapExtraBits(tile, 2);
   225 					}
   221 					}
   226 					cost += _price.build_trees;
   222 					cost += _price.build_trees;
   227 					break;
   223 					break;
   228 
   224 
   241 	byte x,y;
   237 	byte x,y;
   242 } TreeListEnt;
   238 } TreeListEnt;
   243 
   239 
   244 static void DrawTile_Trees(TileInfo *ti)
   240 static void DrawTile_Trees(TileInfo *ti)
   245 {
   241 {
   246 	uint16 m2;
       
   247 	const uint32 *s;
   242 	const uint32 *s;
   248 	const TreePos* d;
   243 	const TreePos* d;
   249 	byte z;
   244 	byte z;
   250 
   245 
   251 	m2 = _m[ti->tile].m2;
   246 	switch (GetTreeGround(ti->tile)) {
   252 
   247 		case TR_GRASS: DrawClearLandTile(ti, 3); break;
   253 	if ((m2 & 0x30) == 0) {
   248 		case TR_ROUGH: DrawHillyLandTile(ti); break;
   254 		DrawClearLandTile(ti, 3);
   249 		default:       DrawGroundSprite(_tree_sprites_1[GetTreeDensity(ti->tile)] + _tileh_to_sprite[ti->tileh]); break;
   255 	} else if ((m2 & 0x30) == 0x20) {
       
   256 		DrawGroundSprite(_tree_sprites_1[m2 >> 6] + _tileh_to_sprite[ti->tileh]);
       
   257 	} else {
       
   258 		DrawHillyLandTile(ti);
       
   259 	}
   250 	}
   260 
   251 
   261 	DrawClearLandFence(ti);
   252 	DrawClearLandFence(ti);
   262 
   253 
   263 	z = ti->z;
   254 	z = ti->z;
   278 		tmp = ROR(tmp, 1);
   269 		tmp = ROR(tmp, 1);
   279 		tmp += ti->y;
   270 		tmp += ti->y;
   280 
   271 
   281 		d = _tree_layout_xy[GB(tmp, 4, 2)];
   272 		d = _tree_layout_xy[GB(tmp, 4, 2)];
   282 
   273 
   283 		index = GB(tmp, 6, 2) + (_m[ti->tile].m3 << 2);
   274 		index = GB(tmp, 6, 2) + (GetTreeType(ti->tile) << 2);
   284 
   275 
   285 		/* different tree styles above one of the grounds */
   276 		/* different tree styles above one of the grounds */
   286 		if ((m2 & 0xB0) == 0xA0 && index >= 48 && index < 80)
   277 		if (GetTreeGround(ti->tile) == TR_SNOW_DESERT &&
   287 			index += 164 - 48;
   278 				GetTreeDensity(ti->tile) >= 2 &&
       
   279 				IS_INT_INSIDE(index, TR_SUB_ARCTIC << 2, TR_RAINFOREST << 2)) {
       
   280 			index += 164 - (TR_SUB_ARCTIC << 2);
       
   281 		}
   288 
   282 
   289 		assert(index < lengthof(_tree_layout_sprite));
   283 		assert(index < lengthof(_tree_layout_sprite));
   290 		s = _tree_layout_sprite[index];
   284 		s = _tree_layout_sprite[index];
   291 	}
   285 	}
   292 
   286 
   350 		Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
   344 		Town *t = ClosestTownFromTile(tile, _patches.dist_local_authority);
   351 		if (t != NULL)
   345 		if (t != NULL)
   352 			ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM);
   346 			ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM);
   353 	}
   347 	}
   354 
   348 
   355 	num = GB(_m[tile].m5, 6, 2) + 1;
   349 	num = GetTreeCount(tile) + 1;
   356 	if (IS_INT_INSIDE(_m[tile].m3, 20, 26 + 1)) num *= 4;
   350 	if (IS_INT_INSIDE(GetTreeType(tile), TR_RAINFOREST, TR_CACTUS)) num *= 4;
   357 
   351 
   358 	if (flags & DC_EXEC) DoClearSquare(tile);
   352 	if (flags & DC_EXEC) DoClearSquare(tile);
   359 
   353 
   360 	return num * _price.remove_trees;
   354 	return num * _price.remove_trees;
   361 }
   355 }
   365 	/* not used */
   359 	/* not used */
   366 }
   360 }
   367 
   361 
   368 static void GetTileDesc_Trees(TileIndex tile, TileDesc *td)
   362 static void GetTileDesc_Trees(TileIndex tile, TileDesc *td)
   369 {
   363 {
   370 	byte b;
   364 	TreeType tt = GetTreeType(tile);
   371 	StringID str;
   365 
       
   366 	if (IS_INT_INSIDE(tt, TR_RAINFOREST, TR_CACTUS)) {
       
   367 		td->str = STR_280F_RAINFOREST;
       
   368 	} else if (tt == TR_CACTUS) {
       
   369 		td->str = STR_2810_CACTUS_PLANTS;
       
   370 	} else {
       
   371 		td->str = STR_280E_TREES;
       
   372 	}
   372 
   373 
   373 	td->owner = GetTileOwner(tile);
   374 	td->owner = GetTileOwner(tile);
   374 
       
   375 	b = _m[tile].m3;
       
   376 	(str=STR_2810_CACTUS_PLANTS, b==0x1B) ||
       
   377 	(str=STR_280F_RAINFOREST, IS_BYTE_INSIDE(b, 0x14, 0x1A+1)) ||
       
   378 	(str=STR_280E_TREES, true);
       
   379 	td->str = str;
       
   380 }
   375 }
   381 
   376 
   382 static void AnimateTile_Trees(TileIndex tile)
   377 static void AnimateTile_Trees(TileIndex tile)
   383 {
   378 {
   384 	/* not used */
   379 	/* not used */
   385 }
   380 }
   386 
   381 
   387 static void TileLoopTreesDesert(TileIndex tile)
   382 static void TileLoopTreesDesert(TileIndex tile)
   388 {
   383 {
   389 	static const SoundFx forest_sounds[] = {
   384 	switch (GetMapExtraBits(tile)) {
   390 		SND_42_LOON_BIRD,
   385 		case 1:
   391 		SND_43_LION,
   386 			if (GetTreeGround(tile) != TR_SNOW_DESERT) {
   392 		SND_44_MONKEYS,
   387 				SetTreeGroundDensity(tile, TR_SNOW_DESERT, 3);
   393 		SND_48_DISTANT_BIRD
   388 				MarkTileDirtyByTile(tile);
   394 	};
   389 			}
   395 
   390 			break;
   396 	byte b = GetMapExtraBits(tile);
   391 
   397 
   392 		case 2: {
   398 	if (b == 2) {
   393 			static const SoundFx forest_sounds[] = {
   399 		uint32 r = Random();
   394 				SND_42_LOON_BIRD,
   400 
   395 				SND_43_LION,
   401 		if (CHANCE16I(1, 200, r)) SndPlayTileFx(forest_sounds[GB(r, 16, 2)], tile);
   396 				SND_44_MONKEYS,
   402 	} else if (b == 1) {
   397 				SND_48_DISTANT_BIRD
   403 		if (GB(_m[tile].m2, 4, 2) != 2) {
   398 			};
   404 			SB(_m[tile].m2, 4, 2, 2);
   399 			uint32 r = Random();
   405 			SB(_m[tile].m2, 6, 2, 3);
   400 
   406 			MarkTileDirtyByTile(tile);
   401 			if (CHANCE16I(1, 200, r)) SndPlayTileFx(forest_sounds[GB(r, 16, 2)], tile);
       
   402 			break;
   407 		}
   403 		}
   408 	}
   404 	}
   409 }
   405 }
   410 
   406 
   411 static void TileLoopTreesAlps(TileIndex tile)
   407 static void TileLoopTreesAlps(TileIndex tile)
   412 {
   408 {
   413 	byte tmp, m2;
   409 	int k = GetTileZ(tile) - _opt.snow_line;
   414 	int k;
       
   415 
       
   416 	/* distance from snow line, in steps of 8 */
       
   417 	k = GetTileZ(tile) - _opt.snow_line;
       
   418 
       
   419 	tmp = _m[tile].m2 & 0xF0;
       
   420 
   410 
   421 	if (k < -8) {
   411 	if (k < -8) {
   422 		if ((tmp & 0x30) != 0x20) return;
   412 		if (GetTreeGround(tile) != TR_SNOW_DESERT) return;
   423 		m2 = 0; // no snow
   413 		SetTreeGroundDensity(tile, TR_GRASS, 0);
   424 	} else if (k == -8) {
       
   425 		m2 = 0x20; // 1/4 snow
       
   426 		if (tmp == m2) return;
       
   427 	} else if (k == 0) {
       
   428 		m2 = 0x60;// 1/2 snow
       
   429 		if (tmp == m2) return;
       
   430 	} else if (k == 8) {
       
   431 		m2 = 0xA0; // 3/4 snow
       
   432 		if (tmp == m2) return;
       
   433 	} else {
   414 	} else {
   434 		if (tmp == 0xE0) {
   415 		uint density = min((uint)(k + 8) / 8, 3);
   435 			uint32 r = Random();
   416 
   436 			if (CHANCE16I(1, 200, r)) {
   417 		if (GetTreeGround(tile) != TR_SNOW_DESERT || GetTreeDensity(tile) != density) {
   437 				SndPlayTileFx((r & 0x80000000) ? SND_39_HEAVY_WIND : SND_34_WIND, tile);
   418 			SetTreeGroundDensity(tile, TR_SNOW_DESERT, density);
       
   419 		} else {
       
   420 			if (GetTreeDensity(tile) == 3) {
       
   421 				uint32 r = Random();
       
   422 				if (CHANCE16I(1, 200, r)) {
       
   423 					SndPlayTileFx((r & 0x80000000) ? SND_39_HEAVY_WIND : SND_34_WIND, tile);
       
   424 				}
   438 			}
   425 			}
   439 			return;
   426 			return;
   440 		} else {
   427 		}
   441 			m2 = 0xE0; // full snow
   428 	}
   442 		}
       
   443 	}
       
   444 
       
   445 	_m[tile].m2 &= 0xF;
       
   446 	_m[tile].m2 |= m2;
       
   447 	MarkTileDirtyByTile(tile);
   429 	MarkTileDirtyByTile(tile);
   448 }
   430 }
   449 
   431 
   450 static void TileLoop_Trees(TileIndex tile)
   432 static void TileLoop_Trees(TileIndex tile)
   451 {
   433 {
   452 	byte m5;
       
   453 
       
   454 	static const TileIndexDiffC _tileloop_trees_dir[] = {
   434 	static const TileIndexDiffC _tileloop_trees_dir[] = {
   455 		{-1, -1},
   435 		{-1, -1},
   456 		{ 0, -1},
   436 		{ 0, -1},
   457 		{ 1, -1},
   437 		{ 1, -1},
   458 		{-1,  0},
   438 		{-1,  0},
   460 		{-1,  1},
   440 		{-1,  1},
   461 		{ 0,  1},
   441 		{ 0,  1},
   462 		{ 1,  1}
   442 		{ 1,  1}
   463 	};
   443 	};
   464 
   444 
   465 	if (_opt.landscape == LT_DESERT) {
   445 	switch (_opt.landscape) {
   466 		TileLoopTreesDesert(tile);
   446 		case LT_DESERT: TileLoopTreesDesert(tile); break;
   467 	} else if (_opt.landscape == LT_HILLY) {
   447 		case LT_HILLY:  TileLoopTreesAlps(tile);   break;
   468 		TileLoopTreesAlps(tile);
       
   469 	}
   448 	}
   470 
   449 
   471 	TileLoopClearHelper(tile);
   450 	TileLoopClearHelper(tile);
   472 
   451 
   473 	/* increase counter */
   452 	if (GetTreeCounter(tile) < 15) {
   474 	AB(_m[tile].m2, 0, 4, 1);
   453 		AddTreeCounter(tile, 1);
   475 	if (GB(_m[tile].m2, 0, 4) != 0) return;
   454 		return;
   476 
   455 	}
   477 	m5 = _m[tile].m5;
   456 	SetTreeCounter(tile, 0);
   478 	if (GB(m5, 0, 3) == 3) {
   457 
   479 		/* regular sized tree */
   458 	switch (GetTreeGrowth(tile)) {
   480 		if (_opt.landscape == LT_DESERT && _m[tile].m3 != 0x1B && GetMapExtraBits(tile) == 1) {
   459 		case 3: /* regular sized tree */
   481 			m5++; /* start destructing */
   460 			if (_opt.landscape == LT_DESERT && GetTreeType(tile) != TR_CACTUS && GetMapExtraBits(tile) == 1) {
   482 		} else {
   461 				AddTreeGrowth(tile, 1);
   483 			switch (GB(Random(), 0, 3)) {
   462 			} else {
   484 			case 0: /* start destructing */
   463 				switch (GB(Random(), 0, 3)) {
   485 				m5++;
   464 					case 0: /* start destructing */
   486 				break;
   465 						AddTreeGrowth(tile, 1);
   487 
   466 						break;
   488 			case 1: /* add a tree */
   467 
   489 				if (m5 < 0xC0) {
   468 					case 1: /* add a tree */
   490 					m5 = (m5 + 0x40) & ~7;
   469 						if (GetTreeCount(tile) < 3) {
   491 					break;
   470 							AddTreeCount(tile, 1);
       
   471 							SetTreeGrowth(tile, 0);
       
   472 							break;
       
   473 						}
       
   474 						/* FALL THROUGH */
       
   475 
       
   476 					case 2: { /* add a neighbouring tree */
       
   477 						TreeType treetype = GetTreeType(tile);
       
   478 
       
   479 						tile += ToTileIndexDiff(_tileloop_trees_dir[Random() & 7]);
       
   480 
       
   481 						if (!IsTileType(tile, MP_CLEAR)) return;
       
   482 
       
   483 						switch (GetClearGround(tile)) {
       
   484 							case CL_GRASS:
       
   485 								if (GetClearDensity(tile) != 3) return;
       
   486 								SetTreeGroundDensity(tile, TR_GRASS, 0);
       
   487 								break;
       
   488 
       
   489 							case CL_ROUGH: SetTreeGroundDensity(tile, TR_ROUGH, 0); break;
       
   490 							case CL_SNOW:  SetTreeGroundDensity(tile, TR_SNOW_DESERT, GetClearDensity(tile)); break;
       
   491 							default: return;
       
   492 						}
       
   493 						SetTreeCounter(tile, 0);
       
   494 
       
   495 						SetTileType(tile, MP_TREES);
       
   496 						SetTreeType(tile, treetype);
       
   497 						SetFenceSE(tile, 0);
       
   498 						SetFenceSW(tile, 0);
       
   499 						SetTreeCount(tile, 0);
       
   500 						SetTreeGrowth(tile, 0);
       
   501 						break;
       
   502 					}
       
   503 
       
   504 					default:
       
   505 						return;
   492 				}
   506 				}
   493 				/* fall through */
   507 			}
   494 
   508 			break;
   495 			case 2: { /* add a neighbouring tree */
   509 
   496 				byte m3 = _m[tile].m3;
   510 		case 6: /* final stage of tree destruction */
   497 
   511 			if (GetTreeCount(tile) > 0) {
   498 				tile += ToTileIndexDiff(_tileloop_trees_dir[Random() & 7]);
   512 				/* more than one tree, delete it */
   499 
   513 				AddTreeCount(tile, -1);
   500 				if (!IsTileType(tile, MP_CLEAR)) return;
   514 				SetTreeGrowth(tile, 3);
   501 
   515 			} else {
   502 				switch (GetClearGround(tile)) {
   516 				/* just one tree, change type into MP_CLEAR */
   503 					case CL_GRASS:
   517 				SetTileType(tile, MP_CLEAR);
   504 						if (GetClearDensity(tile) != 3) return;
   518 				SetTileOwner(tile, OWNER_NONE);
   505 						_m[tile].m2 = 0;
   519 				switch (GetTreeGround(tile)) {
   506 						break;
   520 					case TR_GRASS: SetClearGroundDensity(tile, CL_GRASS, 3); break;
   507 
   521 					case TR_ROUGH: SetClearGroundDensity(tile, CL_ROUGH, 3); break;
   508 					case CL_ROUGH: _m[tile].m2 = 0x10; break;
   522 					default:       SetClearGroundDensity(tile, CL_SNOW, GetTreeDensity(tile)); break;
   509 					case CL_SNOW:  _m[tile].m2 = GetClearDensity(tile) << 6 | 0x20; break;
       
   510 					default: return;
       
   511 				}
   523 				}
   512 
       
   513 				_m[tile].m3 = m3;
       
   514 				_m[tile].m4 = 0;
       
   515 				SetTileType(tile, MP_TREES);
       
   516 
       
   517 				m5 = 0;
       
   518 				break;
       
   519 			}
   524 			}
   520 
   525 			break;
   521 			default:
   526 
   522 				return;
   527 		default:
   523 			}
   528 			AddTreeGrowth(tile, 1);
   524 		}
   529 			break;
   525 	} else if (GB(m5, 0, 3) == 6) {
   530 	}
   526 		/* final stage of tree destruction */
   531 
   527 		if (GB(m5, 6, 2) != 0) {
       
   528 			/* more than one tree, delete it? */
       
   529 			m5 = ((m5 - 6) - 0x40) + 3;
       
   530 		} else {
       
   531 			/* just one tree, change type into MP_CLEAR */
       
   532 			SetTileType(tile, MP_CLEAR);
       
   533 			SetTileOwner(tile, OWNER_NONE);
       
   534 			switch (_m[tile].m2 & 0x30) {
       
   535 				case 0x00: SetClearGroundDensity(tile, CL_GRASS, 3); break;
       
   536 				case 0x10: SetClearGroundDensity(tile, CL_ROUGH, 3); break;
       
   537 				default:   SetClearGroundDensity(tile, CL_SNOW, GB(_m[tile].m2, 6, 2)); break;
       
   538 			}
       
   539 			MarkTileDirtyByTile(tile);
       
   540 			return;
       
   541 		}
       
   542 	} else {
       
   543 		/* in the middle of a transition, change to next */
       
   544 		m5++;
       
   545 	}
       
   546 
       
   547 	_m[tile].m5 = m5;
       
   548 	MarkTileDirtyByTile(tile);
   532 	MarkTileDirtyByTile(tile);
   549 }
   533 }
   550 
   534 
   551 void OnTick_Trees(void)
   535 void OnTick_Trees(void)
   552 {
   536 {
   558 	/* place a tree at a random rainforest spot */
   542 	/* place a tree at a random rainforest spot */
   559 	if (_opt.landscape == LT_DESERT &&
   543 	if (_opt.landscape == LT_DESERT &&
   560 			(r = Random(), tile = RandomTileSeed(r), GetMapExtraBits(tile) == 2) &&
   544 			(r = Random(), tile = RandomTileSeed(r), GetMapExtraBits(tile) == 2) &&
   561 			IsTileType(tile, MP_CLEAR) &&
   545 			IsTileType(tile, MP_CLEAR) &&
   562 			(ct = GetClearGround(tile), ct == CL_GRASS || ct == CL_ROUGH) &&
   546 			(ct = GetClearGround(tile), ct == CL_GRASS || ct == CL_ROUGH) &&
   563 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) >= 0) {
   547 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TR_INVALID) {
   564 
   548 		SetTileType(tile, MP_TREES);
   565 		ModifyTile(tile,
   549 		SetTreeGroundDensity(tile, ct == CL_ROUGH ? TR_ROUGH : TR_GRASS, 0);
   566 			MP_SETTYPE(MP_TREES) |
   550 		SetTreeCounter(tile, 0);
   567 			MP_MAP2 | MP_MAP3LO | MP_MAP3HI | MP_MAP5,
   551 		SetTreeType(tile, tree);
   568 			(ct == CL_ROUGH ? 0x10 : 0),
   552 		SetTreeCount(tile, 0);
   569 			tree,
   553 		SetTreeGrowth(tile, 0);
   570 			_m[tile].m4 & ~3,
       
   571 			0
       
   572 		);
       
   573 	}
   554 	}
   574 
   555 
   575 	// byte underflow
   556 	// byte underflow
   576 	if (--_trees_tick_ctr != 0) return;
   557 	if (--_trees_tick_ctr != 0) return;
   577 
   558 
   578 	/* place a tree at a random spot */
   559 	/* place a tree at a random spot */
   579 	r = Random();
   560 	r = Random();
   580 	tile = TILE_MASK(r);
   561 	tile = TILE_MASK(r);
   581 	if (IsTileType(tile, MP_CLEAR) &&
   562 	if (IsTileType(tile, MP_CLEAR) &&
   582 			(ct = GetClearGround(tile), ct == CL_GRASS || ct == CL_ROUGH || ct == CL_SNOW) &&
   563 			(ct = GetClearGround(tile), ct == CL_GRASS || ct == CL_ROUGH || ct == CL_SNOW) &&
   583 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) >= 0) {
   564 			(tree = GetRandomTreeType(tile, GB(r, 24, 8))) != TR_INVALID) {
   584 		int m2;
       
   585 
       
   586 		switch (ct) {
   565 		switch (ct) {
   587 			case CL_GRASS: m2 = 0; break;
   566 			case CL_GRASS: SetTreeGroundDensity(tile, TR_GRASS, 0); break;
   588 			case CL_ROUGH: m2 = 0x10; break;
   567 			case CL_ROUGH: SetTreeGroundDensity(tile, TR_ROUGH, 0); break;
   589 			default:       m2 = (GetClearDensity(tile) << 6) | 0x20; break;
   568 			default:       SetTreeGroundDensity(tile, TR_SNOW_DESERT, GetClearDensity(tile)); break;
   590 		}
   569 		}
   591 
   570 		SetTreeCounter(tile, 0);
   592 		ModifyTile(tile,
   571 		SetTileType(tile, MP_TREES);
   593 			MP_SETTYPE(MP_TREES) |
   572 		SetTreeType(tile, tree);
   594 			MP_MAP2 | MP_MAP3LO | MP_MAP3HI | MP_MAP5,
   573 		SetTreeCount(tile, 0);
   595 			m2,
   574 		SetTreeGrowth(tile, 0);
   596 			tree,
       
   597 			_m[tile].m4 & ~3,
       
   598 			0
       
   599 		);
       
   600 	}
   575 	}
   601 }
   576 }
   602 
   577 
   603 static void ClickTile_Trees(TileIndex tile)
   578 static void ClickTile_Trees(TileIndex tile)
   604 {
   579 {