Merge pull request #1339 from trigger-death/develop

Added ride filters in object selection
This commit is contained in:
Ted John 2015-06-14 18:07:56 +01:00
commit 9f0c8afb4b
4 changed files with 244 additions and 23 deletions

View File

@ -3681,4 +3681,11 @@ STR_5344 :Changelog
STR_5345 :Financial cheats
STR_5346 :Guest cheats
STR_5347 :Ride cheats
STR_5348 :Park cheats
STR_5348 :Park cheats
STR_5349 :{SMALLFONT}{BLACK}All Rides
STR_5350 :{SMALLFONT}{BLACK}Transport Rides
STR_5351 :{SMALLFONT}{BLACK}Gentle Rides
STR_5352 :{SMALLFONT}{BLACK}Roller Coasters
STR_5353 :{SMALLFONT}{BLACK}Thrill Rides
STR_5354 :{SMALLFONT}{BLACK}Water Rides
STR_5355 :{SMALLFONT}{BLACK}Shops & Stalls

View File

@ -67,6 +67,17 @@ typedef struct {
rct_object_entry_extended *entries;
} rct_object_entry_group;
typedef struct {
uint8 category[2];
} rct_ride_filters;
typedef struct {
union {
rct_ride_filters ride;
};
} rct_object_filters;
extern rct_object_entry_group object_entry_groups[];
int object_load_entry(const char *path, rct_object_entry *outEntry);
@ -95,4 +106,6 @@ rct_object_entry *object_list_find(rct_object_entry *entry);
char *object_get_name(rct_object_entry *entry);
rct_object_filters *get_object_filter(int index);
#endif

View File

