319 image = dtss->image; |
319 image = dtss->image; |
320 pal = dtss->pal; |
320 pal = dtss->pal; |
321 |
321 |
322 if (IS_CUSTOM_SPRITE(image)) image += stage; |
322 if (IS_CUSTOM_SPRITE(image)) image += stage; |
323 |
323 |
324 if ((HASBIT(image, SPRITE_MODIFIER_OPAQUE) || !IsTransparencySet(TO_HOUSES)) && HASBIT(image, PALETTE_MODIFIER_COLOR)) { |
324 if ((HasBit(image, SPRITE_MODIFIER_OPAQUE) || !IsTransparencySet(TO_HOUSES)) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
325 if (pal == 0) { |
325 if (pal == 0) { |
326 const HouseSpec *hs = GetHouseSpecs(house_id); |
326 const HouseSpec *hs = GetHouseSpecs(house_id); |
327 if (HASBIT(hs->callback_mask, CBM_HOUSE_COLOUR)) { |
327 if (HasBit(hs->callback_mask, CBM_HOUSE_COLOUR)) { |
328 uint16 callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile); |
328 uint16 callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile); |
329 if (callback != CALLBACK_FAILED) { |
329 if (callback != CALLBACK_FAILED) { |
330 /* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */ |
330 /* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */ |
331 pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback; |
331 pal = HasBit(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback; |
332 } |
332 } |
333 } else { |
333 } else { |
334 pal = hs->random_colour[OriginalTileRandomiser(ti->x, ti->y)] + PALETTE_RECOLOR_START; |
334 pal = hs->random_colour[OriginalTileRandomiser(ti->x, ti->y)] + PALETTE_RECOLOR_START; |
335 } |
335 } |
336 } |
336 } |
378 { |
378 { |
379 const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
379 const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
380 byte animation_speed = hs->animation_speed; |
380 byte animation_speed = hs->animation_speed; |
381 bool frame_set_by_callback = false; |
381 bool frame_set_by_callback = false; |
382 |
382 |
383 if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) { |
383 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) { |
384 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
384 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
385 if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 2, 16); |
385 if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 2, 16); |
386 } |
386 } |
387 |
387 |
388 /* An animation speed of 2 means the animation frame changes 4 ticks, and |
388 /* An animation speed of 2 means the animation frame changes 4 ticks, and |
392 if (_tick_counter % (1 << animation_speed) != 0) return; |
392 if (_tick_counter % (1 << animation_speed) != 0) return; |
393 |
393 |
394 byte frame = GetHouseAnimationFrame(tile); |
394 byte frame = GetHouseAnimationFrame(tile); |
395 byte num_frames = GB(hs->animation_frames, 0, 7); |
395 byte num_frames = GB(hs->animation_frames, 0, 7); |
396 |
396 |
397 if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) { |
397 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) { |
398 uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0; |
398 uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0; |
399 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
399 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
400 |
400 |
401 if (callback_res != CALLBACK_FAILED) { |
401 if (callback_res != CALLBACK_FAILED) { |
402 frame_set_by_callback = true; |
402 frame_set_by_callback = true; |
421 } |
421 } |
422 |
422 |
423 if (!frame_set_by_callback) { |
423 if (!frame_set_by_callback) { |
424 if (frame < num_frames) { |
424 if (frame < num_frames) { |
425 frame++; |
425 frame++; |
426 } else if (frame == num_frames && HASBIT(hs->animation_frames, 7)) { |
426 } else if (frame == num_frames && HasBit(hs->animation_frames, 7)) { |
427 /* This animation loops, so start again from the beginning */ |
427 /* This animation loops, so start again from the beginning */ |
428 frame = 0; |
428 frame = 0; |
429 } else { |
429 } else { |
430 /* This animation doesn't loop, so stay here */ |
430 /* This animation doesn't loop, so stay here */ |
431 DeleteAnimatedTile(tile); |
431 DeleteAnimatedTile(tile); |
459 /* Human players are always allowed to remove buildings, as is water and |
459 /* Human players are always allowed to remove buildings, as is water and |
460 * anyone using the scenario editor. */ |
460 * anyone using the scenario editor. */ |
461 if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player)) |
461 if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player)) |
462 || _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true; |
462 || _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true; |
463 |
463 |
464 if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) { |
464 if (HasBit(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) { |
465 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
465 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
466 return (callback_res == CALLBACK_FAILED || callback_res == 0); |
466 return (callback_res == CALLBACK_FAILED || callback_res == 0); |
467 } else { |
467 } else { |
468 return !(hs->extra_flags & BUILDING_IS_PROTECTED); |
468 return !(hs->extra_flags & BUILDING_IS_PROTECTED); |
469 } |
469 } |
471 |
471 |
472 static void AnimationControl(TileIndex tile, uint16 random_bits) |
472 static void AnimationControl(TileIndex tile, uint16 random_bits) |
473 { |
473 { |
474 const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
474 const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile)); |
475 |
475 |
476 if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { |
476 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { |
477 uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random(); |
477 uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random(); |
478 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
478 uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
479 |
479 |
480 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
480 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
481 } |
481 } |
491 } |
491 } |
492 |
492 |
493 TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP); |
493 TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP); |
494 TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP_TOP); |
494 TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP_TOP); |
495 |
495 |
496 if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { |
496 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) { |
497 /* If this house is marked as having a synchronised callback, all the |
497 /* If this house is marked as having a synchronised callback, all the |
498 * tiles will have the callback called at once, rather than when the |
498 * tiles will have the callback called at once, rather than when the |
499 * tile loop reaches them. This should only be enabled for the northern |
499 * tile loop reaches them. This should only be enabled for the northern |
500 * tile, or strange things will happen (here, and in TTDPatch). */ |
500 * tile, or strange things will happen (here, and in TTDPatch). */ |
501 if (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) { |
501 if (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) { |
509 AnimationControl(tile, 0); |
509 AnimationControl(tile, 0); |
510 } |
510 } |
511 } |
511 } |
512 |
512 |
513 /* Check callback 21, which determines if a house should be destroyed. */ |
513 /* Check callback 21, which determines if a house should be destroyed. */ |
514 if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) { |
514 if (HasBit(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) { |
515 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
515 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
516 if (callback_res != CALLBACK_FAILED && callback_res > 0) { |
516 if (callback_res != CALLBACK_FAILED && callback_res > 0) { |
517 ClearTownHouse(GetTownByTile(tile), tile); |
517 ClearTownHouse(GetTownByTile(tile), tile); |
518 return false; |
518 return false; |
519 } |
519 } |