diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 47362b5448..36bb81c361 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -110,6 +110,7 @@ + diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index 262a0ef02b..9c13072575 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -531,6 +531,9 @@ Source\World + + Source\World + diff --git a/src/world/particle.c b/src/world/particle.c new file mode 100644 index 0000000000..1636b3ac42 --- /dev/null +++ b/src/world/particle.c @@ -0,0 +1,123 @@ +#include "../audio/audio.h" +#include "sprite.h" + +/** + * + * rct2: 0x006735A1 + */ +void crashed_vehicle_particle_create(rct_vehicle_colour colours, int x, int y, int z) +{ + rct_crashed_vehicle_particle *sprite = (rct_crashed_vehicle_particle*)create_sprite(2); + if (sprite != NULL) { + sprite->colour[0] = colours.body_colour; + sprite->colour[1] = colours.trim_colour; + sprite->sprite_width = 8; + sprite->sprite_height_negative = 8; + sprite->sprite_height_positive = 8; + sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z + 4, (rct_sprite*)sprite); + sprite->misc_identifier = SPRITE_MISC_CRASHED_VEHICLE_PARTICLE; + + sprite->var_26 = (rand() & 0xFF) * 12; + sprite->var_24 = (rand() & 0x7F) + 140; + sprite->var_2E = ((rand() & 0xFF) * 5) >> 8; + sprite->acceleration_x = (rand() & 0xFFFF) * 4; + sprite->acceleration_y = (rand() & 0xFFFF) * 4; + sprite->acceleration_z = (rand() & 0xFFFF) * 4 + 0x10000; + sprite->velocity_x = 0; + sprite->velocity_y = 0; + sprite->velocity_z = 0; + } +} + +/** + * + * rct: 0x00673298 + */ +void crashed_vehicle_particle_update(rct_crashed_vehicle_particle *particle) +{ + invalidate_sprite_0((rct_sprite*)particle); + particle->var_24--; + if (particle->var_24 == 0) { + sprite_remove((rct_sprite*)particle); + return; + } + + // Apply gravity + particle->acceleration_z -= 5041; + + // Apply air resistance + particle->acceleration_x -= (particle->acceleration_x / 256); + particle->acceleration_y -= (particle->acceleration_y / 256); + particle->acceleration_z -= (particle->acceleration_z / 256); + + // Update velocity and position + sint32 vx = particle->velocity_x + particle->acceleration_x; + sint32 vy = particle->velocity_y + particle->acceleration_y; + sint32 vz = particle->velocity_z + particle->acceleration_z; + + sint16 x = particle->x + (vx >> 16); + sint16 y = particle->y + (vy >> 16); + sint16 z = particle->z + (vz >> 16); + + particle->velocity_x = vx & 0xFFFF; + particle->velocity_y = vy & 0xFFFF; + particle->velocity_z = vz & 0xFFFF; + + // Check collision with land / water + uint32 waterLand = map_element_height(x, y); + sint16 landZ = (waterLand & 0xFFFF); + sint16 waterZ = (waterLand >> 16); + + if (waterZ != 0 && particle->z >= waterZ && z <= waterZ) { + // Splash + sound_play_panned(SOUND_WATER_2, 0x8001, particle->x, particle->y, waterZ); + crash_splash_create(particle->x, particle->y, waterZ); + sprite_remove((rct_sprite*)particle); + return; + } + + if (particle->z >= landZ && z <= landZ) { + // Bounce + particle->acceleration_z *= -1; + z = landZ; + } + sprite_move(x, y, z, (rct_sprite*)particle); + invalidate_sprite_0((rct_sprite*)particle); + + particle->var_26 += 85; + if (particle->var_26 >= 3072) { + particle->var_26 = 0; + } +} + +/** + * + * rct2: 0x00673699 + */ +void crash_splash_create(int x, int y, int z) +{ + rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2); + if (sprite != NULL) { + sprite->sprite_width = 33; + sprite->sprite_height_negative = 51; + sprite->sprite_height_positive = 16; + sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z + 3, (rct_sprite*)sprite); + sprite->misc_identifier = SPRITE_MISC_CRASH_SPLASH; + sprite->var_26 = 0; + } +} + +/** + * + * rct: 0x0067339D + */ +void crash_splash_update(rct_crash_splash *splash) +{ + invalidate_sprite_2((rct_sprite*)splash); + splash->var_26 += 85; + if (splash->var_26 >= 7168) { + sprite_remove((rct_sprite*)splash); + } +} diff --git a/src/world/sprite.c b/src/world/sprite.c index de0cb76716..cc93929c27 100644 --- a/src/world/sprite.c +++ b/src/world/sprite.c @@ -266,45 +266,81 @@ void move_sprite_to_list(rct_sprite *sprite, uint8 cl) * * rct: 0x00673200 */ -static void sub_673200(rct_sprite *sprite) +static void sprite_misc_0_update(rct_sprite *sprite) { - RCT2_CALLPROC_X(0x00673200, 0, 0, 0, 0, (int)sprite, 0, 0); + invalidate_sprite_2(sprite); + + int original_var24 = sprite->unknown.var_24; + sprite->unknown.var_24 += 0x5555; + if (sprite->unknown.var_24 < 0x5555) { + sprite_move(sprite->unknown.x, sprite->unknown.y, sprite->unknown.z + 1, sprite); + } + sprite->unknown.var_26 += 64; + if (sprite->unknown.var_26 >= (56 * 64)) { + sprite_remove(sprite); + } } /** * - * rct: 0x00673298 + * rct2: 0x0067363D */ -static void sub_673298(rct_sprite *sprite) +void sprite_misc_3_create(int x, int y, int z) { - RCT2_CALLPROC_X(0x00673298, 0, 0, 0, 0, (int)sprite, 0, 0); + rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2); + if (sprite != NULL) { + sprite->sprite_width = 44; + sprite->sprite_height_negative = 32; + sprite->sprite_height_positive = 34; + sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z + 4, (rct_sprite*)sprite); + sprite->misc_identifier = SPRITE_MISC_3; + sprite->var_26 = 0; + } } /** * * rct: 0x00673385 */ -static void sub_673385(rct_sprite *sprite) +static void sprite_misc_3_update(rct_sprite *sprite) { - RCT2_CALLPROC_X(0x00673385, 0, 0, 0, 0, (int)sprite, 0, 0); + invalidate_sprite_2(sprite); + sprite->unknown.var_26 += 128; + if (sprite->unknown.var_26 >= (36 * 128)) { + sprite_remove(sprite); + } } /** * - * rct: 0x0067339D + * rct2: 0x0067366B */ -static void sub_67339D(rct_sprite *sprite) +void sprite_misc_5_create(int x, int y, int z) { - RCT2_CALLPROC_X(0x0067339D, 0, 0, 0, 0, (int)sprite, 0, 0); + rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2); + if (sprite != NULL) { + sprite->sprite_width = 25; + sprite->sprite_height_negative = 85; + sprite->sprite_height_positive = 8; + sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; + sprite_move(x, y, z + 4, (rct_sprite*)sprite); + sprite->misc_identifier = SPRITE_MISC_5; + sprite->var_26 = 0; + } } /** * * rct: 0x006733B4 */ -static void sub_6733B4(rct_sprite *sprite) +static void sprite_misc_5_update(rct_sprite *sprite) { - RCT2_CALLPROC_X(0x006733B4, 0, 0, 0, 0, (int)sprite, 0, 0); + invalidate_sprite_2(sprite); + sprite->unknown.var_26 += 64; + if (sprite->unknown.var_26 >= (124 * 64)) { + sprite_remove(sprite); + } } /** @@ -315,22 +351,22 @@ void sprite_misc_update(rct_sprite *sprite) { switch (sprite->unknown.misc_identifier) { case SPRITE_MISC_0: - sub_673200(sprite); + sprite_misc_0_update(sprite); break; case SPRITE_MISC_MONEY_EFFECT: money_effect_update(&sprite->money_effect); break; - case SPRITE_MISC_2: - sub_673298(sprite); + case SPRITE_MISC_CRASHED_VEHICLE_PARTICLE: + crashed_vehicle_particle_update((rct_crashed_vehicle_particle*)sprite); break; case SPRITE_MISC_3: - sub_673385(sprite); + sprite_misc_3_update(sprite); break; - case SPRITE_MISC_4: - sub_67339D(sprite); + case SPRITE_MISC_CRASH_SPLASH: + crash_splash_update((rct_crash_splash*)sprite); break; case SPRITE_MISC_5: - sub_6733B4(sprite); + sprite_misc_5_update(sprite); break; case SPRITE_MISC_JUMPING_FOUNTAIN_WATER: case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW: @@ -528,39 +564,3 @@ void sub_6738E1(int x, int y, int z) { RCT2_CALLPROC_X(0x006738E1, x, 0, y, z, 0, 0, 0); } - -/** - * - * rct2: 0x0067363D - */ -void sprite_misc_3_create(int x, int y, int z) -{ - rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2); - if (sprite != NULL) { - sprite->sprite_width = 44; - sprite->sprite_height_negative = 32; - sprite->sprite_height_positive = 34; - sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite_move(x, y, z + 4, (rct_sprite*)sprite); - sprite->misc_identifier = SPRITE_MISC_3; - sprite->var_26 = 0; - } -} - -/** - * - * rct2: 0x0067366B - */ -void sprite_misc_5_create(int x, int y, int z) -{ - rct_unk_sprite *sprite = (rct_unk_sprite*)create_sprite(2); - if (sprite != NULL) { - sprite->sprite_width = 25; - sprite->sprite_height_negative = 85; - sprite->sprite_height_positive = 8; - sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite_move(x, y, z + 4, (rct_sprite*)sprite); - sprite->misc_identifier = SPRITE_MISC_5; - sprite->var_26 = 0; - } -} diff --git a/src/world/sprite.h b/src/world/sprite.h index 0e829b2922..b3eb9051de 100644 --- a/src/world/sprite.h +++ b/src/world/sprite.h @@ -71,7 +71,7 @@ typedef struct { uint8 sprite_direction; //direction of sprite? 0x1e uint8 pad_1F[3]; // 0x1f uint16 name_string_idx; // 0x22 - uint8 pad_24[2]; + uint16 var_24; uint16 var_26; uint8 var_28[3]; uint8 var_2B; @@ -211,6 +211,77 @@ typedef struct { uint16 wiggle; // 0x46 } rct_money_effect; +typedef struct { + uint8 sprite_identifier; // 0x00 + uint8 misc_identifier; // 0x01 + uint16 next_in_quadrant; // 0x02 + uint16 next; // 0x04 + uint16 previous; // 0x06 + uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... + // Height from center of sprite to bottom + uint8 sprite_height_negative; // 0x09 + uint16 sprite_index; // 0x0A + uint16 var_0C; + sint16 x; // 0x0E + sint16 y; // 0x10 + sint16 z; // 0x12 + // Width from center of sprite to edge + uint8 sprite_width; // 0x14 + // Height from center of sprite to top + uint8 sprite_height_positive; // 0x15 + sint16 sprite_left; // 0x16 + sint16 sprite_top; // 0x18 + sint16 sprite_right; // 0x1A + sint16 sprite_bottom; // 0x1C + uint8 sprite_direction; //direction of sprite? 0x1e + uint8 pad_1F[3]; // 0x1f + uint16 name_string_idx; // 0x22 + uint16 var_24; + uint16 var_26; + uint8 var_28[3]; + uint8 var_2B; + uint8 colour[2]; + uint16 var_2E; + sint16 velocity_x; // 0x30 + sint16 velocity_y; // 0x32 + sint16 velocity_z; // 0x34 + uint16 pad_36; + sint32 acceleration_x; // 0x38 + sint32 acceleration_y; // 0x3C + sint32 acceleration_z; // 0x40 + uint8 pad_44[0x2D]; + uint8 var_71; +} rct_crashed_vehicle_particle; + +typedef struct { + uint8 sprite_identifier; // 0x00 + uint8 misc_identifier; // 0x01 + uint16 next_in_quadrant; // 0x02 + uint16 next; // 0x04 + uint16 previous; // 0x06 + uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... + // Height from center of sprite to bottom + uint8 sprite_height_negative; // 0x09 + uint16 sprite_index; // 0x0A + uint16 var_0C; + sint16 x; // 0x0E + sint16 y; // 0x10 + sint16 z; // 0x12 + // Width from center of sprite to edge + uint8 sprite_width; // 0x14 + // Height from center of sprite to top + uint8 sprite_height_positive; // 0x15 + sint16 sprite_left; // 0x16 + sint16 sprite_top; // 0x18 + sint16 sprite_right; // 0x1A + sint16 sprite_bottom; // 0x1C + uint8 sprite_direction; //direction of sprite? 0x1e + uint8 pad_1F[3]; // 0x1f + uint16 name_string_idx; // 0x22 + uint16 var_24; + uint16 var_26; +} rct_crash_splash; + /** * Sprite structure. * size: 0x0100 @@ -225,14 +296,16 @@ typedef union { rct_duck duck; rct_jumping_fountain jumping_fountain; rct_money_effect money_effect; + rct_crashed_vehicle_particle crashed_vehicle_particle; + rct_crash_splash crash_splash; } rct_sprite; enum { SPRITE_MISC_0, SPRITE_MISC_MONEY_EFFECT, - SPRITE_MISC_2, // (related to vehicle crash, probably crash particles) + SPRITE_MISC_CRASHED_VEHICLE_PARTICLE, SPRITE_MISC_3, // (related to vehicle crash, probably crash particles) - SPRITE_MISC_4, // (related to vehicle crash, probably crash particles) + SPRITE_MISC_CRASH_SPLASH, SPRITE_MISC_5, // (related to vehicle crash, probably crash particles) SPRITE_MISC_JUMPING_FOUNTAIN_WATER, SPRITE_MISC_BALLOON, @@ -280,4 +353,12 @@ void duck_remove_all(); void money_effect_create(money32 value); void money_effect_update(rct_money_effect *moneyEffect); +/////////////////////////////////////////////////////////////// +// Crash particles +/////////////////////////////////////////////////////////////// +void crashed_vehicle_particle_create(rct_vehicle_colour colours, int x, int y, int z); +void crashed_vehicle_particle_update(rct_crashed_vehicle_particle *particle); +void crash_splash_create(int x, int y, int z); +void crash_splash_update(rct_crash_splash *splash); + #endif