@ -28,6 +28,7 @@
#define OBJECT_ENTRY_GROUP_COUNT 11
#define OBJECT_ENTRY_COUNT 721
#define FILTER_VERSION 1
typedef struct {
uint32 total_files;
@ -86,7 +87,10 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileDateModifiedChecksum, int currentItemOffset);
void object_list_create_hash_table();
static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path);
static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path, rct_object_filters* filter);
static void load_object_filter(rct_object_entry* entry, uint8* chunk, rct_object_filters* filter);
static rct_object_filters *_installedObjectFilters = NULL;
static void get_plugin_path(char *outPath)
{
@ -97,6 +101,7 @@ static void get_plugin_path(char *outPath)
static void object_list_sort()
{
rct_object_entry **objectBuffer, *newBuffer, *entry, *destEntry, *lowestEntry;
rct_object_filters *newFilters, *destFilter;
int numObjects, i, j, bufferSize, entrySize, lowestIndex;
char *objectName, *lowestString;
uint8 *copied;
@ -104,7 +109,7 @@ static void object_list_sort()
objectBuffer = &RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32);
copied = calloc(numObjects, sizeof(uint8));
// Get buffer size
entry = *objectBuffer;
for (i = 0; i < numObjects; i++)
@ -114,6 +119,10 @@ static void object_list_sort()
// Create new buffer
newBuffer = rct2_malloc(bufferSize);
destEntry = newBuffer;
if (_installedObjectFilters) {
newFilters = malloc(numObjects * sizeof(rct_object_filters));
destFilter = newFilters;
}
// Copy over sorted objects
for (i = 0; i < numObjects; i++) {
@ -134,12 +143,18 @@ static void object_list_sort()
entrySize = object_get_length(lowestEntry);
memcpy(destEntry, lowestEntry, entrySize);
destEntry = (rct_object_entry*)((int)destEntry + entrySize);
if (_installedObjectFilters)
destFilter[i] = _installedObjectFilters[lowestIndex];
copied[lowestIndex] = 1;
}
// Replace old buffer
rct2_free(*objectBuffer);
*objectBuffer = newBuffer;
if (_installedObjectFilters) {
free(_installedObjectFilters);
_installedObjectFilters = newFilters;
}
free(copied);
}
@ -264,6 +279,11 @@ void object_list_load()
log_verbose("building cache of available objects...");
if (_installedObjectFilters) {
free(_installedObjectFilters);
_installedObjectFilters = NULL;
}
enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char));
if (enumFileHandle != INVALID_HANDLE) {
uint32 installed_buffer_size = 0x1000;
@ -288,9 +308,16 @@ void object_list_load()
if (!object_load_entry(path, &entry))
continue;
rct_object_entry* installed_entry = (rct_object_entry*)(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset);
if (_installedObjectFilters)
_installedObjectFilters = realloc(_installedObjectFilters, sizeof(rct_object_filters) * fileCount);
else
_installedObjectFilters = malloc(sizeof(rct_object_filters) * fileCount);
current_item_offset += install_object_entry(&entry, installed_entry, enumFileInfo.path);
rct_object_entry* installed_entry = (rct_object_entry*)(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset);
rct_object_filters filter;
current_item_offset += install_object_entry(&entry, installed_entry, enumFileInfo.path, &filter);
_installedObjectFilters[fileCount - 1] = filter;
}
platform_enumerate_files_end(enumFileHandle);
}
@ -313,6 +340,7 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
char path[MAX_PATH];
FILE *file;
rct_plugin_header pluginHeader;
uint32 filterVersion = 0;
log_verbose("loading object list cache (plugin.dat)");
@ -344,10 +372,21 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
if (pluginHeader.object_list_no_items != (pluginHeader.total_files & 0xFFFFFF))
log_error("Potential mismatch in file numbers. Possible corrupt file. Consider deleting plugin.dat.");
fclose(file);
reset_loaded_objects();
object_list_examine();
return 1;
if (fread(&filterVersion, sizeof(filterVersion), 1, file)) {
if (filterVersion == FILTER_VERSION) {
if (_installedObjectFilters)
free(_installedObjectFilters);
_installedObjectFilters = malloc(sizeof(rct_object_filters) * pluginHeader.object_list_no_items);
if (fread(_installedObjectFilters, sizeof(rct_object_filters) * pluginHeader.object_list_no_items, 1, file)) {
fclose(file);
reset_loaded_objects();
object_list_examine();
return 1;
}
}
}
}
}
else if (pluginHeader.total_files != totalFiles) {
@ -378,6 +417,7 @@ static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileD
char path[MAX_PATH];
FILE *file;
rct_plugin_header pluginHeader;
uint32 filterVersion = FILTER_VERSION;
log_verbose("saving object list cache (plugin.dat)");
@ -396,6 +436,8 @@ static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileD
fwrite(&pluginHeader, sizeof(rct_plugin_header), 1, file);
fwrite(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*), pluginHeader.object_list_size, 1, file);
fwrite(&filterVersion, sizeof(filterVersion), 1, file);
fwrite(_installedObjectFilters, sizeof(rct_object_filters) * RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32), 1, file);
fclose(file);
return 1;
}
@ -511,6 +553,7 @@ void object_unload_all()
uint32 _installedObjectHashTableSize;
rct_object_entry ** _installedObjectHashTable = NULL;
uint32 _installedObjectHashTableCollisions;
uint32 object_get_hash_code(rct_object_entry *object)
@ -551,7 +594,7 @@ void object_list_create_hash_table()
// Set hash table slot
_installedObjectHashTable[index] = installedObject;
// Next installed object
installedObject = object_get_next(installedObject);
}
@ -600,7 +643,7 @@ rct_object_entry *object_list_find(rct_object_entry *entry)
/* Installs an object_entry at the desired installed_entry address
* Returns the size of the new entry. Will return 0 on failure.
*/
static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path){
static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path, rct_object_filters* filter){
uint8* installed_entry_pointer = (uint8*) installed_entry;
/** Copy all known information into the install entry **/
@ -661,6 +704,9 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in
uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load
load_object_filter(entry, chunk, filter);
// When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars)
if ((objectType == OBJECT_TYPE_RIDE) && !((((rct_ride_type*)chunk)->flags) & RIDE_ENTRY_FLAG_SEPERATE_RIDE_NAME)) {
rct_ride_type* ride_type = (rct_ride_type*)chunk;
@ -712,4 +758,30 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in
object_unload(objectType, (rct_object_entry_extended*)entry);
return size_of_object;
}
}
static void load_object_filter(rct_object_entry* entry, uint8* chunk, rct_object_filters* filter)
{
switch (entry->flags & 0xF) {
case OBJECT_TYPE_RIDE:
filter->ride.category[0] = ((rct_ride_type*)chunk)->category[0];
filter->ride.category[1] = ((rct_ride_type*)chunk)->category[1];
break;
case OBJECT_TYPE_SMALL_SCENERY:
case OBJECT_TYPE_LARGE_SCENERY:
case OBJECT_TYPE_WALLS:
case OBJECT_TYPE_BANNERS:
case OBJECT_TYPE_PATHS:
case OBJECT_TYPE_PATH_BITS:
case OBJECT_TYPE_SCENERY_SETS:
case OBJECT_TYPE_PARK_ENTRANCE:
case OBJECT_TYPE_WATER:
case OBJECT_TYPE_SCENARIO_TEXT:
break;
}
}
rct_object_filters *get_object_filter(int index)
{
return &_installedObjectFilters[index];
}

