src/industry_cmd.cpp
branchNewGRF_ports
changeset 6720 35756db7e577
parent 6719 4cc327ad39d5
child 6725 23339968083f
equal deleted inserted replaced
6719:4cc327ad39d5 6720:35756db7e577
    28 #include "genworld.h"
    28 #include "genworld.h"
    29 #include "date.h"
    29 #include "date.h"
    30 #include "water_map.h"
    30 #include "water_map.h"
    31 #include "tree_map.h"
    31 #include "tree_map.h"
    32 #include "cargotype.h"
    32 #include "cargotype.h"
       
    33 #include "newgrf_industries.h"
       
    34 #include "newgrf_industrytiles.h"
       
    35 #include "newgrf_callbacks.h"
    33 
    36 
    34 void ShowIndustryViewWindow(int industry);
    37 void ShowIndustryViewWindow(int industry);
    35 void BuildOilRig(TileIndex tile);
    38 void BuildOilRig(TileIndex tile);
    36 
    39 
    37 static byte _industry_sound_ctr;
    40 static byte _industry_sound_ctr;
    38 static TileIndex _industry_sound_tile;
    41 static TileIndex _industry_sound_tile;
       
    42 
       
    43 int _total_industries;                      //general counter
       
    44 uint16 _industry_counts[NUM_INDUSTRYTYPES]; // Number of industries per type ingame
       
    45 
       
    46 const Industry **_industry_sort;
       
    47 bool _industry_sort_dirty;
    39 
    48 
    40 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
    49 IndustrySpec _industry_specs[NUM_INDUSTRYTYPES];
    41 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
    50 IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES];
    42 
    51 
    43 /** This function initialize the spec arrays of both
    52 /** This function initialize the spec arrays of both
   139 			}
   148 			}
   140 		} END_TILE_LOOP(tile_cur, 42, 42, i->xy - TileDiff(21, 21))
   149 		} END_TILE_LOOP(tile_cur, 42, 42, i->xy - TileDiff(21, 21))
   141 	}
   150 	}
   142 
   151 
   143 	_industry_sort_dirty = true;
   152 	_industry_sort_dirty = true;
   144 	_total_industries--;
   153 	DecIndustryTypeCount(i->type);
       
   154 
   145 	DeleteSubsidyWithIndustry(i->index);
   155 	DeleteSubsidyWithIndustry(i->index);
   146 	DeleteWindowById(WC_INDUSTRY_VIEW, i->index);
   156 	DeleteWindowById(WC_INDUSTRY_VIEW, i->index);
   147 	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
   157 	InvalidateWindow(WC_INDUSTRY_DIRECTORY, 0);
   148 }
   158 }
   149 
   159 
   232 	IndustryDrawCoalPlantSparks,
   242 	IndustryDrawCoalPlantSparks,
   233 };
   243 };
   234 
   244 
   235 static void DrawTile_Industry(TileInfo *ti)
   245 static void DrawTile_Industry(TileInfo *ti)
   236 {
   246 {
   237 	const IndustryGfx gfx = GetIndustryGfx(ti->tile);
   247 	IndustryGfx gfx = GetIndustryGfx(ti->tile);
   238 	const Industry *ind;
   248 	Industry *ind = GetIndustryByTile(ti->tile);
       
   249 	const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
   239 	const DrawBuildingsTileStruct *dits;
   250 	const DrawBuildingsTileStruct *dits;
   240 	byte z;
   251 	byte z;
   241 	SpriteID image;
   252 	SpriteID image;
   242 	SpriteID pal;
   253 	SpriteID pal;
   243 
   254 
   244 	/* Pointer to industry */
       
   245 	ind = GetIndustryByTile(ti->tile);
       
   246 
       
   247 	/* Retrieve pointer to the draw industry tile struct */
   255 	/* Retrieve pointer to the draw industry tile struct */
   248 	dits = &_industry_draw_tile_data[gfx << 2 | (GetIndustryTileSpec(gfx)->anim_state ?
   256 	if (gfx >= NEW_INDUSTRYTILEOFFSET) {
       
   257 		/* Draw the tile using the specialized method of newgrf industrytile.
       
   258 		 * DrawNewIndustry will return false if ever the resolver could not
       
   259 		 * find any sprite to display.  So in this case, we will jump on the
       
   260 		 * substitute gfx instead. */
       
   261 		if (indts->grf_prop.spritegroup != NULL && DrawNewIndustryTile(ti, ind, gfx, indts)) {
       
   262 			return;
       
   263 		} else {
       
   264 			/* No sprite group (or no valid one) found, meaning no graphics associated.
       
   265 			 * Use the substitute one instead */
       
   266 			gfx = indts->grf_prop.subst_id;
       
   267 			/* And point the industrytile spec accordingly */
       
   268 			indts = GetIndustryTileSpec(indts->grf_prop.subst_id);
       
   269 		}
       
   270 	}
       
   271 
       
   272 	dits = &_industry_draw_tile_data[gfx << 2 | (indts->anim_state ?
   249 			GetIndustryAnimationState(ti->tile) & 3 :
   273 			GetIndustryAnimationState(ti->tile) & 3 :
   250 			GetIndustryConstructionStage(ti->tile))];
   274 			GetIndustryConstructionStage(ti->tile))];
   251 
   275 
   252 	image = dits->ground.sprite;
   276 	image = dits->ground.sprite;
   253 	if (HASBIT(image, PALETTE_MODIFIER_COLOR) && dits->ground.pal == PAL_NONE) {
   277 	if (HASBIT(image, PALETTE_MODIFIER_COLOR) && dits->ground.pal == PAL_NONE) {
   257 	}
   281 	}
   258 
   282 
   259 	z = ti->z;
   283 	z = ti->z;
   260 	/* Add bricks below the industry? */
   284 	/* Add bricks below the industry? */
   261 	if (ti->tileh != SLOPE_FLAT) {
   285 	if (ti->tileh != SLOPE_FLAT) {
   262 		AddSortableSpriteToDraw(SPR_FOUNDATION_BASE + ti->tileh, PAL_NONE, ti->x, ti->y, 16, 16, 7, z);
   286 		DrawFoundation(ti, ti->tileh);
   263 		AddChildSpriteScreen(image, pal, 31, 1);
       
   264 		z += TILE_HEIGHT;
   287 		z += TILE_HEIGHT;
   265 	} else {
   288 	}
   266 		/* Else draw regular ground */
   289 
   267 		DrawGroundSprite(image, pal);
   290 	DrawGroundSprite(image, pal);
   268 	}
       
   269 
   291 
   270 	/* Add industry on top of the ground? */
   292 	/* Add industry on top of the ground? */
   271 	image = dits->building.sprite;
   293 	image = dits->building.sprite;
   272 	if (image != 0) {
   294 	if (image != 0) {
   273 		if (HASBIT(_transparent_opt, TO_INDUSTRIES)) {
   295 		if (HASBIT(_transparent_opt, TO_INDUSTRIES)) {
   274 			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
   296 			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
   275 			pal = PALETTE_TO_TRANSPARENT;
   297 			pal = PALETTE_TO_TRANSPARENT;
       
   298 		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR) && dits->building.pal == PAL_NONE) {
       
   299 			pal = GENERAL_SPRITE_COLOR(ind->random_color);
   276 		} else {
   300 		} else {
   277 			pal = dits->building.pal;
   301 			pal = dits->building.pal;
   278 		}
   302 		}
   279 
   303 
   280 		AddSortableSpriteToDraw(image, pal,
   304 		AddSortableSpriteToDraw(image, pal,
   304 	return SLOPE_FLAT;
   328 	return SLOPE_FLAT;
   305 }
   329 }
   306 
   330 
   307 static void GetAcceptedCargo_Industry(TileIndex tile, AcceptedCargo ac)
   331 static void GetAcceptedCargo_Industry(TileIndex tile, AcceptedCargo ac)
   308 {
   332 {
   309 	const IndustryTileSpec *itspec = GetIndustryTileSpec(GetIndustryGfx(tile));
   333 	IndustryGfx gfx = GetIndustryGfx(tile);
   310 	CargoID a;
   334 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
       
   335 
       
   336 	/* When we have to use a callback, we put our data in the next two variables */
       
   337 	CargoID raw_accepts_cargo[lengthof(itspec->accepts_cargo)];
       
   338 	uint8 raw_acceptance[lengthof(itspec->acceptance)];
       
   339 
       
   340 	/* And then these will always point to a same sized array with the required data */
       
   341 	const CargoID *accepts_cargo = itspec->accepts_cargo;
       
   342 	const uint8 *acceptance = itspec->acceptance;
       
   343 
       
   344 	if (HASBIT(itspec->callback_flags, CBM_INDT_ACCEPT_CARGO)) {
       
   345 		uint16 res = GetIndustryTileCallback(CBID_INDTILE_ACCEPT_CARGO, 0, 0, gfx, GetIndustryByTile(tile), tile);
       
   346 		if (res != CALLBACK_FAILED) {
       
   347 			accepts_cargo = raw_accepts_cargo;
       
   348 			for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_accepts_cargo[i] = GetCargoTranslation(GB(res, i * 5, 5), itspec->grf_prop.grffile);
       
   349 		}
       
   350 	}
       
   351 
       
   352 	if (HASBIT(itspec->callback_flags, CBM_INDT_CARGO_ACCEPTANCE)) {
       
   353 		uint16 res = GetIndustryTileCallback(CBID_INDTILE_CARGO_ACCEPTANCE, 0, 0, gfx, GetIndustryByTile(tile), tile);
       
   354 		if (res != CALLBACK_FAILED) {
       
   355 			acceptance = raw_acceptance;
       
   356 			for (uint i = 0; i < lengthof(itspec->accepts_cargo); i++) raw_acceptance[i] = GB(res, i * 4, 4);
       
   357 		}
       
   358 	}
   311 
   359 
   312 	for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
   360 	for (byte i = 0; i < lengthof(itspec->accepts_cargo); i++) {
   313 		a = itspec->accepts_cargo[i];
   361 		CargoID a = accepts_cargo[i];
   314 		if (a != CT_INVALID) ac[a] = itspec->acceptance[i];
   362 		if (a != CT_INVALID) ac[a] = acceptance[i];
   315 	}
   363 	}
   316 }
   364 }
   317 
   365 
   318 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
   366 static void GetTileDesc_Industry(TileIndex tile, TileDesc *td)
   319 {
   367 {
   325 		SetDParamX(td->dparam, 0, td->str);
   373 		SetDParamX(td->dparam, 0, td->str);
   326 		td->str = STR_2058_UNDER_CONSTRUCTION;
   374 		td->str = STR_2058_UNDER_CONSTRUCTION;
   327 	}
   375 	}
   328 }
   376 }
   329 
   377 
   330 static int32 ClearTile_Industry(TileIndex tile, byte flags)
   378 static CommandCost ClearTile_Industry(TileIndex tile, byte flags)
   331 {
   379 {
   332 	Industry *i = GetIndustryByTile(tile);
   380 	Industry *i = GetIndustryByTile(tile);
   333 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
   381 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
   334 
   382 
   335 	/* water can destroy industries
   383 	/* water can destroy industries
   343 		SetDParam(0, indspec->name);
   391 		SetDParam(0, indspec->name);
   344 		return_cmd_error(STR_4800_IN_THE_WAY);
   392 		return_cmd_error(STR_4800_IN_THE_WAY);
   345 	}
   393 	}
   346 
   394 
   347 	if (flags & DC_EXEC) DeleteIndustry(i);
   395 	if (flags & DC_EXEC) DeleteIndustry(i);
   348 	return 0;
   396 	return CommandCost();
   349 }
   397 }
   350 
   398 
   351 static void TransportIndustryGoods(TileIndex tile)
   399 static void TransportIndustryGoods(TileIndex tile)
   352 {
   400 {
   353 	Industry *i = GetIndustryByTile(tile);
   401 	Industry *i = GetIndustryByTile(tile);
   354 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
   402 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
   355 	uint cw, am;
   403 	uint cw, am;
   356 
   404 
   357 	cw = min(i->cargo_waiting[0], 255);
   405 	cw = min(i->produced_cargo_waiting[0], 255);
   358 	if (cw > indspec->minimal_cargo/* && i->produced_cargo[0] != 0xFF*/) {
   406 	if (cw > indspec->minimal_cargo/* && i->produced_cargo[0] != 0xFF*/) {
   359 		i->cargo_waiting[0] -= cw;
   407 		i->produced_cargo_waiting[0] -= cw;
   360 
   408 
   361 		/* fluctuating economy? */
   409 		/* fluctuating economy? */
   362 		if (_economy.fluct <= 0) cw = (cw + 1) / 2;
   410 		if (_economy.fluct <= 0) cw = (cw + 1) / 2;
   363 
   411 
   364 		i->last_mo_production[0] += cw;
   412 		i->this_month_production[0] += cw;
   365 
   413 
   366 		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw);
   414 		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[0], cw);
   367 		i->last_mo_transported[0] += am;
   415 		i->this_month_transported[0] += am;
   368 		if (am != 0) {
   416 		if (am != 0 && !StartStopIndustryTileAnimation(i, IAT_INDUSTRY_DISTRIBUTES_CARGO)) {
   369 			uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
   417 			uint newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_production;
   370 
   418 
   371 			if (newgfx != INDUSTRYTILE_NOANIM) {
   419 			if (newgfx != INDUSTRYTILE_NOANIM) {
   372 				ResetIndustryConstructionStage(tile);
   420 				ResetIndustryConstructionStage(tile);
   373 				SetIndustryCompleted(tile, true);
   421 				SetIndustryCompleted(tile, true);
   375 				MarkTileDirtyByTile(tile);
   423 				MarkTileDirtyByTile(tile);
   376 			}
   424 			}
   377 		}
   425 		}
   378 	}
   426 	}
   379 
   427 
   380 	cw = min(i->cargo_waiting[1], 255);
   428 	cw = min(i->produced_cargo_waiting[1], 255);
   381 	if (cw > indspec->minimal_cargo) {
   429 	if (cw > indspec->minimal_cargo) {
   382 		i->cargo_waiting[1] -= cw;
   430 		i->produced_cargo_waiting[1] -= cw;
   383 
   431 
   384 		if (_economy.fluct <= 0) cw = (cw + 1) / 2;
   432 		if (_economy.fluct <= 0) cw = (cw + 1) / 2;
   385 
   433 
   386 		i->last_mo_production[1] += cw;
   434 		i->this_month_production[1] += cw;
   387 
   435 
   388 		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[1], cw);
   436 		am = MoveGoodsToStation(i->xy, i->width, i->height, indspec->produced_cargo[1], cw);
   389 		i->last_mo_transported[1] += am;
   437 		i->this_month_transported[1] += am;
   390 	}
   438 	}
   391 }
   439 }
   392 
   440 
   393 
   441 
   394 static void AnimateTile_Industry(TileIndex tile)
   442 static void AnimateTile_Industry(TileIndex tile)
   395 {
   443 {
   396 	byte m;
   444 	byte m;
   397 
   445 	IndustryGfx gfx = GetIndustryGfx(tile);
   398 	switch (GetIndustryGfx(tile)) {
   446 
       
   447 	if (GetIndustryTileSpec(gfx)->animation_info != 0xFFFF) {
       
   448 		AnimateNewIndustryTile(tile);
       
   449 		return;
       
   450 	}
       
   451 
       
   452 	switch (gfx) {
   399 	case GFX_SUGAR_MINE_SIEVE:
   453 	case GFX_SUGAR_MINE_SIEVE:
   400 		if ((_tick_counter & 1) == 0) {
   454 		if ((_tick_counter & 1) == 0) {
   401 			m = GetIndustryAnimationState(tile) + 1;
   455 			m = GetIndustryAnimationState(tile) + 1;
   402 
   456 
   403 			switch (m & 7) {
   457 			switch (m & 7) {
   579 	}
   633 	}
   580 
   634 
   581 	stage = GetIndustryConstructionStage(tile) + 1;
   635 	stage = GetIndustryConstructionStage(tile) + 1;
   582 	SetIndustryConstructionCounter(tile, 0);
   636 	SetIndustryConstructionCounter(tile, 0);
   583 	SetIndustryConstructionStage(tile, stage);
   637 	SetIndustryConstructionStage(tile, stage);
       
   638 	StartStopIndustryTileAnimation(tile, IAT_CONSTRUCTION_STATE_CHANGE);
   584 	if (stage == 3) {
   639 	if (stage == 3) {
   585 		SetIndustryCompleted(tile, true);
   640 		SetIndustryCompleted(tile, true);
   586 	}
   641 	}
   587 
   642 
   588 	MarkTileDirtyByTile(tile);
   643 	MarkTileDirtyByTile(tile);
   589 
   644 
   590 	if (!IsIndustryCompleted(tile)) return;
   645 	if (!IsIndustryCompleted(tile)) return;
   591 
   646 
   592 	switch (GetIndustryGfx(tile)) {
   647 	IndustryGfx gfx = GetIndustryGfx(tile);
       
   648 	if (gfx >= NEW_INDUSTRYTILEOFFSET) {
       
   649 		/* New industry */
       
   650 		const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
       
   651 		if (its->animation_info != 0xFFFF) AddAnimatedTile(tile);
       
   652 		return;
       
   653 	}
       
   654 
       
   655 	switch (gfx) {
   593 	case GFX_POWERPLANT_CHIMNEY:
   656 	case GFX_POWERPLANT_CHIMNEY:
   594 		CreateIndustryEffectSmoke(tile);
   657 		CreateIndustryEffectSmoke(tile);
   595 		break;
   658 		break;
   596 
   659 
   597 	case GFX_OILRIG_1:
   660 	case GFX_OILRIG_1:
   650 	}
   713 	}
   651 
   714 
   652 	if (_game_mode == GM_EDITOR) return;
   715 	if (_game_mode == GM_EDITOR) return;
   653 
   716 
   654 	TransportIndustryGoods(tile);
   717 	TransportIndustryGoods(tile);
       
   718 
       
   719 	if (StartStopIndustryTileAnimation(tile, IAT_TILELOOP)) return;
   655 
   720 
   656 	newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
   721 	newgfx = GetIndustryTileSpec(GetIndustryGfx(tile))->anim_next;
   657 	if (newgfx != INDUSTRYTILE_NOANIM) {
   722 	if (newgfx != INDUSTRYTILE_NOANIM) {
   658 		ResetIndustryConstructionStage(tile);
   723 		ResetIndustryConstructionStage(tile);
   659 		SetIndustryGfx(tile, newgfx);
   724 		SetIndustryGfx(tile, newgfx);
   766 	b[1] = i->produced_cargo[1];
   831 	b[1] = i->produced_cargo[1];
   767 }
   832 }
   768 
   833 
   769 static void ChangeTileOwner_Industry(TileIndex tile, PlayerID old_player, PlayerID new_player)
   834 static void ChangeTileOwner_Industry(TileIndex tile, PlayerID old_player, PlayerID new_player)
   770 {
   835 {
   771 	/* not used */
   836 	/* If the founder merges, the industry was created by the merged company */
       
   837 	Industry *i = GetIndustryByTile(tile);
       
   838 	if (i->founder == old_player) i->founder = (new_player == PLAYER_SPECTATOR) ? OWNER_NONE : new_player;
   772 }
   839 }
   773 
   840 
   774 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
   841 static const byte _plantfarmfield_type[] = {1, 1, 1, 1, 1, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6};
   775 
   842 
   776 static bool IsBadFarmFieldTile(TileIndex tile)
   843 static bool IsBadFarmFieldTile(TileIndex tile)
   877 	TileIndex tile = TileAddWrap(i->xy, x, y);
   944 	TileIndex tile = TileAddWrap(i->xy, x, y);
   878 
   945 
   879 	if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
   946 	if (tile != INVALID_TILE) PlantFarmField(tile, i->index);
   880 }
   947 }
   881 
   948 
   882 static void MaybePlantFarmField(const Industry *i)
       
   883 {
       
   884 	if (CHANCE16(1, 8)) PlantRandomFarmField(i);
       
   885 }
       
   886 
       
   887 /**
   949 /**
   888  * Search callback function for ChopLumberMillTrees
   950  * Search callback function for ChopLumberMillTrees
   889  * @param tile to test
   951  * @param tile to test
   890  * @param data that is passed by the caller.  In this case, nothing
   952  * @param data that is passed by the caller.  In this case, nothing
   891  * @return the result of the test
   953  * @return the result of the test
   918 	TileIndex tile = i->xy;
   980 	TileIndex tile = i->xy;
   919 
   981 
   920 	if (!IsIndustryCompleted(tile)) return;  ///< Can't proceed if not completed
   982 	if (!IsIndustryCompleted(tile)) return;  ///< Can't proceed if not completed
   921 
   983 
   922 	if (CircularTileSearch(tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles  to search
   984 	if (CircularTileSearch(tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles  to search
   923 		i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo
   985 		i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo
   924 }
   986 }
   925 
   987 
   926 static void ProduceIndustryGoods(Industry *i)
   988 static void ProduceIndustryGoods(Industry *i)
   927 {
   989 {
   928 	uint32 r;
   990 	uint32 r;
   940 
  1002 
   941 	i->counter--;
  1003 	i->counter--;
   942 
  1004 
   943 	/* produce some cargo */
  1005 	/* produce some cargo */
   944 	if ((i->counter & 0xFF) == 0) {
  1006 	if ((i->counter & 0xFF) == 0) {
       
  1007 		if (HASBIT(indsp->callback_flags, CBM_IND_PRODUCTION_256_TICKS)) IndustryProductionCallback(i, 1);
       
  1008 
   945 		IndustyBehaviour indbehav = indsp->behaviour;
  1009 		IndustyBehaviour indbehav = indsp->behaviour;
   946 		i->cargo_waiting[0] = min(0xffff, i->cargo_waiting[0] + i->production_rate[0]);
  1010 		i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + i->production_rate[0]);
   947 		i->cargo_waiting[1] = min(0xffff, i->cargo_waiting[1] + i->production_rate[1]);
  1011 		i->produced_cargo_waiting[1] = min(0xffff, i->produced_cargo_waiting[1] + i->production_rate[1]);
   948 
  1012 
   949 		if (indbehav & INDUSTRYBEH_PLANT_FIELDS) {
  1013 		if ((indbehav & INDUSTRYBEH_PLANT_FIELDS) != 0) {
   950 			MaybePlantFarmField(i);
  1014 			bool plant;
   951 		} else if ((indbehav & INDUSTRYBEH_CUT_TREES) && (i->counter & 0x1FF) == 0) {
  1015 			if (HASBIT(indsp->callback_flags, CBM_IND_SPECIAL_EFFECT)) {
   952 			ChopLumberMillTrees(i);
  1016 				plant = (GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, Random(), 0, i, i->type, i->xy) != 0);
       
  1017 			} else {
       
  1018 				plant = CHANCE16(1, 8);
       
  1019 			}
       
  1020 
       
  1021 			if (plant) PlantRandomFarmField(i);
       
  1022 		}
       
  1023 		if ((indbehav & INDUSTRYBEH_CUT_TREES) != 0) {
       
  1024 			bool cut = ((i->counter & 0x1FF) == 0);
       
  1025 			if (HASBIT(indsp->callback_flags, CBM_IND_SPECIAL_EFFECT)) {
       
  1026 				cut = (GetIndustryCallback(CBID_INDUSTRY_SPECIAL_EFFECT, 0, 1, i, i->type, i->xy) != 0);
       
  1027 			}
       
  1028 
       
  1029 			if (cut) ChopLumberMillTrees(i);
   953 		}
  1030 		}
   954 	}
  1031 	}
   955 }
  1032 }
   956 
  1033 
   957 void OnTick_Industry()
  1034 void OnTick_Industry()
   970 	}
  1047 	}
   971 
  1048 
   972 	if (_game_mode == GM_EDITOR) return;
  1049 	if (_game_mode == GM_EDITOR) return;
   973 
  1050 
   974 	FOR_ALL_INDUSTRIES(i) {
  1051 	FOR_ALL_INDUSTRIES(i) {
       
  1052 		StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
   975 		ProduceIndustryGoods(i);
  1053 		ProduceIndustryGoods(i);
   976 	}
  1054 	}
   977 }
  1055 }
   978 
  1056 
   979 
  1057 
  1103 	}
  1181 	}
  1104 
  1182 
  1105 	return t;
  1183 	return t;
  1106 }
  1184 }
  1107 
  1185 
  1108 static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type)
  1186 static bool CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileTable *it, int type, bool *custom_shape_check = NULL)
  1109 {
  1187 {
  1110 	_error_message = STR_0239_SITE_UNSUITABLE;
  1188 	_error_message = STR_0239_SITE_UNSUITABLE;
  1111 
  1189 
  1112 	do {
  1190 	do {
  1113 		TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
  1191 		TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
  1122 					GetTileSlope(cur_tile, NULL) != SLOPE_FLAT) {
  1200 					GetTileSlope(cur_tile, NULL) != SLOPE_FLAT) {
  1123 				return false;
  1201 				return false;
  1124 			}
  1202 			}
  1125 		} else {
  1203 		} else {
  1126 			if (!EnsureNoVehicle(cur_tile)) return false;
  1204 			if (!EnsureNoVehicle(cur_tile)) return false;
       
  1205 			if (MayHaveBridgeAbove(cur_tile) && IsBridgeAbove(cur_tile)) return false;
       
  1206 
       
  1207 			const IndustryTileSpec *its = GetIndustryTileSpec(it->gfx);
  1127 			IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
  1208 			IndustyBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
  1128 
  1209 
  1129 			if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) {
  1210 			if (HASBIT(its->callback_flags, CBM_INDT_SHAPE_CHECK)) {
  1130 				/* As soon as the tile is not water, bail out.
  1211 				if (custom_shape_check != NULL) *custom_shape_check = true;
  1131 				 * But that does not mean the search is over.  You have
  1212 				if (!PerformIndustryTileSlopeCheck(cur_tile, its, type, it->gfx)) return false;
  1132 				 * to make sure every tile of the industry will be only water*/
       
  1133 				if (!IsClearWaterTile(cur_tile)) return false;
       
  1134 			} else {
  1213 			} else {
  1135 				Slope tileh;
  1214 				if (ind_behav & INDUSTRYBEH_BUILT_ONWATER) {
  1136 
  1215 					/* As soon as the tile is not water, bail out.
  1137 				if (IsClearWaterTile(cur_tile)) return false;
  1216 					* But that does not mean the search is over.  You have
  1138 
  1217 					* to make sure every tile of the industry will be only water*/
  1139 				tileh = GetTileSlope(cur_tile, NULL);
  1218 					if (!IsClearWaterTile(cur_tile)) return false;
  1140 				if (IsSteepSlope(tileh)) return false;
  1219 				} else {
  1141 
  1220 					Slope tileh;
  1142 				if (_patches.land_generator != LG_TERRAGENESIS || !_generating_world) {
  1221 
  1143 					/* It is almost impossible to have a fully flat land in TG, so what we
  1222 					if (IsClearWaterTile(cur_tile)) return false;
  1144 					 *  do is that we check if we can make the land flat later on. See
  1223 
  1145 					 *  CheckIfCanLevelIndustryPlatform(). */
  1224 					tileh = GetTileSlope(cur_tile, NULL);
  1146 					if (tileh != SLOPE_FLAT) {
  1225 					if (IsSteepSlope(tileh)) return false;
  1147 						Slope t;
  1226 
  1148 						byte bits = GetIndustryTileSpec(it->gfx)->slopes_refused;
  1227 					if (_patches.land_generator != LG_TERRAGENESIS || !_generating_world) {
  1149 
  1228 						/* It is almost impossible to have a fully flat land in TG, so what we
  1150 						if (bits & 0x10) return false;
  1229 						*  do is that we check if we can make the land flat later on. See
  1151 
  1230 						*  CheckIfCanLevelIndustryPlatform(). */
  1152 						t = ComplementSlope(tileh);
  1231 						if (tileh != SLOPE_FLAT) {
  1153 
  1232 							Slope t;
  1154 						if (bits & 1 && (t & SLOPE_NW)) return false;
  1233 							byte bits = its->slopes_refused;
  1155 						if (bits & 2 && (t & SLOPE_NE)) return false;
  1234 
  1156 						if (bits & 4 && (t & SLOPE_SW)) return false;
  1235 							if (bits & 0x10) return false;
  1157 						if (bits & 8 && (t & SLOPE_SE)) return false;
  1236 
       
  1237 							t = ComplementSlope(tileh);
       
  1238 
       
  1239 							if (bits & 1 && (t & SLOPE_NW)) return false;
       
  1240 							if (bits & 2 && (t & SLOPE_NE)) return false;
       
  1241 							if (bits & 4 && (t & SLOPE_SW)) return false;
       
  1242 							if (bits & 8 && (t & SLOPE_SE)) return false;
       
  1243 						}
  1158 					}
  1244 					}
  1159 				}
  1245 				}
  1160 
  1246 			}
  1161 				if (ind_behav & INDUSTRYBEH_ONLY_INTOWN) {
  1247 
  1162 					if (!IsTileType(cur_tile, MP_HOUSE)) {
  1248 			if (ind_behav & INDUSTRYBEH_ONLY_INTOWN) {
  1163 						_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
  1249 				if (!IsTileType(cur_tile, MP_HOUSE)) {
  1164 						return false;
  1250 					_error_message = STR_029D_CAN_ONLY_BE_BUILT_IN_TOWNS;
  1165 					}
  1251 					return false;
  1166 				} else {
       
  1167 					if (ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) {
       
  1168 						if (!IsTileType(cur_tile, MP_HOUSE)) goto do_clear;
       
  1169 					} else {
       
  1170 do_clear:
       
  1171 						if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR)))
       
  1172 							return false;
       
  1173 					}
       
  1174 				}
  1252 				}
       
  1253 				if (CmdFailed(DoCommand(cur_tile, 0, 0, 0, CMD_LANDSCAPE_CLEAR))) return false;
       
  1254 			} else if ((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) == 0 || !IsTileType(cur_tile, MP_HOUSE)) {
       
  1255 				if (CmdFailed(DoCommand(cur_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR))) return false;
  1175 			}
  1256 			}
  1176 		}
  1257 		}
  1177 	} while ((++it)->ti.x != -0x80);
  1258 	} while ((++it)->ti.x != -0x80);
  1178 
  1259 
  1179 	return true;
  1260 	return true;
  1299 
  1380 
  1300 	FOR_ALL_INDUSTRIES(i) {
  1381 	FOR_ALL_INDUSTRIES(i) {
  1301 		/* check if an industry that accepts the same goods is nearby */
  1382 		/* check if an industry that accepts the same goods is nearby */
  1302 		if (DistanceMax(tile, i->xy) <= 14 &&
  1383 		if (DistanceMax(tile, i->xy) <= 14 &&
  1303 				indspec->accepts_cargo[0] != CT_INVALID &&
  1384 				indspec->accepts_cargo[0] != CT_INVALID &&
  1304 				indspec->accepts_cargo[0] == indspec->accepts_cargo[0] && (
  1385 				indspec->accepts_cargo[0] == GetIndustrySpec(i->type)->accepts_cargo[0] && (
  1305 					_game_mode != GM_EDITOR ||
  1386 					_game_mode != GM_EDITOR ||
  1306 					!_patches.same_industry_close ||
  1387 					!_patches.same_industry_close ||
  1307 					!_patches.multiple_industry_per_town
  1388 					!_patches.multiple_industry_per_town
  1308 				)) {
  1389 				)) {
  1309 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1390 			_error_message = STR_INDUSTRY_TOO_CLOSE;
  1345 {
  1426 {
  1346 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1427 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1347 	uint32 r;
  1428 	uint32 r;
  1348 	int j;
  1429 	int j;
  1349 
  1430 
  1350 	_total_industries++;
       
  1351 	i->xy = tile;
  1431 	i->xy = tile;
  1352 	i->width = i->height = 0;
  1432 	i->width = i->height = 0;
  1353 	i->type = type;
  1433 	i->type = type;
       
  1434 	IncIndustryTypeCount(type);
  1354 
  1435 
  1355 	i->production_rate[0] = indspec->production_rate[0];
  1436 	i->production_rate[0] = indspec->production_rate[0];
  1356 	i->production_rate[1] = indspec->production_rate[1];
  1437 	i->production_rate[1] = indspec->production_rate[1];
  1357 
  1438 
  1358 	if (_patches.smooth_economy) {
  1439 	if (_patches.smooth_economy) {
  1364 	i->owner = owner;
  1445 	i->owner = owner;
  1365 
  1446 
  1366 	r = Random();
  1447 	r = Random();
  1367 	i->random_color = GB(r, 8, 4);
  1448 	i->random_color = GB(r, 8, 4);
  1368 	i->counter = GB(r, 0, 12);
  1449 	i->counter = GB(r, 0, 12);
  1369 	i->cargo_waiting[0] = 0;
  1450 	i->produced_cargo_waiting[0] = 0;
  1370 	i->cargo_waiting[1] = 0;
  1451 	i->produced_cargo_waiting[1] = 0;
  1371 	i->last_mo_production[0] = 0;
  1452 	i->incoming_cargo_waiting[0] = 0;
  1372 	i->last_mo_production[1] = 0;
  1453 	i->incoming_cargo_waiting[1] = 0;
  1373 	i->last_mo_transported[0] = 0;
  1454 	i->incoming_cargo_waiting[2] = 0;
  1374 	i->last_mo_transported[1] = 0;
  1455 	i->this_month_production[0] = 0;
  1375 	i->pct_transported[0] = 0;
  1456 	i->this_month_production[1] = 0;
  1376 	i->pct_transported[1] = 0;
  1457 	i->this_month_transported[0] = 0;
  1377 	i->total_transported[0] = 0;
  1458 	i->this_month_transported[1] = 0;
  1378 	i->total_transported[1] = 0;
  1459 	i->last_month_pct_transported[0] = 0;
       
  1460 	i->last_month_pct_transported[1] = 0;
       
  1461 	i->last_month_transported[0] = 0;
       
  1462 	i->last_month_transported[1] = 0;
  1379 	i->was_cargo_delivered = false;
  1463 	i->was_cargo_delivered = false;
  1380 	i->last_prod_year = _cur_year;
  1464 	i->last_prod_year = _cur_year;
  1381 	i->total_production[0] = i->production_rate[0] * 8;
  1465 	i->last_month_production[0] = i->production_rate[0] * 8;
  1382 	i->total_production[1] = i->production_rate[1] * 8;
  1466 	i->last_month_production[1] = i->production_rate[1] * 8;
  1383 
  1467 	i->founder = _current_player;
  1384 	if (!_generating_world) i->total_production[0] = i->total_production[1] = 0;
  1468 	i->construction_date = _date;
       
  1469 	i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
       
  1470 			(_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
       
  1471 
       
  1472 	if (!_generating_world) i->last_month_production[0] = i->last_month_production[1] = 0;
  1385 
  1473 
  1386 	i->prod_level = 0x10;
  1474 	i->prod_level = 0x10;
  1387 
  1475 
  1388 	do {
  1476 	do {
  1389 		TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
  1477 		TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
  1419 /** Helper function for Build/Fund an industry
  1507 /** Helper function for Build/Fund an industry
  1420  * @param tile tile where industry is built
  1508  * @param tile tile where industry is built
  1421  * @param type of industry to build
  1509  * @param type of industry to build
  1422  * @param flags of operations to conduct
  1510  * @param flags of operations to conduct
  1423  * @param indspec pointer to industry specifications
  1511  * @param indspec pointer to industry specifications
  1424  * @param it pointer to list of tile type to build
  1512  * @param itspec_index the index of the itsepc to build/fund
  1425  * @return the pointer of the newly created industry, or NULL if it failed
  1513  * @return the pointer of the newly created industry, or NULL if it failed
  1426  */
  1514  */
  1427 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, const IndustryTileTable *it)
  1515 static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index)
  1428 {
  1516 {
  1429 	const Town *t;
  1517 	const IndustryTileTable *it = indspec->table[itspec_index];
  1430 	Industry *i;
  1518 	bool custom_shape_check = false;
  1431 
  1519 
  1432 	if (!CheckIfIndustryTilesAreFree(tile, it, type)) return NULL;
  1520 	if (!CheckIfIndustryTilesAreFree(tile, it, type, &custom_shape_check)) return NULL;
  1433 	if (_patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
  1521 
  1434 	if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
  1522 	if (HASBIT(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) {
       
  1523 		if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index)) return NULL;
       
  1524 	} else {
       
  1525 		if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
       
  1526 	}
       
  1527 
       
  1528 	if (!custom_shape_check && _patches.land_generator == LG_TERRAGENESIS && _generating_world && !CheckIfCanLevelIndustryPlatform(tile, 0, it, type)) return NULL;
  1435 	if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
  1529 	if (!CheckIfTooCloseToIndustry(tile, type)) return NULL;
  1436 
  1530 
  1437 	t = CheckMultipleIndustryInTown(tile, type);
  1531 	const Town *t = CheckMultipleIndustryInTown(tile, type);
  1438 	if (t == NULL) return NULL;
  1532 	if (t == NULL) return NULL;
  1439 
  1533 
  1440 	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
  1534 	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
  1441 	if (!CheckSuitableIndustryPos(tile)) return NULL;
  1535 	if (!CheckSuitableIndustryPos(tile)) return NULL;
  1442 
  1536 
  1443 	i = AllocateIndustry();
  1537 	Industry *i = AllocateIndustry();
  1444 	if (i == NULL) return NULL;
  1538 	if (i == NULL) return NULL;
  1445 
  1539 
  1446 	if (flags & DC_EXEC) {
  1540 	if (flags & DC_EXEC) {
  1447 		CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type);
  1541 		if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type);
  1448 		DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
  1542 		DoCreateNewIndustry(i, tile, type, it, t, OWNER_NONE);
  1449 	}
  1543 	}
  1450 
  1544 
  1451 	return i;
  1545 	return i;
  1452 }
  1546 }
  1456  * @param flags of operations to conduct
  1550  * @param flags of operations to conduct
  1457  * @param p1 industry type see build_industry.h and see industry.h
  1551  * @param p1 industry type see build_industry.h and see industry.h
  1458  * @param p2 unused
  1552  * @param p2 unused
  1459  * @return index of the newly create industry, or CMD_ERROR if it failed
  1553  * @return index of the newly create industry, or CMD_ERROR if it failed
  1460  */
  1554  */
  1461 int32 CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1555 CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1462 {
  1556 {
  1463 	int num;
  1557 	int num;
  1464 	const IndustryTileTable * const *itt;
  1558 	const IndustryTileTable * const *itt;
  1465 	const IndustryTileTable *it;
  1559 	const IndustryTileTable *it;
  1466 	const IndustrySpec *indspec;
  1560 	const IndustrySpec *indspec;
  1473 	if (!indspec->enabled) {
  1567 	if (!indspec->enabled) {
  1474 		return CMD_ERROR;
  1568 		return CMD_ERROR;
  1475 	}
  1569 	}
  1476 
  1570 
  1477 	/* If the patch for raw-material industries is not on, you cannot build raw-material industries.
  1571 	/* If the patch for raw-material industries is not on, you cannot build raw-material industries.
  1478 	 * Raw material industries are industries that do not accept cargo (at least for now)
  1572 	 * Raw material industries are industries that do not accept cargo (at least for now) */
  1479 	 * Exclude the lumber mill (only "raw" industry that can be built) */
  1573 	if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 0 && indspec->IsRawIndustry()) {
  1480 	if (!_patches.build_rawmaterial_ind &&
       
  1481 			indspec->accepts_cargo[0] == CT_INVALID &&
       
  1482 			indspec->accepts_cargo[1] == CT_INVALID &&
       
  1483 			indspec->accepts_cargo[2] == CT_INVALID &&
       
  1484 			!(indspec->behaviour & INDUSTRYBEH_CUT_TREES)) {
       
  1485 		return CMD_ERROR;
  1574 		return CMD_ERROR;
  1486 	}
  1575 	}
  1487 
  1576 
  1488 	num = indspec->num_table;
  1577 	if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && indspec->IsRawIndustry()) {
  1489 	itt = indspec->table;
  1578 		if (flags & DC_EXEC) {
  1490 
  1579 			/* Prospecting has a chance to fail, however we cannot guarantee that something can
  1491 	do {
  1580 			 * be built on the map, so the chance gets lower when the map is fuller, but there
  1492 		if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE);
  1581 			 * is nothing we can really do about that. */
  1493 	} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1));
  1582 			if (Random() <= indspec->prospecting_chance) {
  1494 
  1583 				for (int i = 0; i < 5000; i++) {
  1495 	if (CreateNewIndustryHelper(tile, p1, flags, indspec, it) == NULL) return CMD_ERROR;
  1584 					uint tilespec_index = RandomRange(indspec->num_table);
  1496 
  1585 					const Industry *ind = CreateNewIndustryHelper(RandomTile(), p1, flags, indspec, tilespec_index);
  1497 	return (_price.build_industry >> 5) * indspec->cost_multiplier;
  1586 					if (ind != NULL) {
       
  1587 						SetDParam(0, indspec->name);
       
  1588 						SetDParam(1, ind->town->index);
       
  1589 						AddNewsItem(indspec->new_industry_text,
       
  1590 								NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0);
       
  1591 						break;
       
  1592 					}
       
  1593 				}
       
  1594 			}
       
  1595 		}
       
  1596 	} else {
       
  1597 		num = indspec->num_table;
       
  1598 		itt = indspec->table;
       
  1599 
       
  1600 
       
  1601 		do {
       
  1602 			if (--num < 0) return_cmd_error(STR_0239_SITE_UNSUITABLE);
       
  1603 		} while (!CheckIfIndustryTilesAreFree(tile, it = itt[num], p1));
       
  1604 
       
  1605 		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR;
       
  1606 	}
       
  1607 
       
  1608 	return CommandCost(indspec->GetConstructionCost());
  1498 }
  1609 }
  1499 
  1610 
  1500 
  1611 
  1501 Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
  1612 Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
  1502 {
  1613 {
  1503 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1614 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1504 	const IndustryTileTable *it = indspec->table[RandomRange(indspec->num_table)];
  1615 
  1505 
  1616 	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table));
  1506 	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, it);
  1617 }
  1507 }
  1618 
  1508 
  1619 static const byte _numof_industry_table[5][11] = {
  1509 static const byte _numof_industry_table[5][12] = {
       
  1510 	/* difficulty settings for number of industries */
  1620 	/* difficulty settings for number of industries */
  1511 	{0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0},   //none
  1621 	{0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0},   //none
  1512 	{0, 1, 1, 1, 1, 1, 1, 1,  1,  1,  1},   //very low
  1622 	{0, 1, 1, 1, 1, 1, 1, 1,  1,  1,  1},   //very low
  1513 	{0, 1, 1, 1, 2, 2, 3, 3,  4,  4,  5},   //low
  1623 	{0, 1, 1, 1, 2, 2, 3, 3,  4,  4,  5},   //low
  1514 	{0, 1, 2, 3, 4, 5, 6, 7,  8,  9, 10},   //normal
  1624 	{0, 1, 2, 3, 4, 5, 6, 7,  8,  9, 10},   //normal
  1595 {
  1705 {
  1596 	bool closeit = true;
  1706 	bool closeit = true;
  1597 	int j;
  1707 	int j;
  1598 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
  1708 	const IndustrySpec *indspec = GetIndustrySpec(i->type);
  1599 
  1709 
  1600 	switch (indspec->life_type) {
  1710 	if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
  1601 		case INDUSTRYLIFE_NOT_CLOSABLE:
  1711 
  1602 			return;
  1712 	if ((indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) {
  1603 
  1713 		for (j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){
  1604 		case INDUSTRYLIFE_CLOSABLE:
  1714 			uint32 r = Random();
  1605 			if ((byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180))
  1715 			int old_prod, new_prod, percent;
       
  1716 			int mag;
       
  1717 
       
  1718 			new_prod = old_prod = i->production_rate[j];
       
  1719 
       
  1720 			if (CHANCE16I(20, 1024, r)) new_prod -= max(((RandomRange(50) + 10) * old_prod) >> 8, 1U);
       
  1721 			/* Chance of increasing becomes better when more is transported */
       
  1722 			if (CHANCE16I(20 + (i->last_month_pct_transported[j] * 20 >> 8), 1024, r >> 16) &&
       
  1723 					((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) == 0 || _opt.landscape != LT_TEMPERATE)) {
       
  1724 				new_prod += max(((RandomRange(50) + 10) * old_prod) >> 8, 1U);
       
  1725 			}
       
  1726 
       
  1727 			new_prod = clamp(new_prod, 1, 255);
       
  1728 			/* Do not stop closing the industry when it has the lowest possible production rate */
       
  1729 			if (new_prod == old_prod && old_prod > 1) {
  1606 				closeit = false;
  1730 				closeit = false;
  1607 			break;
  1731 				continue;
  1608 
  1732 			}
  1609 		default: /* INDUSTRY_PRODUCTION */
  1733 
  1610 			for (j = 0; j < 2 && indspec->produced_cargo[j] != CT_INVALID; j++){
  1734 			percent = (old_prod == 0) ? 100 : (new_prod * 100 / old_prod - 100);
  1611 				uint32 r = Random();
  1735 			i->production_rate[j] = new_prod;
  1612 				int old_prod, new_prod, percent;
  1736 
  1613 				int mag;
  1737 			/* Close the industry when it has the lowest possible production rate */
  1614 
  1738 			if (new_prod > 1) closeit = false;
  1615 				new_prod = old_prod = i->production_rate[j];
  1739 
  1616 				if (CHANCE16I(20, 1024, r))
  1740 			mag = abs(percent);
  1617 					new_prod -= ((RandomRange(50) + 10) * old_prod) >> 8;
  1741 			if (mag >= 10) {
  1618 				if (CHANCE16I(20 + (i->pct_transported[j] * 20 >> 8), 1024, r >> 16))
  1742 				SetDParam(2, mag);
  1619 					new_prod += ((RandomRange(50) + 10) * old_prod) >> 8;
  1743 				SetDParam(0, GetCargo(indspec->produced_cargo[j])->name);
  1620 
  1744 				SetDParam(1, i->index);
  1621 				new_prod = clamp(new_prod, 0, 255);
  1745 				AddNewsItem(
  1622 				if (new_prod == old_prod) {
  1746 					percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
  1623 					closeit = false;
  1747 					NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0),
  1624 					continue;
  1748 					i->xy + TileDiffXY(1, 1), 0
  1625 				}
  1749 				);
  1626 
  1750 			}
  1627 				percent = new_prod * 100 / old_prod - 100;
  1751 		}
  1628 				i->production_rate[j] = new_prod;
  1752 	}
  1629 
  1753 
  1630 				if (new_prod >= indspec->production_rate[j] / 4)
  1754 	if ((indspec->life_type & INDUSTRYLIFE_PROCESSING) != 0) {
  1631 					closeit = false;
  1755 		if ((byte)(_cur_year - i->last_prod_year) < 5 || !CHANCE16(1, 180)) closeit = false;
  1632 
       
  1633 				mag = abs(percent);
       
  1634 				if (mag >= 10) {
       
  1635 					SetDParam(2, mag);
       
  1636 					SetDParam(0, GetCargo(indspec->produced_cargo[j])->name);
       
  1637 					SetDParam(1, i->index);
       
  1638 					AddNewsItem(
       
  1639 						percent >= 0 ? STR_INDUSTRY_PROD_GOUP : STR_INDUSTRY_PROD_GODOWN,
       
  1640 						NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_ECONOMY, 0),
       
  1641 						i->xy + TileDiffXY(1, 1), 0
       
  1642 					);
       
  1643 				}
       
  1644 			}
       
  1645 			break;
       
  1646 	}
  1756 	}
  1647 
  1757 
  1648 	/* If industry will be closed down, show this */
  1758 	/* If industry will be closed down, show this */
  1649 	if (closeit) {
  1759 	if (closeit) {
  1650 		i->prod_level = 0;
  1760 		i->prod_level = 0;
  1665 	const IndustrySpec *indsp = GetIndustrySpec(i->type);
  1775 	const IndustrySpec *indsp = GetIndustrySpec(i->type);
  1666 
  1776 
  1667 	for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
  1777 	for (byte j = 0; j < lengthof(indsp->produced_cargo); j++) {
  1668 		if (indsp->produced_cargo[j] != CT_INVALID) {
  1778 		if (indsp->produced_cargo[j] != CT_INVALID) {
  1669 			pct = 0;
  1779 			pct = 0;
  1670 			if (i->last_mo_production[j] != 0) {
  1780 			if (i->this_month_production[j] != 0) {
  1671 				i->last_prod_year = _cur_year;
  1781 				i->last_prod_year = _cur_year;
  1672 				pct = min(i->last_mo_transported[j] * 256 / i->last_mo_production[j], 255);
  1782 				pct = min(i->this_month_transported[j] * 256 / i->this_month_production[j], 255);
  1673 			}
  1783 			}
  1674 			i->pct_transported[j] = pct;
  1784 			i->last_month_pct_transported[j] = pct;
  1675 
  1785 
  1676 			i->total_production[j] = i->last_mo_production[j];
  1786 			i->last_month_production[j] = i->this_month_production[j];
  1677 			i->last_mo_production[j] = 0;
  1787 			i->this_month_production[j] = 0;
  1678 
  1788 
  1679 			i->total_transported[j] = i->last_mo_transported[j];
  1789 			i->last_month_transported[j] = i->this_month_transported[j];
  1680 			i->last_mo_transported[j] = 0;
  1790 			i->this_month_transported[j] = 0;
  1681 			refresh = true;
  1791 			refresh = true;
  1682 		}
  1792 		}
  1683 	}
  1793 	}
  1684 
  1794 
  1685 	if (refresh)
  1795 	if (refresh)
  1749 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0);
  1859 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, NT_OPENCLOSE, 0), ind->xy, 0);
  1750 }
  1860 }
  1751 
  1861 
  1752 static void ChangeIndustryProduction(Industry *i)
  1862 static void ChangeIndustryProduction(Industry *i)
  1753 {
  1863 {
  1754 	bool only_decrease = false;
       
  1755 	StringID str = STR_NULL;
  1864 	StringID str = STR_NULL;
  1756 	int type = i->type;
  1865 	int type = i->type;
  1757 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1866 	const IndustrySpec *indspec = GetIndustrySpec(type);
  1758 
  1867 
  1759 	switch (indspec->life_type) {
  1868 	if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
  1760 		case INDUSTRYLIFE_NOT_CLOSABLE:
  1869 
  1761 			return;
  1870 	if ((indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0) {
  1762 
  1871 		bool only_decrease = false;
  1763 		case INDUSTRYLIFE_PRODUCTION:
  1872 
  1764 			/* decrease or increase */
  1873 		/* decrease or increase */
  1765 			if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE)
  1874 		if ((indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _opt.landscape == LT_TEMPERATE)
  1766 				only_decrease = true;
  1875 			only_decrease = true;
  1767 
  1876 
  1768 			if (only_decrease || CHANCE16(1, 3)) {
  1877 		if (only_decrease || CHANCE16(1, 3)) {
  1769 				/* If you transport > 60%, 66% chance we increase, else 33% chance we increase */
  1878 			/* If you transport > 60%, 66% chance we increase, else 33% chance we increase */
  1770 				if (!only_decrease && (i->pct_transported[0] > 153) != CHANCE16(1, 3)) {
  1879 			if (!only_decrease && (i->last_month_pct_transported[0] > 153) != CHANCE16(1, 3)) {
  1771 					/* Increase production */
  1880 				/* Increase production */
  1772 					if (i->prod_level != 0x80) {
  1881 				if (i->prod_level != 0x80) {
  1773 						byte b;
  1882 					byte b;
  1774 
  1883 
  1775 						i->prod_level <<= 1;
  1884 					i->prod_level <<= 1;
  1776 
  1885 
  1777 						b = i->production_rate[0] * 2;
  1886 					b = i->production_rate[0] * 2;
  1778 						if (i->production_rate[0] >= 128)
  1887 					if (i->production_rate[0] >= 128)
  1779 							b = 0xFF;
  1888 						b = 0xFF;
  1780 						i->production_rate[0] = b;
  1889 					i->production_rate[0] = b;
  1781 
  1890 
  1782 						b = i->production_rate[1] * 2;
  1891 					b = i->production_rate[1] * 2;
  1783 						if (i->production_rate[1] >= 128)
  1892 					if (i->production_rate[1] >= 128)
  1784 							b = 0xFF;
  1893 						b = 0xFF;
  1785 						i->production_rate[1] = b;
  1894 					i->production_rate[1] = b;
  1786 
  1895 
  1787 						str = indspec->production_up_text;
  1896 					str = indspec->production_up_text;
  1788 					}
  1897 				}
       
  1898 			} else {
       
  1899 				/* Decrease production */
       
  1900 				if (i->prod_level == 4) {
       
  1901 					i->prod_level = 0;
       
  1902 					str = indspec->closure_text;
  1789 				} else {
  1903 				} else {
  1790 					/* Decrease production */
  1904 					i->prod_level >>= 1;
  1791 					if (i->prod_level == 4) {
  1905 					i->production_rate[0] = (i->production_rate[0] + 1) >> 1;
  1792 						i->prod_level = 0;
  1906 					i->production_rate[1] = (i->production_rate[1] + 1) >> 1;
  1793 						str = indspec->closure_text;
  1907 
  1794 					} else {
  1908 					str = indspec->production_down_text;
  1795 						i->prod_level >>= 1;
       
  1796 						i->production_rate[0] = (i->production_rate[0] + 1) >> 1;
       
  1797 						i->production_rate[1] = (i->production_rate[1] + 1) >> 1;
       
  1798 
       
  1799 						str = indspec->production_down_text;
       
  1800 					}
       
  1801 				}
  1909 				}
  1802 			}
  1910 			}
  1803 			break;
  1911 		}
  1804 
  1912 	}
  1805 		case INDUSTRYLIFE_CLOSABLE:
  1913 	if (indspec->life_type & INDUSTRYLIFE_PROCESSING) {
  1806 			/* maybe close */
  1914 		/* maybe close */
  1807 			if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, 2)) {
  1915 		if ( (byte)(_cur_year - i->last_prod_year) >= 5 && CHANCE16(1, 2)) {
  1808 				i->prod_level = 0;
  1916 			i->prod_level = 0;
  1809 				str = indspec->closure_text;
  1917 			str = indspec->closure_text;
  1810 			}
  1918 		}
  1811 			break;
       
  1812 	}
  1919 	}
  1813 
  1920 
  1814 	if (str != STR_NULL) {
  1921 	if (str != STR_NULL) {
  1815 		SetDParam(0, i->index);
  1922 		SetDParam(0, i->index);
  1816 		AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, str == indspec->closure_text ? NT_OPENCLOSE : NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0);
  1923 		AddNewsItem(str, NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_TILE, str == indspec->closure_text ? NT_OPENCLOSE : NT_ECONOMY, 0), i->xy + TileDiffXY(1, 1), 0);
  1846 void InitializeIndustries()
  1953 void InitializeIndustries()
  1847 {
  1954 {
  1848 	CleanPool(&_Industry_pool);
  1955 	CleanPool(&_Industry_pool);
  1849 	AddBlockToPool(&_Industry_pool);
  1956 	AddBlockToPool(&_Industry_pool);
  1850 
  1957 
  1851 	_total_industries = 0;
  1958 	ResetIndustryCounts();
  1852 	_industry_sort_dirty = true;
  1959 	_industry_sort_dirty = true;
  1853 	_industry_sound_tile = 0;
  1960 	_industry_sound_tile = 0;
  1854 }
  1961 }
       
  1962 
       
  1963 bool IndustrySpec::IsRawIndustry() const
       
  1964 {
       
  1965 	/* Lumber mills are extractive/organic, but can always be built like a non-raw industry */
       
  1966 	return (this->life_type & (INDUSTRYLIFE_EXTRACTIVE | INDUSTRYLIFE_ORGANIC)) != 0 &&
       
  1967 			(this->behaviour & INDUSTRYBEH_CUT_TREES) == 0;
       
  1968 }
       
  1969 
       
  1970 Money IndustrySpec::GetConstructionCost() const
       
  1971 {
       
  1972 	return (_price.build_industry *
       
  1973 			(_patches.raw_industry_construction == 1 && this->IsRawIndustry() ?
       
  1974 					this->raw_industry_cost_multiplier :
       
  1975 					this->cost_multiplier
       
  1976 			)) >> 8;
       
  1977 }
       
  1978 
  1855 
  1979 
  1856 extern const TileTypeProcs _tile_type_industry_procs = {
  1980 extern const TileTypeProcs _tile_type_industry_procs = {
  1857 	DrawTile_Industry,           /* draw_tile_proc */
  1981 	DrawTile_Industry,           /* draw_tile_proc */
  1858 	GetSlopeZ_Industry,          /* get_slope_z_proc */
  1982 	GetSlopeZ_Industry,          /* get_slope_z_proc */
  1859 	ClearTile_Industry,          /* clear_tile_proc */
  1983 	ClearTile_Industry,          /* clear_tile_proc */
  1868 	NULL,                        /* vehicle_enter_tile_proc */
  1992 	NULL,                        /* vehicle_enter_tile_proc */
  1869 	GetSlopeTileh_Industry,      /* get_slope_tileh_proc */
  1993 	GetSlopeTileh_Industry,      /* get_slope_tileh_proc */
  1870 };
  1994 };
  1871 
  1995 
  1872 static const SaveLoad _industry_desc[] = {
  1996 static const SaveLoad _industry_desc[] = {
  1873 	SLE_CONDVAR(Industry, xy,                  SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
  1997 	SLE_CONDVAR(Industry, xy,                         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
  1874 	SLE_CONDVAR(Industry, xy,                  SLE_UINT32,                  6, SL_MAX_VERSION),
  1998 	SLE_CONDVAR(Industry, xy,                         SLE_UINT32,                  6, SL_MAX_VERSION),
  1875 	    SLE_VAR(Industry, width,               SLE_UINT8),
  1999 	    SLE_VAR(Industry, width,                      SLE_UINT8),
  1876 	    SLE_VAR(Industry, height,              SLE_UINT8),
  2000 	    SLE_VAR(Industry, height,                     SLE_UINT8),
  1877 	    SLE_REF(Industry, town,                REF_TOWN),
  2001 	    SLE_REF(Industry, town,                       REF_TOWN),
  1878 	SLE_CONDNULL( 2, 2, 60),       ///< used to be industry's produced_cargo
  2002 	SLE_CONDNULL( 2, 2, 60),       ///< used to be industry's produced_cargo
  1879 	    SLE_ARR(Industry, cargo_waiting,       SLE_UINT16, 2),
  2003 	SLE_CONDARR(Industry, incoming_cargo_waiting,     SLE_UINT16, 3,              70, SL_MAX_VERSION),
  1880 	    SLE_ARR(Industry, production_rate,     SLE_UINT8,  2),
  2004 	    SLE_ARR(Industry, produced_cargo_waiting,     SLE_UINT16, 2),
       
  2005 	    SLE_ARR(Industry, production_rate,            SLE_UINT8,  2),
  1881 	SLE_CONDNULL( 3, 2, 60),       ///< used to be industry's accepts_cargo
  2006 	SLE_CONDNULL( 3, 2, 60),       ///< used to be industry's accepts_cargo
  1882 	    SLE_VAR(Industry, prod_level,          SLE_UINT8),
  2007 	    SLE_VAR(Industry, prod_level,                 SLE_UINT8),
  1883 	    SLE_ARR(Industry, last_mo_production,  SLE_UINT16, 2),
  2008 	    SLE_ARR(Industry, this_month_production,      SLE_UINT16, 2),
  1884 	    SLE_ARR(Industry, last_mo_transported, SLE_UINT16, 2),
  2009 	    SLE_ARR(Industry, this_month_transported,     SLE_UINT16, 2),
  1885 	    SLE_ARR(Industry, pct_transported,     SLE_UINT8,  2),
  2010 	    SLE_ARR(Industry, last_month_pct_transported, SLE_UINT8,  2),
  1886 	    SLE_ARR(Industry, total_production,    SLE_UINT16, 2),
  2011 	    SLE_ARR(Industry, last_month_production,      SLE_UINT16, 2),
  1887 	    SLE_ARR(Industry, total_transported,   SLE_UINT16, 2),
  2012 	    SLE_ARR(Industry, last_month_transported,     SLE_UINT16, 2),
  1888 
  2013 
  1889 	    SLE_VAR(Industry, counter,             SLE_UINT16),
  2014 	    SLE_VAR(Industry, counter,                    SLE_UINT16),
  1890 
  2015 
  1891 	    SLE_VAR(Industry, type,                SLE_UINT8),
  2016 	    SLE_VAR(Industry, type,                       SLE_UINT8),
  1892 	    SLE_VAR(Industry, owner,               SLE_UINT8),
  2017 	    SLE_VAR(Industry, owner,                      SLE_UINT8),
  1893 	    SLE_VAR(Industry, random_color,        SLE_UINT8),
  2018 	    SLE_VAR(Industry, random_color,               SLE_UINT8),
  1894 	SLE_CONDVAR(Industry, last_prod_year,      SLE_FILE_U8 | SLE_VAR_I32,  0, 30),
  2019 	SLE_CONDVAR(Industry, last_prod_year,             SLE_FILE_U8 | SLE_VAR_I32,  0, 30),
  1895 	SLE_CONDVAR(Industry, last_prod_year,      SLE_INT32,                 31, SL_MAX_VERSION),
  2020 	SLE_CONDVAR(Industry, last_prod_year,             SLE_INT32,                 31, SL_MAX_VERSION),
  1896 	    SLE_VAR(Industry, was_cargo_delivered, SLE_UINT8),
  2021 	    SLE_VAR(Industry, was_cargo_delivered,        SLE_UINT8),
       
  2022 
       
  2023 	SLE_CONDVAR(Industry, owner,                      SLE_UINT8,                 70, SL_MAX_VERSION),
       
  2024 	SLE_CONDVAR(Industry, construction_date,          SLE_INT32,                 70, SL_MAX_VERSION),
       
  2025 	SLE_CONDVAR(Industry, construction_type,          SLE_UINT8,                 70, SL_MAX_VERSION),
       
  2026 	SLE_CONDVAR(Industry, last_cargo_accepted_at,     SLE_INT32,                 70, SL_MAX_VERSION),
  1897 
  2027 
  1898 	/* reserve extra space in savegame here. (currently 32 bytes) */
  2028 	/* reserve extra space in savegame here. (currently 32 bytes) */
  1899 	SLE_CONDNULL(32, 2, SL_MAX_VERSION),
  2029 	SLE_CONDNULL(32, 2, SL_MAX_VERSION),
  1900 
  2030 
  1901 	SLE_END()
  2031 	SLE_END()
  1914 
  2044 
  1915 static void Load_INDY()
  2045 static void Load_INDY()
  1916 {
  2046 {
  1917 	int index;
  2047 	int index;
  1918 
  2048 
  1919 	_total_industries = 0;
  2049 	ResetIndustryCounts();
  1920 
  2050 
  1921 	while ((index = SlIterateArray()) != -1) {
  2051 	while ((index = SlIterateArray()) != -1) {
  1922 		Industry *i;
  2052 		Industry *i;
  1923 
  2053 
  1924 		if (!AddBlockIfNeeded(&_Industry_pool, index))
  2054 		if (!AddBlockIfNeeded(&_Industry_pool, index))
  1925 			error("Industries: failed loading savegame: too many industries");
  2055 			error("Industries: failed loading savegame: too many industries");
  1926 
  2056 
  1927 		i = GetIndustry(index);
  2057 		i = GetIndustry(index);
  1928 		SlObject(i, _industry_desc);
  2058 		SlObject(i, _industry_desc);
  1929 
  2059 		IncIndustryTypeCount(i->type);
  1930 		_total_industries++;
       
  1931 	}
  2060 	}
  1932 }
  2061 }
  1933 
  2062 
  1934 extern const ChunkHandler _industry_chunk_handlers[] = {
  2063 extern const ChunkHandler _industry_chunk_handlers[] = {
  1935 	{ 'INDY', Save_INDY, Load_INDY, CH_ARRAY | CH_LAST},
  2064 	{ 'INDY', Save_INDY, Load_INDY, CH_ARRAY | CH_LAST},