diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 956fd8efe2..47362b5448 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -107,6 +107,9 @@ + + + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 8321dae4a5..262a0ef02b 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -522,6 +522,15 @@ Source\Windows + + Source\World + + + Source\World + + + Source\World + diff --git a/src/world/balloon.c b/src/world/balloon.c new file mode 100644 index 0000000000..62de010dfe --- /dev/null +++ b/src/world/balloon.c @@ -0,0 +1,83 @@ +#include "../audio/audio.h" +#include "../scenario.h" +#include "sprite.h" + +/** + * + * rct2: 0x006736C7 + */ +void create_balloon(int x, int y, int z, int colour, uint8 bl) +{ + rct_sprite* sprite = create_sprite(2); + if (sprite != NULL) { + sprite->balloon.var_14 = 13; + sprite->balloon.var_09 = 22; + sprite->balloon.var_15 = 11; + sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z, sprite); + sprite->balloon.misc_identifier = SPRITE_MISC_BALLOON; + sprite->balloon.var_26 = 0; + sprite->balloon.colour = colour; + sprite->balloon.popped = bl; + } +} + +void balloon_pop(rct_balloon *balloon) +{ + balloon->popped = 1; + balloon->var_26 = 0; + sound_play_panned(SOUND_BALLOON_POP, 0x8001, balloon->x, balloon->y, balloon->z); +} + +/** + * + * rct: 0x0067342C + */ +void balloon_update(rct_balloon *balloon) +{ + invalidate_sprite_2((rct_sprite*)balloon); + if (balloon->popped == 1) { + balloon->var_26 += 256; + if (balloon->var_26 >= 1280) + sprite_remove((rct_sprite*)balloon); + + return; + } + + int original_var26a = balloon->var_26a; + balloon->var_26a += 85; + if (original_var26a < 255 - 85) + return; + + balloon->var_26b++; + sprite_move(balloon->x, balloon->y, balloon->z + 1, (rct_sprite*)balloon); + + int maxZ = 1967 - ((balloon->x ^ balloon->y) & 31); + if (balloon->z < maxZ) + return; + + balloon_pop(balloon); +} + +/** + * + * rct2: 0x006E88ED + */ +void balloon_press(rct_balloon *balloon) +{ + if (balloon->popped == 1) + return; + + uint32 random = rand(); + if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) { + balloon_pop(balloon); + return; + } + + sprite_move( + balloon->x + ((random & 0x80000000) ? -6 : 6), + balloon->y, + balloon->z, + (rct_sprite*)balloon + ); +} diff --git a/src/world/duck.c b/src/world/duck.c new file mode 100644 index 0000000000..9f75a65ac5 --- /dev/null +++ b/src/world/duck.c @@ -0,0 +1,309 @@ +#include "../addresses.h" +#include "../audio/audio.h" +#include "../localisation/date.h" +#include "../scenario.h" +#include "sprite.h" + +enum { + DUCK_STATE_FLY_TO_WATER, + DUCK_STATE_SWIM, + DUCK_STATE_DRINK, + DUCK_STATE_DOUBLE_DRINK, + DUCK_STATE_FLY_AWAY +}; + +static void duck_update_fly_to_water(rct_duck *duck); +static void duck_update_swim(rct_duck *duck); +static void duck_update_drink(rct_duck *duck); +static void duck_update_double_drink(rct_duck *duck); +static void duck_update_fly_away(rct_duck *duck); + +// rct2: 0x009A3B04 +static const rct_xy16 duck_move_offset[] = { + { -1, 0 }, + { 0, 1 }, + { 1, 0 }, + { 0, -1 } +}; + +// rct2: 0x0097F073 +static const uint8 duck_drink_animation[] = { + 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 255 +}; + +// rct2: 0x0097F08C +static const uint8 duck_double_drink_animation[] = { + 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, + 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 0, 0, 0, 0, 255 +}; + +/** + * + * rct2: 0x0067440F + */ +void create_duck(int targetX, int targetY) +{ + rct_sprite* sprite = create_sprite(2); + if (sprite != NULL) { + sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite->duck.misc_identifier = SPRITE_MISC_DUCK; + sprite->duck.var_14 = 9; + sprite->duck.var_09 = 0xC; + sprite->duck.var_15 = 9; + int offset_xy = scenario_rand() & 0x1E; + targetX += offset_xy; + targetY += offset_xy; + sprite->duck.target_x = targetX; + sprite->duck.target_y = targetY; + uint8 direction = scenario_rand() & 3; + switch (direction) { + case 0: + targetX = 8191 - (scenario_rand() & 0x3F); + break; + case 1: + targetY = scenario_rand() & 0x3F; + break; + case 2: + targetX = scenario_rand() & 0x3F; + break; + case 3: + targetY = 8191 - (scenario_rand() & 0x3F); + break; + } + sprite->duck.sprite_direction = direction << 3; + sprite_move(targetX, targetY, 496, sprite); + sprite->duck.state = DUCK_STATE_FLY_TO_WATER; + sprite->duck.var_26 = 0; + } +} + +/** + * + * rct: 0x006740E8 + */ +void duck_update(rct_duck *duck) +{ + switch (duck->state) { + case DUCK_STATE_FLY_TO_WATER: + duck_update_fly_to_water(duck); + break; + case DUCK_STATE_SWIM: + duck_update_swim(duck); + break; + case DUCK_STATE_DRINK: + duck_update_drink(duck); + break; + case DUCK_STATE_DOUBLE_DRINK: + duck_update_double_drink(duck); + break; + case DUCK_STATE_FLY_AWAY: + duck_update_fly_away(duck); + break; + } +} + +static void duck_invalidate(rct_duck *duck) +{ + invalidate_sprite_0((rct_sprite*)duck); +} + +/** + * + * rct: 0x00674108 + */ +static void duck_update_fly_to_water(rct_duck *duck) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) + return; + + duck->var_26++; + if (duck->var_26 >= 6) + duck->var_26 = 0; + + duck_invalidate(duck); + int manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y); + int direction = duck->sprite_direction >> 3; + int x = duck->x + duck_move_offset[direction].x; + int y = duck->y + duck_move_offset[direction].y; + int manhattanDistanceN = abs(duck->target_x - x) + abs(duck->target_y - y); + + rct_map_element *mapElement = map_get_surface_element_at(duck->target_x >> 5, duck->target_y >> 5); + int waterHeight = mapElement->properties.surface.terrain & 0x1F; + if (waterHeight == 0) { + duck->state = DUCK_STATE_FLY_AWAY; + duck_update_fly_away(duck); + return; + } + waterHeight <<= 4; + int z = abs(duck->z - waterHeight); + + if (manhattanDistanceN <= manhattanDistance) { + if (z > manhattanDistanceN) { + z = duck->z - 2; + if (waterHeight >= duck->z) + z += 4; + + duck->var_26 = 1; + } else { + z = duck->z; + } + sprite_move(x, y, z, (rct_sprite*)duck); + duck_invalidate(duck); + } else { + if (z > 4) { + duck->state = DUCK_STATE_FLY_AWAY; + duck_update_fly_away(duck); + } else { + duck->state = DUCK_STATE_SWIM; + duck->var_26 = 0; + duck_update_swim(duck); + } + } +} + +/** + * + * rct: 0x00674282 + */ +static void duck_update_swim(rct_duck *duck) +{ + if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3) + return; + + uint32 randomNumber = scenario_rand(); + if ((randomNumber & 0xFFFF) < 0x666) { + if (randomNumber & 0x80000000) { + duck->state = DUCK_STATE_DOUBLE_DRINK; + duck->var_26 = -1; + duck_update_double_drink(duck); + } else { + duck->state = DUCK_STATE_DRINK; + duck->var_26 = -1; + duck_update_drink(duck); + } + return; + } + + int currentMonth = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16)); + if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) { + duck->state = DUCK_STATE_FLY_AWAY; + duck_update_fly_away(duck); + return; + } + + duck_invalidate(duck); + int landZ = map_element_height(duck->x, duck->y); + int waterZ = (landZ >> 16) & 0xFFFF; + landZ &= 0xFFFF; + + if (duck->z < landZ || waterZ == 0) { + duck->state = DUCK_STATE_FLY_AWAY; + duck_update_fly_away(duck); + return; + } + + duck->z = waterZ; + randomNumber = scenario_rand(); + if ((randomNumber & 0xFFFF) <= 0xAAA) { + randomNumber >>= 16; + duck->sprite_direction = randomNumber & 0x18; + } + + int direction = duck->sprite_direction >> 3; + int x = duck->x + duck_move_offset[direction].x; + int y = duck->y + duck_move_offset[direction].y; + landZ = map_element_height(x, y); + waterZ = (landZ >> 16) & 0xFFFF; + landZ &= 0xFFFF; + + if (duck->z < landZ || duck->z != waterZ) + return; + + sprite_move(x, y, waterZ, (rct_sprite*)duck); + duck_invalidate(duck); +} + +/** + * + * rct: 0x00674357 + */ +static void duck_update_drink(rct_duck *duck) +{ + duck->var_26++; + if (duck_drink_animation[duck->var_26] == 255) { + duck->state = DUCK_STATE_SWIM; + duck->var_26 = 0; + duck_update_swim(duck); + } else { + duck_invalidate(duck); + } +} + +/** + * + * rct: 0x00674372 + */ +static void duck_update_double_drink(rct_duck *duck) +{ + duck->var_26++; + if (duck_double_drink_animation[duck->var_26] == 255) { + duck->state = DUCK_STATE_SWIM; + duck->var_26 = 0; + duck_update_swim(duck); + } else { + duck_invalidate(duck); + } +} + +/** + * + * rct: 0x0067438D + */ +static void duck_update_fly_away(rct_duck *duck) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) + return; + + duck->var_26++; + if (duck->var_26 >= 6) + duck->var_26 = 0; + + duck_invalidate(duck); + int direction = duck->sprite_direction >> 3; + int x = duck->x + (duck_move_offset[direction].x * 2); + int y = duck->y + (duck_move_offset[direction].y * 2); + if (x < 0 || y < 0 || x >= (32 * 256) || y >= (32 * 256)) { + sprite_remove((rct_sprite*)duck); + return; + } + + int z = z = min(duck->z + 2, 496); + sprite_move(x, y, z, (rct_sprite*)duck); + duck_invalidate(duck); +} + +/** + * + * rct: 0x006E895D + */ +void duck_press(rct_duck *duck) +{ + sound_play_panned(SOUND_QUACK, 0x8001, duck->x, duck->y, duck->z); +} + +/** + * + * rct: 0x00674576 + */ +void duck_remove_all() +{ + rct_unk_sprite* sprite; + uint16 spriteIndex, nextSpriteIndex; + + for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { + sprite = &(g_sprite_list[spriteIndex].unknown); + nextSpriteIndex = sprite->next; + if (sprite->misc_identifier == SPRITE_MISC_DUCK) + sprite_remove((rct_sprite*)sprite); + } +} diff --git a/src/world/money_effect.c b/src/world/money_effect.c new file mode 100644 index 0000000000..132d6293a3 --- /dev/null +++ b/src/world/money_effect.c @@ -0,0 +1,109 @@ +#include "../localisation/localisation.h" +#include "../interface/viewport.h" +#include "../interface/window.h" +#include "sprite.h" + +static const rct_xy16 _moneyEffectMoveOffset[] = { + { 1, -1 }, + { 1, 1 }, + { -1, 1 }, + { -1, -1 } +}; + +/** + * + * rct: 0x0067351F + */ +void money_effect_create_at(money32 value, int x, int y, int z) +{ + rct_money_effect *moneyEffect; + rct_string_id stringId; + char buffer[128]; + + moneyEffect = (rct_money_effect*)create_sprite(2); + if (moneyEffect == NULL) + return; + + moneyEffect->value = value; + moneyEffect->var_14 = 64; + moneyEffect->var_09 = 20; + moneyEffect->var_15 = 30; + moneyEffect->sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z, (rct_sprite*)moneyEffect); + moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT; + moneyEffect->num_movements = 0; + moneyEffect->move_delay = 0; + + stringId = 1388; + if (value < 0) { + value *= -1; + stringId = 1399; + } + format_string(buffer, stringId, &value); + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; + moneyEffect->offset_x = -(gfx_get_string_width(buffer) / 2); + moneyEffect->wiggle = 0; +} + +/** + * + * rct: 0x0069C5D0 + */ +void money_effect_create(money32 value) +{ + rct_window *mainWindow; + rct_viewport *mainViewport; + rct_xyz16 mapPosition; + + mapPosition.x = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16); + mapPosition.y = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16); + mapPosition.z = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16); + if (mapPosition.x == (sint16)0x8000) { + mainWindow = window_get_main(); + if (mainWindow == NULL) + return; + + mainViewport = mainWindow->viewport; + screen_get_map_xy( + mainViewport->x + (mainViewport->width / 2), + mainViewport->y + (mainViewport->height / 2), + &mapPosition.x, + &mapPosition.y, + NULL + ); + if (mapPosition.x == (sint16)0x8000) + return; + + mapPosition.z = map_element_height(mapPosition.x, mapPosition.y) & 0xFFFF; + } + mapPosition.z += 10; + money_effect_create_at(-value, mapPosition.x, mapPosition.y, mapPosition.z); +} + +/** + * + * rct: 0x00673232 + */ +void money_effect_update(rct_money_effect *moneyEffect) +{ + invalidate_sprite_2((rct_sprite*)moneyEffect); + moneyEffect->wiggle++; + if (moneyEffect->wiggle >= 22) + moneyEffect->wiggle = 0; + + moneyEffect->move_delay++; + if (moneyEffect->move_delay < 2) + return; + + moneyEffect->move_delay = 0; + int x = moneyEffect->x + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].x; + int y = moneyEffect->y + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].y; + int z = moneyEffect->z; + sprite_move(x, y, z, (rct_sprite*)moneyEffect); + + moneyEffect->num_movements++; + if (moneyEffect->num_movements < 55) + return; + + sprite_remove((rct_sprite*)moneyEffect); +} diff --git a/src/world/sprite.c b/src/world/sprite.c index 0b8570e5bb..de0cb76716 100644 --- a/src/world/sprite.c +++ b/src/world/sprite.c @@ -27,500 +27,9 @@ #include "fountain.h" #include "sprite.h" -enum { - DUCK_STATE_FLY_TO_WATER, - DUCK_STATE_SWIM, - DUCK_STATE_DRINK, - DUCK_STATE_DOUBLE_DRINK, - DUCK_STATE_FLY_AWAY -}; - rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite); -static void duck_update_fly_to_water(rct_duck *duck); -static void duck_update_swim(rct_duck *duck); -static void duck_update_drink(rct_duck *duck); -static void duck_update_double_drink(rct_duck *duck); -static void duck_update_fly_away(rct_duck *duck); - -/** - * - * rct2: 0x006736C7 - */ -void create_balloon(int x, int y, int z, int colour, uint8 bl) -{ - rct_sprite* sprite = create_sprite(2); - if (sprite != NULL) - { - sprite->balloon.var_14 = 13; - sprite->balloon.var_09 = 22; - sprite->balloon.var_15 = 11; - sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite_move(x, y, z, sprite); - sprite->balloon.misc_identifier = SPRITE_MISC_BALLOON; - sprite->balloon.var_26 = 0; - sprite->balloon.colour = colour; - sprite->balloon.popped = bl; - } -} - -void balloon_pop(rct_balloon *balloon) -{ - balloon->popped = 1; - balloon->var_26 = 0; - sound_play_panned(SOUND_BALLOON_POP, 0x8001, balloon->x, balloon->y, balloon->z); -} - -/** - * - * rct: 0x0067342C - */ -void balloon_update(rct_balloon *balloon) -{ - invalidate_sprite_2((rct_sprite*)balloon); - if (balloon->popped == 1) { - balloon->var_26 += 256; - if (balloon->var_26 >= 1280) - sprite_remove((rct_sprite*)balloon); - - return; - } - - int original_var26a = balloon->var_26a; - balloon->var_26a += 85; - if (original_var26a < 255 - 85) - return; - - balloon->var_26b++; - sprite_move(balloon->x, balloon->y, balloon->z + 1, (rct_sprite*)balloon); - - int maxZ = 1967 - ((balloon->x ^ balloon->y) & 31); - if (balloon->z < maxZ) - return; - - balloon_pop(balloon); -} - -/** - * - * rct2: 0x006E88ED - */ -void balloon_press(rct_balloon *balloon) -{ - if (balloon->popped == 1) - return; - - uint32 random = scenario_rand(); - if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) { - balloon_pop(balloon); - return; - } - - sprite_move( - balloon->x + ((random & 0x80000000) ? -6 : 6), - balloon->y, - balloon->z, - (rct_sprite*)balloon - ); -} - -// rct2: 0x009A3B04 -static const rct_xy16 duck_move_offset[] = { - { -1, 0 }, - { 0, 1 }, - { 1, 0 }, - { 0, -1 } -}; - -// rct2: 0x0097F073 -static const uint8 duck_drink_animation[] = { - 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 255 -}; - -// rct2: 0x0097F08C -static const uint8 duck_double_drink_animation[] = { - 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, - 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 0, 0, 0, 0, 255 -}; - -/** - * - * rct2: 0x0067440F - */ -void create_duck(int targetX, int targetY) -{ - rct_sprite* sprite = create_sprite(2); - if (sprite != NULL) { - sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite->duck.misc_identifier = SPRITE_MISC_DUCK; - sprite->duck.var_14 = 9; - sprite->duck.var_09 = 0xC; - sprite->duck.var_15 = 9; - int offset_xy = scenario_rand() & 0x1E; - targetX += offset_xy; - targetY += offset_xy; - sprite->duck.target_x = targetX; - sprite->duck.target_y = targetY; - uint8 direction = scenario_rand() & 3; - switch (direction) - { - case 0: - targetX = 8191 - (scenario_rand() & 0x3F); - break; - case 1: - targetY = scenario_rand() & 0x3F; - break; - case 2: - targetX = scenario_rand() & 0x3F; - break; - case 3: - targetY = 8191 - (scenario_rand() & 0x3F); - break; - } - sprite->duck.sprite_direction = direction << 3; - sprite_move(targetX, targetY, 496, sprite); - sprite->duck.state = DUCK_STATE_FLY_TO_WATER; - sprite->duck.var_26 = 0; - } -} - -/** - * - * rct: 0x006740E8 - */ -void duck_update(rct_duck *duck) -{ - switch (duck->state) { - case DUCK_STATE_FLY_TO_WATER: - duck_update_fly_to_water(duck); - break; - case DUCK_STATE_SWIM: - duck_update_swim(duck); - break; - case DUCK_STATE_DRINK: - duck_update_drink(duck); - break; - case DUCK_STATE_DOUBLE_DRINK: - duck_update_double_drink(duck); - break; - case DUCK_STATE_FLY_AWAY: - duck_update_fly_away(duck); - break; - } -} - -static void duck_invalidate(rct_duck *duck) -{ - invalidate_sprite_0((rct_sprite*)duck); -} - -/** - * - * rct: 0x00674108 - */ -static void duck_update_fly_to_water(rct_duck *duck) -{ - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) - return; - - duck->var_26++; - if (duck->var_26 >= 6) - duck->var_26 = 0; - - duck_invalidate(duck); - int manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y); - int direction = duck->sprite_direction >> 3; - int x = duck->x + duck_move_offset[direction].x; - int y = duck->y + duck_move_offset[direction].y; - int manhattanDistanceN = abs(duck->target_x - x) + abs(duck->target_y - y); - - rct_map_element *mapElement = map_get_surface_element_at(duck->target_x >> 5, duck->target_y >> 5); - int waterHeight = mapElement->properties.surface.terrain & 0x1F; - if (waterHeight == 0) { - duck->state = DUCK_STATE_FLY_AWAY; - duck_update_fly_away(duck); - return; - } - waterHeight <<= 4; - int z = abs(duck->z - waterHeight); - - if (manhattanDistanceN <= manhattanDistance) { - if (z > manhattanDistanceN) { - z = duck->z - 2; - if (waterHeight >= duck->z) - z += 4; - - duck->var_26 = 1; - } else { - z = duck->z; - } - sprite_move(x, y, z, (rct_sprite*)duck); - duck_invalidate(duck); - } else { - if (z > 4) { - duck->state = DUCK_STATE_FLY_AWAY; - duck_update_fly_away(duck); - } else { - duck->state = DUCK_STATE_SWIM; - duck->var_26 = 0; - duck_update_swim(duck); - } - } -} - -/** - * - * rct: 0x00674282 - */ -static void duck_update_swim(rct_duck *duck) -{ - if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3) - return; - - uint32 randomNumber = scenario_rand(); - if ((randomNumber & 0xFFFF) < 0x666) { - if (randomNumber & 0x80000000) { - duck->state = DUCK_STATE_DOUBLE_DRINK; - duck->var_26 = -1; - duck_update_double_drink(duck); - } else { - duck->state = DUCK_STATE_DRINK; - duck->var_26 = -1; - duck_update_drink(duck); - } - return; - } - - int currentMonth = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16)); - if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) { - duck->state = DUCK_STATE_FLY_AWAY; - duck_update_fly_away(duck); - return; - } - - duck_invalidate(duck); - int landZ = map_element_height(duck->x, duck->y); - int waterZ = (landZ >> 16) & 0xFFFF; - landZ &= 0xFFFF; - - if (duck->z < landZ || waterZ == 0) { - duck->state = DUCK_STATE_FLY_AWAY; - duck_update_fly_away(duck); - return; - } - - duck->z = waterZ; - randomNumber = scenario_rand(); - if ((randomNumber & 0xFFFF) <= 0xAAA) { - randomNumber >>= 16; - duck->sprite_direction = randomNumber & 0x18; - } - - int direction = duck->sprite_direction >> 3; - int x = duck->x + duck_move_offset[direction].x; - int y = duck->y + duck_move_offset[direction].y; - landZ = map_element_height(x, y); - waterZ = (landZ >> 16) & 0xFFFF; - landZ &= 0xFFFF; - - if (duck->z < landZ || duck->z != waterZ) - return; - - sprite_move(x, y, waterZ, (rct_sprite*)duck); - duck_invalidate(duck); -} - -/** - * - * rct: 0x00674357 - */ -static void duck_update_drink(rct_duck *duck) -{ - duck->var_26++; - if (duck_drink_animation[duck->var_26] == 255) { - duck->state = DUCK_STATE_SWIM; - duck->var_26 = 0; - duck_update_swim(duck); - } else { - duck_invalidate(duck); - } -} - -/** - * - * rct: 0x00674372 - */ -static void duck_update_double_drink(rct_duck *duck) -{ - duck->var_26++; - if (duck_double_drink_animation[duck->var_26] == 255) { - duck->state = DUCK_STATE_SWIM; - duck->var_26 = 0; - duck_update_swim(duck); - } else { - duck_invalidate(duck); - } -} - -/** - * - * rct: 0x0067438D - */ -static void duck_update_fly_away(rct_duck *duck) -{ - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) - return; - - duck->var_26++; - if (duck->var_26 >= 6) - duck->var_26 = 0; - - duck_invalidate(duck); - int direction = duck->sprite_direction >> 3; - int x = duck->x + (duck_move_offset[direction].x * 2); - int y = duck->y + (duck_move_offset[direction].y * 2); - if (x < 0 || y < 0 || x >= (32 * 256) || y >= (32 * 256)) { - sprite_remove((rct_sprite*)duck); - return; - } - - int z = z = min(duck->z + 2, 496); - sprite_move(x, y, z, (rct_sprite*)duck); - duck_invalidate(duck); -} - -/** - * - * rct: 0x006E895D - */ -void duck_press(rct_duck *duck) -{ - sound_play_panned(SOUND_QUACK, 0x8001, duck->x, duck->y, duck->z); -} - -/** - * - * rct: 0x00674576 - */ -void duck_remove_all() -{ - rct_unk_sprite* sprite; - uint16 spriteIndex, nextSpriteIndex; - - for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { - sprite = &(g_sprite_list[spriteIndex].unknown); - nextSpriteIndex = sprite->next; - if (sprite->misc_identifier == SPRITE_MISC_DUCK) - sprite_remove((rct_sprite*)sprite); - } -} - -static const rct_xy16 _moneyEffectMoveOffset[] = { - { 1, -1 }, - { 1, 1 }, - { -1, 1 }, - { -1, -1 } -}; - -/** - * - * rct: 0x0067351F - */ -void money_effect_create_at(money32 value, int x, int y, int z) -{ - rct_money_effect *moneyEffect; - rct_string_id stringId; - char buffer[128]; - - moneyEffect = (rct_money_effect*)create_sprite(2); - if (moneyEffect == NULL) - return; - - moneyEffect->value = value; - moneyEffect->var_14 = 64; - moneyEffect->var_09 = 20; - moneyEffect->var_15 = 30; - moneyEffect->sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite_move(x, y, z, (rct_sprite*)moneyEffect); - moneyEffect->misc_identifier = SPRITE_MISC_MONEY_EFFECT; - moneyEffect->num_movements = 0; - moneyEffect->move_delay = 0; - - stringId = 1388; - if (value < 0) { - value *= -1; - stringId = 1399; - } - format_string(buffer, stringId, &value); - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; - moneyEffect->offset_x = -(gfx_get_string_width(buffer) / 2); - moneyEffect->wiggle = 0; -} - -/** - * - * rct: 0x0069C5D0 - */ -void money_effect_create(money32 value) -{ - rct_window *mainWindow; - rct_viewport *mainViewport; - rct_xyz16 mapPosition; - - mapPosition.x = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16); - mapPosition.y = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16); - mapPosition.z = RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16); - if (mapPosition.x == (sint16)0x8000) { - mainWindow = window_get_main(); - if (mainWindow == NULL) - return; - - mainViewport = mainWindow->viewport; - screen_get_map_xy( - mainViewport->x + (mainViewport->width / 2), - mainViewport->y + (mainViewport->height / 2), - &mapPosition.x, - &mapPosition.y, - NULL - ); - if (mapPosition.x == (sint16)0x8000) - return; - - mapPosition.z = map_element_height(mapPosition.x, mapPosition.y) & 0xFFFF; - } - mapPosition.z += 10; - money_effect_create_at(-value, mapPosition.x, mapPosition.y, mapPosition.z); -} - -/** - * - * rct: 0x00673232 - */ -void money_effect_update(rct_money_effect *moneyEffect) -{ - invalidate_sprite_2((rct_sprite*)moneyEffect); - moneyEffect->wiggle++; - if (moneyEffect->wiggle >= 22) - moneyEffect->wiggle = 0; - - moneyEffect->move_delay++; - if (moneyEffect->move_delay < 2) - return; - - moneyEffect->move_delay = 0; - int x = moneyEffect->x + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].x; - int y = moneyEffect->y + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].y; - int z = moneyEffect->z; - sprite_move(x, y, z, (rct_sprite*)moneyEffect); - - moneyEffect->num_movements++; - if (moneyEffect->num_movements < 55) - return; - - sprite_remove((rct_sprite*)moneyEffect); -} - -void invalidate_sprite_max_zoom(rct_sprite *sprite, int maxZoom) +static void invalidate_sprite_max_zoom(rct_sprite *sprite, int maxZoom) { if (sprite->unknown.sprite_left == (sint16)0x8000) return; diff --git a/src/world/sprite.h b/src/world/sprite.h index 2ba74fe34f..0e829b2922 100644 --- a/src/world/sprite.h +++ b/src/world/sprite.h @@ -243,12 +243,6 @@ enum { // rct2: 0x010E63BC extern rct_sprite* g_sprite_list; -void create_balloon(int x, int y, int z, int colour, uint8 bl); -void balloon_press(rct_balloon *balloon); -void create_duck(int targetX, int targetY); -void duck_press(rct_duck *duck); -void duck_remove_all(); -void money_effect_create(money32 value); rct_sprite *create_sprite(uint8 bl); void reset_sprite_list(); void reset_0x69EBE4(); @@ -265,4 +259,25 @@ void sub_6738E1(int x, int y, int z); void sprite_misc_3_create(int x, int y, int z); void sprite_misc_5_create(int x, int y, int z); +/////////////////////////////////////////////////////////////// +// Balloon +/////////////////////////////////////////////////////////////// +void create_balloon(int x, int y, int z, int colour, uint8 bl); +void balloon_update(rct_balloon *balloon); +void balloon_press(rct_balloon *balloon); + +/////////////////////////////////////////////////////////////// +// Duck +/////////////////////////////////////////////////////////////// +void create_duck(int targetX, int targetY); +void duck_update(rct_duck *duck); +void duck_press(rct_duck *duck); +void duck_remove_all(); + +/////////////////////////////////////////////////////////////// +// Money effect +/////////////////////////////////////////////////////////////// +void money_effect_create(money32 value); +void money_effect_update(rct_money_effect *moneyEffect); + #endif