src/newgrf_industrytiles.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
    20 #include "industry_map.h"
    20 #include "industry_map.h"
    21 #include "clear_map.h"
    21 #include "clear_map.h"
    22 #include "table/sprites.h"
    22 #include "table/sprites.h"
    23 #include "table/strings.h"
    23 #include "table/strings.h"
    24 #include "sprite.h"
    24 #include "sprite.h"
       
    25 #include "transparency.h"
    25 
    26 
    26 /**
    27 /**
    27  * Based on newhouses equivalent, but adapted for newindustries
    28  * Based on newhouses equivalent, but adapted for newindustries
    28  * @param parameter from callback.  It's in fact a pair of coordinates
    29  * @param parameter from callback.  It's in fact a pair of coordinates
    29  * @param tile TileIndex from which the callback was initiated
    30  * @param tile TileIndex from which the callback was initiated
   116 
   117 
   117 static uint32 IndustryTileGetRandomBits(const ResolverObject *object)
   118 static uint32 IndustryTileGetRandomBits(const ResolverObject *object)
   118 {
   119 {
   119 	const TileIndex tile = object->u.industry.tile;
   120 	const TileIndex tile = object->u.industry.tile;
   120 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
   121 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
   121 	return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : 0; //GetIndustryByTile(tile)->random_bits;
   122 	return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : GetIndustryByTile(tile)->random;
   122 }
   123 }
   123 
   124 
   124 static uint32 IndustryTileGetTriggers(const ResolverObject *object)
   125 static uint32 IndustryTileGetTriggers(const ResolverObject *object)
   125 {
   126 {
   126 	const TileIndex tile = object->u.industry.tile;
   127 	const TileIndex tile = object->u.industry.tile;
   127 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
   128 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0;
   128 	return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : 0; //GetIndustryByTile(tile)->triggers;
   129 	return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : GetIndustryByTile(tile)->random_triggers;
   129 }
   130 }
   130 
   131 
   131 static void IndustryTileSetTriggers(const ResolverObject *object, int triggers)
   132 static void IndustryTileSetTriggers(const ResolverObject *object, int triggers)
   132 {
   133 {
   133 	const TileIndex tile = object->u.industry.tile;
   134 	const TileIndex tile = object->u.industry.tile;
   134 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return;
   135 	if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return;
   135 
   136 
   136 	if (object->scope != VSG_SCOPE_SELF) {
   137 	if (object->scope == VSG_SCOPE_SELF) {
   137 		SetIndustryTriggers(tile, triggers);
   138 		SetIndustryTriggers(tile, triggers);
   138 	} else {
   139 	} else {
   139 		//GetIndustryByTile(tile)->triggers = triggers;
   140 		GetIndustryByTile(tile)->random_triggers = triggers;
   140 	}
   141 	}
   141 }
   142 }
   142 
   143 
   143 static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIndex tile, Industry *indus)
   144 static void NewIndustryTileResolver(ResolverObject *res, IndustryGfx gfx, TileIndex tile, Industry *indus)
   144 {
   145 {
   179 		image = dtss->image;
   180 		image = dtss->image;
   180 		pal   = dtss->pal;
   181 		pal   = dtss->pal;
   181 
   182 
   182 		if (IS_CUSTOM_SPRITE(image)) image += stage;
   183 		if (IS_CUSTOM_SPRITE(image)) image += stage;
   183 
   184 
   184 		if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
   185 		if (HasBit(image, PALETTE_MODIFIER_COLOR)) {
   185 			pal = GENERAL_SPRITE_COLOR(rnd_color);
   186 			if (pal == 0) {
       
   187 				pal = GENERAL_SPRITE_COLOR(rnd_color);
       
   188 			}
   186 		} else {
   189 		} else {
   187 			pal = PAL_NONE;
   190 			pal = PAL_NONE;
   188 		}
   191 		}
   189 
   192 
   190 		if ((byte)dtss->delta_z != 0x80) {
   193 		if ((byte)dtss->delta_z != 0x80) {
   191 			AddSortableSpriteToDraw(
   194 			AddSortableSpriteToDraw(
   192 				image, pal,
   195 				image, pal,
   193 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
   196 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
   194 				dtss->size_x, dtss->size_y,
   197 				dtss->size_x, dtss->size_y,
   195 				dtss->size_z, ti->z + dtss->delta_z,
   198 				dtss->size_z, ti->z + dtss->delta_z,
   196 				!HASBIT(image, SPRITE_MODIFIER_OPAQUE) && HASBIT(_transparent_opt, TO_INDUSTRIES)
   199 				!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_INDUSTRIES)
   197 			);
   200 			);
   198 		} else {
   201 		} else {
   199 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_INDUSTRIES));
   202 			AddChildSpriteScreen(image, pal, (byte)dtss->delta_x, (byte)dtss->delta_y, IsTransparencySet(TO_INDUSTRIES));
   200 		}
   203 		}
   201 	}
   204 	}
   202 }
   205 }
   203 
   206 
   204 uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile)
   207 uint16 GetIndustryTileCallback(CallbackID callback, uint32 param1, uint32 param2, IndustryGfx gfx_id, Industry *industry, TileIndex tile)
   222 	const SpriteGroup *group;
   225 	const SpriteGroup *group;
   223 	ResolverObject object;
   226 	ResolverObject object;
   224 
   227 
   225 	if (ti->tileh != SLOPE_FLAT) {
   228 	if (ti->tileh != SLOPE_FLAT) {
   226 		bool draw_old_one = true;
   229 		bool draw_old_one = true;
   227 		if (HASBIT(inds->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
   230 		if (HasBit(inds->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
   228 			/* Called to determine the type (if any) of foundation to draw for industry tile */
   231 			/* Called to determine the type (if any) of foundation to draw for industry tile */
   229 			uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, i, ti->tile);
   232 			uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, i, ti->tile);
   230 			draw_old_one = callback_res != 0;
   233 			draw_old_one = callback_res != 0;
   231 		}
   234 		}
   232 
   235 
   239 	if (group == NULL || group->type != SGT_TILELAYOUT) {
   242 	if (group == NULL || group->type != SGT_TILELAYOUT) {
   240 		return false;
   243 		return false;
   241 	} else {
   244 	} else {
   242 		/* Limit the building stage to the number of stages supplied. */
   245 		/* Limit the building stage to the number of stages supplied. */
   243 		byte stage = GetIndustryConstructionStage(ti->tile);
   246 		byte stage = GetIndustryConstructionStage(ti->tile);
   244 		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
   247 		stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
   245 		IndustryDrawTileLayout(ti, group, i->random_color, stage, gfx);
   248 		IndustryDrawTileLayout(ti, group, i->random_color, stage, gfx);
   246 		return true;
   249 		return true;
   247 	}
   250 	}
   248 }
   251 }
   249 
   252 
   262 		return !IsSlopeRefused(GetTileSlope(ind_tile, NULL), its->slopes_refused);
   265 		return !IsSlopeRefused(GetTileSlope(ind_tile, NULL), its->slopes_refused);
   263 	}
   266 	}
   264 	if (its->grf_prop.grffile->grf_version < 7) {
   267 	if (its->grf_prop.grffile->grf_version < 7) {
   265 		return callback_res != 0;
   268 		return callback_res != 0;
   266 	}
   269 	}
       
   270 
       
   271 	/* Copy some parameters from the registers to the error message text ref. stack */
       
   272 	SwitchToErrorRefStack();
       
   273 	PrepareTextRefStackUsage(4);
       
   274 	SwitchToNormalRefStack();
   267 
   275 
   268 	switch (callback_res) {
   276 	switch (callback_res) {
   269 		case 0x400: return true;
   277 		case 0x400: return true;
   270 		case 0x401: _error_message = STR_0239_SITE_UNSUITABLE;                 return false;
   278 		case 0x401: _error_message = STR_0239_SITE_UNSUITABLE;                 return false;
   271 		case 0x402: _error_message = STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST; return false;
   279 		case 0x402: _error_message = STR_0317_CAN_ONLY_BE_BUILT_IN_RAINFOREST; return false;
   279 	Industry *ind = GetIndustryByTile(tile);
   287 	Industry *ind = GetIndustryByTile(tile);
   280 	IndustryGfx gfx = GetIndustryGfx(tile);
   288 	IndustryGfx gfx = GetIndustryGfx(tile);
   281 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
   289 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
   282 	byte animation_speed = itspec->animation_speed;
   290 	byte animation_speed = itspec->animation_speed;
   283 
   291 
   284 	if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_SPEED)) {
   292 	if (HasBit(itspec->callback_flags, CBM_INDT_ANIM_SPEED)) {
   285 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIMATION_SPEED, 0, 0, gfx, ind, tile);
   293 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIMATION_SPEED, 0, 0, gfx, ind, tile);
   286 		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 0, 16);
   294 		if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 0, 16);
   287 	}
   295 	}
   288 
   296 
   289 	/* An animation speed of 2 means the animation frame changes 4 ticks, and
   297 	/* An animation speed of 2 means the animation frame changes 4 ticks, and
   290 	 * increasing this value by one doubles the wait. 0 is the minimum value
   298 	 * increasing this value by one doubles the wait. 0 is the minimum value
   291 	 * allowed for animation_speed, which corresponds to 30ms, and 16 is the
   299 	 * allowed for animation_speed, which corresponds to 30ms, and 16 is the
   292 	 * maximum, corresponding to around 33 minutes. */
   300 	 * maximum, corresponding to around 33 minutes. */
   293 	if ((_tick_counter % (1 << animation_speed)) != 0) return;
   301 	if ((_tick_counter % (1 << animation_speed)) != 0) return;
   294 
   302 
   295 	bool frame_set_by_callback = false;
   303 	bool frame_set_by_callback = false;
   296 	byte frame = GetIndustryAnimationState(tile);
   304 	byte frame = GetIndustryAnimationState(tile);
   297 	uint16 num_frames = GB(itspec->animation_info, 0, 8) + 1;
   305 	uint16 num_frames = GB(itspec->animation_info, 0, 8);
   298 
   306 
   299 	if (HASBIT(itspec->callback_flags, CBM_INDT_ANIM_NEXT_FRAME)) {
   307 	if (HasBit(itspec->callback_flags, CBM_INDT_ANIM_NEXT_FRAME)) {
   300 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_NEXT_FRAME, HASBIT(itspec->animation_special_flags, 0) ? Random() : 0, 0, gfx, ind, tile);
   308 		uint16 callback_res = GetIndustryTileCallback(CBID_INDTILE_ANIM_NEXT_FRAME, HasBit(itspec->animation_special_flags, 0) ? Random() : 0, 0, gfx, ind, tile);
   301 
   309 
   302 		if (callback_res != CALLBACK_FAILED) {
   310 		if (callback_res != CALLBACK_FAILED) {
   303 			frame_set_by_callback = true;
   311 			frame_set_by_callback = true;
   304 
   312 
   305 			switch (callback_res & 0xFF) {
   313 			switch (callback_res & 0xFF) {
   352 bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random)
   360 bool StartStopIndustryTileAnimation(TileIndex tile, IndustryAnimationTrigger iat, uint32 random)
   353 {
   361 {
   354 	IndustryGfx gfx = GetIndustryGfx(tile);
   362 	IndustryGfx gfx = GetIndustryGfx(tile);
   355 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
   363 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
   356 
   364 
   357 	if (!HASBIT(itspec->animation_triggers, iat)) return false;
   365 	if (!HasBit(itspec->animation_triggers, iat)) return false;
   358 
   366 
   359 	Industry *ind = GetIndustryByTile(tile);
   367 	Industry *ind = GetIndustryByTile(tile);
   360 	ChangeIndustryTileAnimationFrame(tile, iat, random, gfx, ind);
   368 	ChangeIndustryTileAnimationFrame(tile, iat, random, gfx, ind);
   361 	return true;
   369 	return true;
   362 }
   370 }
   375 		}
   383 		}
   376 	END_TILE_LOOP(tile, ind->width, ind->height, ind->xy)
   384 	END_TILE_LOOP(tile, ind->width, ind->height, ind->xy)
   377 
   385 
   378 	return ret;
   386 	return ret;
   379 }
   387 }
       
   388 
       
   389 static void DoTriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger, Industry *ind)
       
   390 {
       
   391 	ResolverObject object;
       
   392 
       
   393 	IndustryGfx gfx = GetIndustryGfx(tile);
       
   394 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
       
   395 
       
   396 	NewIndustryTileResolver(&object, gfx, tile, ind);
       
   397 
       
   398 	object.callback = CBID_RANDOM_TRIGGER;
       
   399 	object.trigger = trigger;
       
   400 
       
   401 	const SpriteGroup *group = Resolve(itspec->grf_prop.spritegroup, &object);
       
   402 	if (group == NULL) return;
       
   403 
       
   404 	byte new_random_bits = Random();
       
   405 	byte random_bits = GetIndustryRandomBits(tile);
       
   406 	random_bits &= ~object.reseed;
       
   407 	random_bits |= new_random_bits & object.reseed;
       
   408 	SetIndustryRandomBits(tile, random_bits);
       
   409 }
       
   410 
       
   411 void TriggerIndustryTile(TileIndex tile, IndustryTileTrigger trigger)
       
   412 {
       
   413 	DoTriggerIndustryTile(tile, trigger, GetIndustryByTile(tile));
       
   414 }
       
   415 
       
   416 extern void DoTriggerIndustry(Industry *ind, IndustryTileTrigger trigger);
       
   417 
       
   418 void TriggerIndustry(Industry *ind, IndustryTileTrigger trigger)
       
   419 {
       
   420 	BEGIN_TILE_LOOP(tile, ind->width, ind->height, ind->xy)
       
   421 		if (IsTileType(tile, MP_INDUSTRY) && GetIndustryIndex(tile) == ind->index) {
       
   422 			DoTriggerIndustryTile(tile, trigger, ind);
       
   423 		}
       
   424 	END_TILE_LOOP(tile, ind->width, ind->height, ind->xy)
       
   425 
       
   426 	DoTriggerIndustry(ind, trigger);
       
   427 }