diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 3a650aa77d..0f494356a3 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -138,6 +138,7 @@
+
@@ -204,6 +205,7 @@
+
diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters
index fce4be6300..6bc6dd78b5 100644
--- a/projects/openrct2.vcxproj.filters
+++ b/projects/openrct2.vcxproj.filters
@@ -345,7 +345,6 @@
Source\Windows
-
Source\Windows
@@ -371,7 +370,7 @@
Source\World
-
+
Source
@@ -427,6 +426,9 @@
Source\Windows
+
+ Source\World
+
@@ -627,5 +629,8 @@
Source\World
+
+ Source\World
+
\ No newline at end of file
diff --git a/src/game.c b/src/game.c
index dc702c2d7e..74ddbbc797 100644
--- a/src/game.c
+++ b/src/game.c
@@ -49,6 +49,7 @@
#include "windows/error.h"
#include "windows/tooltip.h"
#include "world/climate.h"
+#include "world/map_animation.h"
#include "world/park.h"
#include "world/sprite.h"
#include "world/water.h"
@@ -317,7 +318,7 @@ void game_logic_update()
research_update();
ride_ratings_update_all();
ride_measurements_update();
- map_invalidate_animations();
+ map_animation_invalidate_all();
vehicle_sounds_update();
peep_update_crowd_noise();
climate_update_sound();
diff --git a/src/ride/ride_data.c b/src/ride/ride_data.c
index 5ba1213a73..83e8f50742 100644
--- a/src/ride/ride_data.c
+++ b/src/ride/ride_data.c
@@ -864,4 +864,19 @@ const uint8 RideAvailableBreakdowns[] = {
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 58 Mine Ride
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 59 LIM Launched Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE) // 60 (none)
+};
+
+const rct_ride_entrance_definition RideEntranceDefinitions[12] = {
+ { 22664, 32, 2 }, // RIDE_ENTRANCE_STYLE_PLAIN
+ { 22760, 31, 21 }, // RIDE_ENTRANCE_STYLE_WOODEN
+ { 22680, 43, 2 }, // RIDE_ENTRANCE_STYLE_CANVAS_TENT
+ { 22728, 43, 19 }, // RIDE_ENTRANCE_STYLE_CASTLE_GREY
+ { 22712, 33, 19 }, // RIDE_ENTRANCE_STYLE_CASTLE_BROWN
+ { 22776, 32, 19 }, // RIDE_ENTRANCE_STYLE_JUNGLE
+ { 22744, 32, 20 }, // RIDE_ENTRANCE_STYLE_LOG_CABIN
+ { 22696, 34, 19 }, // RIDE_ENTRANCE_STYLE_CLASSICAL_ROMAN
+ { 22792, 40, 22 }, // RIDE_ENTRANCE_STYLE_ABSTRACT
+ { 22824, 35, 23 }, // RIDE_ENTRANCE_STYLE_SNOW_ICE
+ { 22840, 33, 19 }, // RIDE_ENTRANCE_STYLE_PAGODA
+ { 22856, 33, 2 } // RIDE_ENTRANCE_STYLE_SPACE
};
\ No newline at end of file
diff --git a/src/ride/ride_data.h b/src/ride/ride_data.h
index c2e81cc9f8..c5cac5fb9c 100644
--- a/src/ride/ride_data.h
+++ b/src/ride/ride_data.h
@@ -30,6 +30,12 @@ typedef struct {
rct_string_id unk_name;
} rct_ride_name_convention;
+typedef struct {
+ uint32 spriteIndex;
+ uint16 height;
+ uint16 var_06;
+} rct_ride_entrance_definition;
+
extern const bool hasRunningTrack[0x60];
extern const uint8 initialUpkeepCosts[0x60];
extern const uint8 costPerTrackPiece[0x60];
@@ -42,4 +48,6 @@ extern const rct_ride_name_convention RideNameConvention[96];
extern const uint8 RideAvailableModes[];
extern const uint8 RideAvailableBreakdowns[];
+extern const rct_ride_entrance_definition RideEntranceDefinitions[12];
+
#endif
\ No newline at end of file
diff --git a/src/windows/ride.c b/src/windows/ride.c
index de63e8bb05..0a949ee097 100644
--- a/src/windows/ride.c
+++ b/src/windows/ride.c
@@ -4132,7 +4132,7 @@ static void window_ride_colour_paint()
spriteIndex = (trackColour.additional << 24) | (trackColour.main << 19);
spriteIndex |= 0xA0000000;
- spriteIndex += RCT2_GLOBAL(0x00993E7C + (ride->entrance_style * 8), uint32);
+ spriteIndex += RideEntranceDefinitions[ride->entrance_style].spriteIndex;
// Back
gfx_draw_sprite(clippedDpi, spriteIndex, 34, 20, terniaryColour);
diff --git a/src/world/map.c b/src/world/map.c
index c2be5a635a..c1ee8373d4 100644
--- a/src/world/map.c
+++ b/src/world/map.c
@@ -42,7 +42,6 @@ const rct_xy16 TileDirectionDelta[] = {
};
rct_xy16 *gMapSelectionTiles = (rct_xy16*)0x009DE596;
-rct_animated_object *gAnimatedObjects = (rct_animated_object*)0x013886A0;
int _sub_6A876D_save_x;
int _sub_6A876D_save_y;
@@ -459,41 +458,6 @@ int map_coord_is_connected(int x, int y, int z, uint8 faceDirection)
return 0;
}
-/** rct2: 0x009819DC */
-const uint32 *_animatedObjectEventHandlers = (uint32*)0x009819DC;
-
-/**
- * @returns true if the animation should be removed.
- */
-bool map_invalidate_animation(rct_animated_object *obj)
-{
- uint32 address = _animatedObjectEventHandlers[obj->type];
- int result = RCT2_CALLPROC_X(address, obj->x, 0, obj->y, obj->baseZ, 0, 0, 0);
- return (result & 0x100) != 0;
-}
-
-/**
- *
- * rct2: 0x0068AFAD
- */
-void map_invalidate_animations()
-{
- rct_animated_object *aobj = &gAnimatedObjects[0];
- int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
- while (numAnimatedObjects > 0) {
- if (map_invalidate_animation(aobj)) {
- // Remove animated object
- RCT2_GLOBAL(0x0138B580, uint16)--;
- numAnimatedObjects--;
- if (numAnimatedObjects > 0)
- memmove(aobj, aobj + 1, numAnimatedObjects);
- } else {
- numAnimatedObjects--;
- aobj++;
- }
- }
-}
-
/**
*
* rct2: 0x006A876D
diff --git a/src/world/map.h b/src/world/map.h
index 13de4499e4..cd9b08bdd3 100644
--- a/src/world/map.h
+++ b/src/world/map.h
@@ -181,6 +181,10 @@ enum {
PATH_TILE
};
+enum {
+ PATH_FLAG_QUEUE_BANNER = 1 << 3
+};
+
enum {
ENTRANCE_TYPE_RIDE_ENTRANCE,
ENTRANCE_TYPE_RIDE_EXIT,
@@ -229,20 +233,8 @@ typedef struct {
uint8 direction;
} rct2_peep_spawn;
-/**
- * Animated object
- * size: 0x06
- */
-typedef struct {
- uint8 baseZ;
- uint8 type;
- uint16 x;
- uint16 y;
-} rct_animated_object;
-
extern const rct_xy16 TileDirectionDelta[];
extern rct_xy16 *gMapSelectionTiles;
-extern rct_animated_object *gAnimatedObjects;
void map_init(int size);
void map_update_tile_pointers();
@@ -258,7 +250,6 @@ rct_map_element *map_get_surface_element_at(int x, int y);
int map_element_height(int x, int y);
void sub_68B089();
int map_coord_is_connected(int x, int y, int z, uint8 faceDirection);
-void map_invalidate_animations();
void sub_6A876D();
int map_is_location_owned(int x, int y, int z);
int map_is_location_in_park(int x, int y);
diff --git a/src/world/map_animation.c b/src/world/map_animation.c
new file mode 100644
index 0000000000..35dc9ca2fa
--- /dev/null
+++ b/src/world/map_animation.c
@@ -0,0 +1,392 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#include "../addresses.h"
+#include "../ride/ride.h"
+#include "../ride/ride_data.h"
+#include "map_animation.h"
+#include "map.h"
+#include "scenery.h"
+#include "sprite.h"
+
+rct_animated_object *gAnimatedObjects = (rct_animated_object*)0x013886A0;
+
+typedef bool (*map_animation_invalidate_event_handler)(int x, int y, int baseZ);
+
+static bool map_animation_invalidate_ride_entrance(int x, int y, int baseZ);
+static bool map_animation_invalidate_queue_banner(int x, int y, int baseZ);
+static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ);
+static bool map_animation_invalidate_park_entrance(int x, int y, int baseZ);
+static bool map_animation_invalidate_remove(int x, int y, int baseZ);
+static bool map_animation_invalidate_banner(int x, int y, int baseZ);
+static bool map_animation_invalidate_large_scenery(int x, int y, int baseZ);
+static bool sub_6E5B50(int x, int y, int baseZ);
+static bool map_animation_invalidate_wall(int x, int y, int baseZ);
+
+/** rct2: 0x009819DC */
+const uint32 _animatedObjectEventHandlers[] = {
+ (uint32)map_animation_invalidate_ride_entrance, // ride entrance
+ (uint32)map_animation_invalidate_queue_banner, // queue banner
+ (uint32)map_animation_invalidate_small_scenery, // small scenery + peep
+ (uint32)map_animation_invalidate_park_entrance, // park entrance
+ 0x006CE29E, // track
+ 0x006CE2F3, // track
+ 0x006CE39D, // track
+ 0x006CE348, // track
+ 0x006CE3FA, // track
+ (uint32)map_animation_invalidate_remove, // simply return true
+ (uint32)map_animation_invalidate_banner, // banner
+ (uint32)map_animation_invalidate_large_scenery, // large scenery
+ (uint32)sub_6E5B50, // wall
+ (uint32)map_animation_invalidate_wall // wall
+};
+
+
+static bool map_animation_invalidate(rct_animated_object *obj);
+
+/**
+ *
+ * rct2: 0x0068AFAD
+ */
+void map_animation_invalidate_all()
+{
+ rct_animated_object *aobj = &gAnimatedObjects[0];
+ int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
+ while (numAnimatedObjects > 0) {
+ if (map_animation_invalidate(aobj)) {
+ // Remove animated object
+ RCT2_GLOBAL(0x0138B580, uint16)--;
+ numAnimatedObjects--;
+ if (numAnimatedObjects > 0)
+ memmove(aobj, aobj + 1, numAnimatedObjects);
+ } else {
+ numAnimatedObjects--;
+ aobj++;
+ }
+ }
+}
+
+/**
+ * @returns true if the animation should be removed.
+ */
+static bool map_animation_invalidate(rct_animated_object *obj)
+{
+ uint32 address = _animatedObjectEventHandlers[obj->type];
+ if (((address >> 20) & 0xFFF) == 0x006) {
+ int result = RCT2_CALLPROC_X(address, obj->x, 0, obj->y, obj->baseZ, 0, 0, 0);
+ return (result & 0x100) != 0;
+ } else {
+ map_animation_invalidate_event_handler handler = (map_animation_invalidate_event_handler)address;
+ return handler(obj->x, obj->y, obj->baseZ);
+ }
+}
+
+/**
+ *
+ * rct2: 0x00666670
+ */
+static bool map_animation_invalidate_ride_entrance(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+ rct_ride *ride;
+ const rct_ride_entrance_definition *entranceDefinition;
+
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
+ continue;
+ if (mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_ENTRANCE)
+ continue;
+
+ ride = GET_RIDE(mapElement->properties.entrance.ride_index);
+ entranceDefinition = &RideEntranceDefinitions[ride->entrance_style];
+
+ int height = (mapElement->base_height * 8) + entranceDefinition->height + 8;
+ map_invalidate_tile(x, y, height, height + 16);
+ return false;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x006A7BD4
+ */
+static bool map_animation_invalidate_queue_banner(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH)
+ continue;
+ if (!(mapElement->flags & 1))
+ continue;
+ if (!(mapElement->properties.path.type & PATH_FLAG_QUEUE_BANNER))
+ continue;
+
+ int direction = ((mapElement->type >> 6) & 3) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8);
+ if (direction == MAP_ELEMENT_DIRECTION_NORTH || direction == MAP_ELEMENT_DIRECTION_EAST) {
+ baseZ = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, baseZ + 16, baseZ + 30);
+ }
+ return false;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x006E32C9
+ */
+static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+ rct_scenery_entry *sceneryEntry;
+ rct_sprite *sprite;
+ rct_peep *peep;
+
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY)
+ continue;
+ if (mapElement->flags & (1 << 4))
+ continue;
+
+ sceneryEntry = g_smallSceneryEntries[mapElement->properties.scenery.type];
+ if (sceneryEntry->small_scenery.flags & 0xD800) {
+ map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
+ return false;
+ }
+
+ if (sceneryEntry->small_scenery.flags & 0x2000) {
+ if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x3FF)) {
+ int direction = mapElement->type & 3;
+ int x2 = x - TileDirectionDelta[direction].x;
+ int y2 = y - TileDirectionDelta[direction].y;
+
+ uint16 spriteIdx = RCT2_ADDRESS(0x00F1EF60, uint16)[((x2 & 0x1FE0) << 3) | (y2 >> 5)];
+ for (; spriteIdx != 0xFFFF; spriteIdx = sprite->unknown.var_02) {
+ sprite = &g_sprite_list[spriteIdx];
+ if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)
+ continue;
+
+ peep = &sprite->peep;
+ if (peep->state != PEEP_STATE_WALKING)
+ continue;
+ if (peep->z != mapElement->base_height * 8)
+ continue;
+ if (peep->action < PEEP_ACTION_NONE_1)
+ continue;
+
+ peep->action = 0;
+ peep->action_frame = 0;
+ peep->var_70 = 0;
+ sub_693B58(peep);
+ RCT2_CALLPROC_X(0x006EC53F, 0, 0, 0, 0, (int)peep, 0, 0);
+ break;
+ }
+ }
+ map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
+ return false;
+ }
+ } while (!map_element_is_last_for_tile(mapElement++));
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x00666C63
+ */
+static bool map_animation_invalidate_park_entrance(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
+ continue;
+ if (mapElement->properties.entrance.type != ENTRANCE_TYPE_PARK_ENTRANCE)
+ continue;
+ if (mapElement->properties.entrance.index & 0x0F)
+ continue;
+
+ baseZ = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, baseZ + 32, baseZ + 64);
+ return false;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x0068DF8F
+ */
+static bool map_animation_invalidate_remove(int x, int y, int baseZ)
+{
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x006BA2BB
+ */
+static bool map_animation_invalidate_banner(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_BANNER)
+ continue;
+
+ baseZ = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, baseZ, baseZ + 16);
+ return false;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return true;
+}
+
+/**
+ *
+ * rct2: 0x006B94EB
+ */
+static bool map_animation_invalidate_large_scenery(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+ rct_scenery_entry *sceneryEntry;
+
+ bool wasInvalidated = false;
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE)
+ continue;
+
+ sceneryEntry = g_largeSceneryEntries[mapElement->properties.scenery.type & 0x3FF];
+ if (sceneryEntry->large_scenery.flags & (1 << 3)) {
+ int z = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, z, z + 16);
+ wasInvalidated = true;
+ }
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return !wasInvalidated;
+}
+
+/**
+ *
+ * rct2: 0x006E5B50
+ */
+static bool sub_6E5B50(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+ rct_scenery_entry *sceneryEntry;
+
+ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 1)
+ return false;
+
+ bool wasInvalidated = false;
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE)
+ continue;
+
+ sceneryEntry = g_wallSceneryEntries[mapElement->properties.scenery.type];
+ if (!(sceneryEntry->wall.flags & (1 << 4)))
+ continue;
+
+ uint8 di = 0;
+ uint8 bl = mapElement->properties.fence.item[2];
+ uint8 bh = bl & 0x78;
+ if (bh != 0) {
+ if (bh == 0x78) {
+ bl &= 0x87;
+ } else {
+ di |= 2;
+ if (bh != 40) {
+ bh += 8;
+ if (bh == 104 && !(sceneryEntry->wall.flags & (1 << 5)))
+ bh = 120;
+
+ di |= 1;
+ bl &= 135;
+ bl |= bh;
+ }
+ }
+ }
+
+ mapElement->properties.fence.item[2] = bl;
+ if (di & 1) {
+ int z = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, z, z + 32);
+ }
+ if (di & 2)
+ wasInvalidated = true;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return !wasInvalidated;
+}
+
+/**
+ *
+ * rct2: 0x006E5EE4
+ */
+static bool map_animation_invalidate_wall(int x, int y, int baseZ)
+{
+ rct_map_element *mapElement;
+ rct_scenery_entry *sceneryEntry;
+
+ bool wasInvalidated = false;
+ mapElement = map_get_first_element_at(x >> 5, y >> 5);
+ do {
+ if (mapElement->base_height != baseZ)
+ continue;
+ if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE)
+ continue;
+
+ sceneryEntry = g_wallSceneryEntries[mapElement->properties.scenery.type];
+ if (!(sceneryEntry->wall.flags2 & (1 << 4)) && sceneryEntry->wall.var_0D == 255)
+ continue;
+
+ int z = mapElement->base_height * 8;
+ map_invalidate_tile(x, y, z, z + 16);
+ wasInvalidated = true;
+ } while (!map_element_is_last_for_tile(mapElement++));
+
+ return !wasInvalidated;
+}
\ No newline at end of file
diff --git a/src/world/map_animation.h b/src/world/map_animation.h
new file mode 100644
index 0000000000..e766f60b3b
--- /dev/null
+++ b/src/world/map_animation.h
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * Copyright (c) 2014 Ted John
+ * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
+ *
+ * This file is part of OpenRCT2.
+ *
+ * OpenRCT2 is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *****************************************************************************/
+
+#ifndef _MAP_ANIMATION_H_
+#define _MAP_ANIMATION_H_
+
+#include "../common.h"
+
+/**
+ * Animated object
+ * size: 0x06
+ */
+typedef struct {
+ uint8 baseZ;
+ uint8 type;
+ uint16 x;
+ uint16 y;
+} rct_animated_object;
+
+extern rct_animated_object *gAnimatedObjects;
+
+void map_animation_invalidate_all();
+
+#endif
\ No newline at end of file
diff --git a/src/world/sprite.h b/src/world/sprite.h
index ea1ec8a105..2eca98ca63 100644
--- a/src/world/sprite.h
+++ b/src/world/sprite.h
@@ -66,6 +66,10 @@ typedef struct {
uint8 sprite_direction; //direction of sprite? 0x1e
uint8 pad_1F[3]; // 0x1f
uint16 name_string_idx; // 0x22
+ uint8 pad_24[7];
+ uint8 var_2B;
+ uint8 pad_2C[0x45];
+ uint8 var_71;
} rct_unk_sprite;
typedef struct {