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 } |