View File

@ -38,11 +38,21 @@ enum {
FILTER_WW = (1 << 1),
FILTER_TT = (1 << 2),
FILTER_CUSTOM = (1 << 3),
FILTER_ALL = 0xF
FILTER_RIDE_TRANSPORT = (1 << 5),
FILTER_RIDE_GENTLE = (1 << 6),
FILTER_RIDE_COASTER = (1 << 7),
FILTER_RIDE_THRILL = (1 << 8),
FILTER_RIDE_WATER = (1 << 9),
FILTER_RIDE_STALL = (1 << 10),
FILTER_ALL = 0x7EF,
} FILTER_FLAGS;
uint32 _filter_flags;
uint16 _filter_object_counts[11];
uint8 _filter_ride_tab;
char _filter_string[41];
@ -91,7 +101,15 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX {
WIDX_DROPDOWN2, // 18, 40000
WIDX_FILTER_DROPDOWN, // 19, 80000
WIDX_FILTER_STRING_BUTTON, // 20, 100000
WIDX_FILTER_CLEAR_BUTTON // 21, 200000
WIDX_FILTER_CLEAR_BUTTON, // 21, 200000
WIDX_FILTER_RIDE_TAB_FRAME,
WIDX_FILTER_RIDE_TAB_ALL,
WIDX_FILTER_RIDE_TAB_TRANSPORT,
WIDX_FILTER_RIDE_TAB_GENTLE,
WIDX_FILTER_RIDE_TAB_COASTER,
WIDX_FILTER_RIDE_TAB_THRILL,
WIDX_FILTER_RIDE_TAB_WATER,
WIDX_FILTER_RIDE_TAB_STALL
};
static rct_widget window_editor_object_selection_widgets[] = {
@ -117,6 +135,14 @@ static rct_widget window_editor_object_selection_widgets[] = {
{ WWT_DROPDOWN_BUTTON, 0, 350, 463, 23, 34, 5261, 5265 },
{ WWT_TEXT_BOX, 1, 4, 214, 46, 57, (uint32)_filter_string, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 1, 218, 287, 46, 57, 5277, STR_NONE },
{ WWT_RESIZE, 1, 3, 287, 73, 76, 0xFFFFFFFF, STR_NONE },
{ WWT_TAB, 1, 3, 33, 47, 73, 0x2000144E, 5349 },
{ WWT_TAB, 1, 34, 64, 47, 73, 0x2000144E, 5350 },
{ WWT_TAB, 1, 65, 95, 47, 73, 0x2000144E, 5351 },
{ WWT_TAB, 1, 96, 126, 47, 73, 0x2000144E, 5352 },
{ WWT_TAB, 1, 127, 157, 47, 73, 0x2000144E, 5353 },
{ WWT_TAB, 1, 158, 188, 47, 73, 0x2000144E, 5354 },
{ WWT_TAB, 1, 189, 219, 47, 73, 0x2000144E, 5355 },
{ WIDGETS_END }
};
@ -182,6 +208,7 @@ static void window_editor_object_selection_manage_tracks();
static void editor_load_selected_objects();
static bool filter_string(rct_object_entry *entry);
static bool filter_source(rct_object_entry *entry);
static bool filter_chunks(rct_object_entry *entry, rct_object_filters *filter);
static void filter_update_counts();
static rct_object_entry DefaultSelectedObjects[] = {
@ -341,6 +368,28 @@ static void window_editor_object_selection_mouseup()
case WIDX_TAB_11:
window_editor_object_set_page(w, widgetIndex - WIDX_TAB_1);
break;
case WIDX_FILTER_RIDE_TAB_ALL:
_filter_flags |= 0x7E0;
filter_update_counts();
w->scrolls->v_top = 0;
window_invalidate(w);
break;
case WIDX_FILTER_RIDE_TAB_TRANSPORT:
case WIDX_FILTER_RIDE_TAB_GENTLE:
case WIDX_FILTER_RIDE_TAB_COASTER:
case WIDX_FILTER_RIDE_TAB_THRILL:
case WIDX_FILTER_RIDE_TAB_WATER:
case WIDX_FILTER_RIDE_TAB_STALL:
_filter_flags &= ~0x7E0;
_filter_flags |= (1 << (widgetIndex - WIDX_FILTER_RIDE_TAB_TRANSPORT + 5));
filter_update_counts();
w->scrolls->v_top = 0;
window_invalidate(w);
break;
case WIDX_DROPDOWN1:
w->list_information_type ^= 1;
@ -380,10 +429,10 @@ void window_editor_object_selection_mousedown(int widgetIndex, rct_window*w, rct
case WIDX_FILTER_DROPDOWN:
num_items = 4;
gDropdownItemsFormat[0] = 1142;
gDropdownItemsFormat[1] = 1142;
gDropdownItemsFormat[2] = 1142;
gDropdownItemsFormat[3] = 1142;
gDropdownItemsFormat[0] = 1156;
gDropdownItemsFormat[1] = 1156;
gDropdownItemsFormat[2] = 1156;
gDropdownItemsFormat[3] = 1156;
gDropdownItemsArgs[0] = 2741;
gDropdownItemsArgs[1] = 5262;
gDropdownItemsArgs[2] = 5263;
@ -398,8 +447,9 @@ void window_editor_object_selection_mousedown(int widgetIndex, rct_window*w, rct
num_items
);
gDropdownItemsChecked = _filter_flags;
gDropdownItemsChecked = _filter_flags & 0xF;
break;
}
}
@ -415,7 +465,6 @@ static void window_editor_object_selection_dropdown()
return;
switch (widgetIndex) {
case WIDX_FILTER_DROPDOWN:
_filter_flags ^= (1 << dropdownIndex);
filter_update_counts();
@ -640,6 +689,39 @@ static void window_editor_object_selection_invalidate()
w->widgets[WIDX_LIST].right = 587 - x;
w->widgets[WIDX_PREVIEW].left = 537 - (x >> 1);
w->widgets[WIDX_PREVIEW].right = w->widgets[WIDX_PREVIEW].left + 113;
bool ridePage = (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS);
w->widgets[WIDX_LIST].top = (ridePage ? 94 : 60);
w->widgets[WIDX_FILTER_STRING_BUTTON].top = (ridePage ? 80 : 46);
w->widgets[WIDX_FILTER_STRING_BUTTON].bottom = (ridePage ? 91 : 57);
w->widgets[WIDX_FILTER_CLEAR_BUTTON].top = (ridePage ? 80 : 46);
w->widgets[WIDX_FILTER_CLEAR_BUTTON].bottom = (ridePage ? 91 : 57);
if (ridePage) {
w->enabled_widgets |= (1 << WIDX_FILTER_RIDE_TAB_ALL) | (1 << WIDX_FILTER_RIDE_TAB_TRANSPORT) |
(1 << WIDX_FILTER_RIDE_TAB_GENTLE) | (1 << WIDX_FILTER_RIDE_TAB_COASTER) | (1 << WIDX_FILTER_RIDE_TAB_THRILL) |
(1 << WIDX_FILTER_RIDE_TAB_WATER) | (1 << WIDX_FILTER_RIDE_TAB_STALL);
for (i = 0; i < 7; i++)
w->pressed_widgets &= ~(1 << (WIDX_FILTER_RIDE_TAB_ALL + i));
if ((_filter_flags & 0x7E0) == 0x7E0)
w->pressed_widgets |= (1 << WIDX_FILTER_RIDE_TAB_ALL);
else {
for (int i = 0; i < 6; i++) {
if (_filter_flags & (1 << (5 + i)))
w->pressed_widgets |= (uint64)(1 << (WIDX_FILTER_RIDE_TAB_TRANSPORT + i));
}
}
w->widgets[WIDX_FILTER_RIDE_TAB_FRAME].type = WWT_RESIZE;
for (int i = WIDX_FILTER_RIDE_TAB_ALL; i <= WIDX_FILTER_RIDE_TAB_STALL; i++)
w->widgets[i].type = WWT_TAB;
}
else {
w->enabled_widgets &= ~((1 << WIDX_FILTER_RIDE_TAB_ALL) | (1 << WIDX_FILTER_RIDE_TAB_TRANSPORT) |
(1 << WIDX_FILTER_RIDE_TAB_GENTLE) | (1 << WIDX_FILTER_RIDE_TAB_COASTER) | (1 << WIDX_FILTER_RIDE_TAB_THRILL) |
(1 << WIDX_FILTER_RIDE_TAB_WATER) | (1 << WIDX_FILTER_RIDE_TAB_STALL));
for (int i = WIDX_FILTER_RIDE_TAB_FRAME; i <= WIDX_FILTER_RIDE_TAB_STALL; i++)
w->widgets[i].type = WWT_EMPTY;
}
}
/**
@ -659,6 +741,17 @@ static void window_editor_object_selection_paint()
window_paint_get_registers(w, dpi);
/*if (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS) {
gfx_fill_rect_inset(dpi,
w->x + w->widgets[WIDX_FILTER_RIDE_TAB_ALL].left - 1,
w->y + w->widgets[WIDX_FILTER_RIDE_TAB_ALL].bottom,
w->x + w->widgets[WIDX_FILTER_RIDE_TAB_STALL].right + 1,
w->y + w->widgets[WIDX_FILTER_RIDE_TAB_ALL].bottom + 2,
w->colours[1],
0x10
);
}*/
window_draw_widgets(w, dpi);
// Draw tabs
@ -672,6 +765,22 @@ static void window_editor_object_selection_paint()
gfx_draw_sprite(dpi, 5458 + i, x, y, 0);
}
const int ride_tabs[] = { 5458, 0x200015A1, 5542, 0x200015AA, 5557 + 5, 5551, 5530, 5327 };
// Draw ride tabs
if (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS) {
for (i = 0; i < 7; i++) {
widget = &w->widgets[WIDX_FILTER_RIDE_TAB_ALL + i];
if (widget->type == WWT_EMPTY)
continue;
x = w->x + widget->left;
y = w->y + widget->top;
gfx_draw_sprite(dpi, ride_tabs[i] | (w->colours[1] << 19), x, y, 0);
}
}
// Preview background
widget = &w->widgets[WIDX_PREVIEW];
gfx_fill_rect(
@ -823,6 +932,7 @@ static void window_editor_object_selection_scrollpaint()
int x, y, i, colour, colour2, numObjects, type;
short scrollIndex;
rct_object_entry *entry;
rct_object_filters *filter;
rct_window *w;
rct_drawpixelinfo *dpi;
uint8 *itemFlags;
@ -839,9 +949,10 @@ static void window_editor_object_selection_scrollpaint()
itemFlags = RCT2_GLOBAL(0x009ADAEC, uint8*);
y = 0;
for (i = 0; i < numObjects; i++) {
filter = get_object_filter(i);
type = entry->flags & 0x0F;
source = (entry->flags & 0xF0) >> 4;
if (type == w->selected_tab && !(*itemFlags & 0x20) && filter_source(entry) && filter_string(entry)) {
if (type == w->selected_tab && !(*itemFlags & 0x20) && filter_source(entry) && filter_string(entry) && filter_chunks(entry, filter)) {
if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) {
// Draw checkbox
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && !(*itemFlags & 0x20))
@ -949,13 +1060,15 @@ static int window_editor_object_selection_select_object(int flags, rct_object_en
*/
static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry)
{
rct_object_filters *filter;
*installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*);
uint8 source;
int object_count = 0;
for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){
filter = get_object_filter(RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) - i);
source = ((*installed_entry)->flags & 0xF0) >> 4;
if (((*installed_entry)->flags & 0xF) == object_type && filter_source(*installed_entry) && filter_string(*installed_entry)){
if (((*installed_entry)->flags & 0xF) == object_type && filter_source(*installed_entry) && filter_string(*installed_entry) && filter_chunks(*installed_entry, filter)){
if (!(*selection_flags & 0x20)){
y -= 12;
*object_selection_flags = *selection_flags;
@ -1106,17 +1219,33 @@ static bool filter_source(rct_object_entry *entry)
return (_FILTER_RCT2 && source == 8) || (_FILTER_WW && source == 1) || (_FILTER_TT && source == 2) || (_FILTER_CUSTOM && source != 8 && source != 1 && source != 2);
}
static bool filter_chunks(rct_object_entry *entry, rct_object_filters *filter)
{
switch (entry->flags & 0x0F) {
case OBJECT_TYPE_RIDE:
if (_filter_flags & (1 << (filter->ride.category[0] + 5)))
return true;
if (_filter_flags & (1 << (filter->ride.category[1] + 5)))
return true;
return false;
}
return true;
}
static void filter_update_counts()
{
if (!_FILTER_ALL || strlen(_filter_string) > 0) {
rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
rct_object_filters *filter;
uint8 type;
for (int i = 0; i < 11; i++) {
_filter_object_counts[i] = 0;
}
for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i) {
filter = get_object_filter(RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) - i);
type = installed_entry->flags & 0xF;
if (filter_source(installed_entry) && filter_string(installed_entry)) {
if (filter_source(installed_entry) && filter_string(installed_entry) && filter_chunks(installed_entry, filter)) {
_filter_object_counts[type]++;
}
installed_entry = object_get_next(installed_entry);