improve saving of S6 data and remove ghost banners / user strings

This commit is contained in:
IntelOrca 2015-06-15 21:56:26 +01:00
parent 40591fda50
commit 32046c3c0a
4 changed files with 208 additions and 146 deletions

View File

@ -818,16 +818,30 @@ static void sub_674BCF()
}
}
static void get_map_elements_without_ghost(rct_map_element *resultElements)
/**
* Modifys the given S6 data so that ghost elements, rides with no track elements or unused banners / user strings are saved.
*/
static scenario_fix_ghosts(rct_s6_data *s6)
{
// Remove all ghost elements
size_t mapElementTotalSize = MAX_MAP_ELEMENTS * sizeof(rct_map_element);
rct_map_element *destinationElement = resultElements;
rct_map_element *destinationElement = s6->map_elements;
for (int y = 0; y < 256; y++) {
for (int x = 0; x < 256; x++) {
rct_map_element *originalElement = map_get_first_element_at(x, y);
do {
if (!(originalElement->flags & MAP_ELEMENT_FLAG_GHOST)) {
if (originalElement->flags & MAP_ELEMENT_FLAG_GHOST) {
int bannerIndex = map_element_get_banner_index(originalElement);
if (bannerIndex != -1) {
rct_banner *banner = &s6->banners[bannerIndex];
if (banner->type != BANNER_NULL) {
banner->type = BANNER_NULL;
if (is_user_string_id(banner->string_idx))
s6->custom_strings[(banner->string_idx % MAX_USER_STRINGS) * USER_STRING_MAX_LENGTH] = 0;
}
}
} else {
*destinationElement++ = *originalElement;
}
} while (!map_element_is_last_for_tile(originalElement++));
@ -836,6 +850,20 @@ static void get_map_elements_without_ghost(rct_map_element *resultElements)
(destinationElement - 1)->flags |= MAP_ELEMENT_FLAG_LAST_TILE;
}
}
// Remove trackless rides
bool rideHasTrack[MAX_RIDES];
ride_all_has_any_track_elements(rideHasTrack);
for (int i = 0; i < MAX_RIDES; i++) {
rct_ride *ride = &s6->rides[i];
if (rideHasTrack[i] || ride->type == RIDE_TYPE_NULL)
continue;
ride->type = RIDE_TYPE_NULL;
if (is_user_string_id(ride->name))
s6->custom_strings[(ride->name % MAX_USER_STRINGS) * USER_STRING_MAX_LENGTH] = 0;
}
}
/**
@ -845,16 +873,6 @@ static void get_map_elements_without_ghost(rct_map_element *resultElements)
*/
int scenario_save(char *path, int flags)
{
rct_s6_header *s6Header = (rct_s6_header*)0x009E34E4;
rct_s6_info *s6Info = (rct_s6_info*)0x0141F570;
FILE *file;
char *buffer;
sawyercoding_chunk_header chunkHeader;
int encodedLength;
long fileSize;
uint32 checksum;
rct_window *w;
rct_viewport *viewport;
int viewX, viewY, viewZoom, viewRotation;
@ -899,145 +917,159 @@ int scenario_save(char *path, int flags)
RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_Y, uint16) = viewY;
RCT2_GLOBAL(RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION, uint16) = viewZoom | (viewRotation << 8);
//
memset(s6Header, 0, sizeof(rct_s6_header));
s6Header->type = flags & 2 ? S6_TYPE_SCENARIO : S6_TYPE_SAVEDGAME;
s6Header->num_packed_objects = flags & 1 ? scenario_get_num_packed_objects_to_write() : 0;
s6Header->version = S6_RCT2_VERSION;
s6Header->magic_number = S6_MAGIC_NUMBER;
// Prepare S6
rct_s6_data *s6 = malloc(sizeof(rct_s6_data));
s6->header.type = flags & 2 ? S6_TYPE_SCENARIO : S6_TYPE_SAVEDGAME;
s6->header.num_packed_objects = flags & 1 ? scenario_get_num_packed_objects_to_write() : 0;
s6->header.version = S6_RCT2_VERSION;
s6->header.magic_number = S6_MAGIC_NUMBER;
memcpy(&s6->info, (rct_s6_info*)0x0141F570, sizeof(rct_s6_info));
for (int i = 0; i < 721; i++) {
uint32 chunkPtr = RCT2_ADDRESS(0x009ACFA4, uint32)[i];
rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]);
if (RCT2_ADDRESS(0x009ACFA4, uint32)[i] == 0xFFFFFFFF) {
memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry));
} else {
s6->objects[i] = *((rct_object_entry*)entry);
}
}
memcpy(&s6->elapsed_months, (void*)0x00F663A8, 16);
memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000);
memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570);
scenario_fix_ghosts(s6);
scenario_save_s6(path, s6);
free(s6);
if (!(flags & 0x80000000))
reset_loaded_objects();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
return 1;
}
bool scenario_save_s6(char *path, rct_s6_data *s6)
{
FILE *file;
char *buffer;
sawyercoding_chunk_header chunkHeader;
int encodedLength;
long fileSize;
uint32 checksum;
file = fopen(path, "wb+");
if (file == NULL) {
log_error("Unable to write to %s", path);
return 0;
return false;
}
buffer = malloc(0x600000);
if (buffer == NULL) {
log_error("Unable to allocate enough space for a write buffer.");
fclose(file);
return 0;
return false;
}
// Write header chunk
// 0: Write header chunk
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
chunkHeader.length = sizeof(rct_s6_header);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6Header, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->header, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write scenario info chunk
if (flags & 2) {
// 1: Write scenario info chunk
if (s6->header.type == S6_TYPE_SCENARIO) {
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
chunkHeader.length = sizeof(rct_s6_info);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6Info, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->info, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
}
// Write packed objects
if (s6Header->num_packed_objects > 0) {
// 2: Write packed objects
if (s6->header.num_packed_objects > 0) {
if (!scenario_write_packed_objects(file)) {
free(buffer);
fclose(file);
return 0;
return false;
}
}
// Write available objects chunk
scenario_write_available_objects(file);
// 3: Write available objects chunk
chunkHeader.encoding = CHUNK_ENCODING_ROTATE;
chunkHeader.length = 721 * sizeof(rct_object_entry);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->objects, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write date etc. chunk
// 4: Misc fields (data, rand...) chunk
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 16;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x00F663A8, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->elapsed_months, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write map elements
uint8 *chunkData = malloc(0x4A85EC);
get_map_elements_without_ghost((rct_map_element*)chunkData);
memcpy(chunkData + 0x180000, (uint8*)(RCT2_ADDRESS_MAP_ELEMENTS + 0x180000), 0x4A85EC - 0x180000);
// 5: Map elements + sprites and other fields chunk
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 0x4A85EC;
encodedLength = sawyercoding_write_chunk_buffer(buffer, chunkData, chunkHeader);
chunkHeader.length = 0x180000;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)s6->map_elements, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
free(chunkData);
if (flags & 2) {
// Write chunk
if (s6->header.type == S6_TYPE_SCENARIO) {
// 6:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 0x27104C;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x010E63B8, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 7:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 4;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x01357844, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->guests_in_park, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 8:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 8;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x01357BC8, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->last_guests_in_park, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 9:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 2;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x01357CB0, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_rating, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 10:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 1082;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x01357CF2, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->active_research_types, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 11:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 16;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x0135832C, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->current_expenditure, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk
// 12:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 4;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x0135853C, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->park_value, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
// Write chunk (don't save rides which have no track pieces)
uint8 *chunkData = malloc(0x761E8);
memcpy(chunkData, (void*)0x01358740, 0x761E8);
bool rideHasTrack[MAX_RIDES];
rct_ride *rides = (rct_ride*)(chunkData + (0x013628F8 - 0x01358740));
ride_all_has_any_track_elements(rideHasTrack);
for (int i = 0; i < MAX_RIDES; i++) {
if (!rideHasTrack[i])
rides[i].type = RIDE_TYPE_NULL;
}
// 13:
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 0x761E8;
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)0x01358740, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->completed_company_value, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
free(chunkData);
} else {
// Write chunk (don't save rides which have no track pieces)
uint8 *chunkData = malloc(0x2E8570);
memcpy(chunkData, (void*)0x010E63B8, 0x2E8570);
bool rideHasTrack[MAX_RIDES];
rct_ride *rides = (rct_ride*)(chunkData + (0x013628F8 - 0x010E63B8));
ride_all_has_any_track_elements(rideHasTrack);
for (int i = 0; i < MAX_RIDES; i++) {
if (!rideHasTrack[i])
rides[i].type = RIDE_TYPE_NULL;
}
// 6: Everything else...
chunkHeader.encoding = CHUNK_ENCODING_RLECOMPRESSED;
chunkHeader.length = 0x2E8570;
encodedLength = sawyercoding_write_chunk_buffer(buffer, chunkData, chunkHeader);
encodedLength = sawyercoding_write_chunk_buffer(buffer, (uint8*)&s6->dword_010E63B8, chunkHeader);
fwrite(buffer, encodedLength, 1, file);
}
@ -1057,13 +1089,7 @@ int scenario_save(char *path, int flags)
fseek(file, fileSize, SEEK_SET);
fwrite(&checksum, sizeof(uint32), 1, file);
fclose(file);
if (!(flags & 0x80000000))
reset_loaded_objects();
gfx_invalidate_screen();
RCT2_GLOBAL(0x009DEA66, uint16) = 0;
return 1;
return true;
}
static void scenario_objective_check_guests_by()

View File

@ -21,9 +21,16 @@
#ifndef _SCENARIO_H_
#define _SCENARIO_H_
#include "rct2.h"
#include "common.h"
#include "management/award.h"
#include "management/news_item.h"
#include "management/research.h"
#include "ride/ride.h"
#include "object.h"
#include "platform/platform.h"
#include "world/banner.h"
#include "world/map.h"
#include "world/sprite.h"
/**
* SV6/SC6 header chunk
@ -93,7 +100,7 @@ typedef struct {
#define g_stexEntries ((rct_stex_entry**)object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].chunks)
/* This will be useful for backwards compatibility
// This will be useful for backwards compatibility
typedef struct {
// SC6[0]
rct_s6_header header;
@ -131,18 +138,18 @@ typedef struct {
uint16 word_013573CE;
uint16 word_013573D0;
uint8 pad_013573D2[2];
uint16 word_013573D4;
uint8 pad_013573D6[4];
uint32 dword_013573D8;
uint32 dword_013573DC;
rct_string_id park_name;
uint8 pad_013573D6[2];
uint32 park_name_args;
money32 initial_cash;
money32 current_loan;
uint32 park_flags;
money16 park_entrance_fee;
uint16 word_013573EA;
uint16 word_013573EC;
uint8 pad_013573EE[16];
uint8 pad_013573EE[2];
uint8 byte_013573F0;
uint8 pad_013573F1[2];
uint8 pad_013573F1;
rct2_peep_spawn peep_spawns[2];
uint8 guest_count_change_modifier;
uint8 current_research_level;
@ -195,17 +202,17 @@ typedef struct {
uint8 next_research_category;
uint8 next_research_expected_day;
uint8 next_research_expected_month;
uint8 byte_013580E9;
uint8 guest_initial_happiness;
uint16 park_size;
uint16 guest_generation_probability;
uint16 total_ride_value;
money32 maximum_loan;
money16 guest_initial_cash;
uint8 dword_013580F6;
uint8 dword_013580F7;
uint8 guest_initial_hunger;
uint8 guest_initial_thirst;
uint8 objective_type;
uint8 objective_year;
uint8 pad_013580FA[4];
uint8 pad_013580FA[2];
money32 objective_currency;
uint16 objective_guests;
uint8 campaign_weeks_left[20];
@ -223,28 +230,32 @@ typedef struct {
// Ignored in scenario
money32 weekly_profit_history[128];
money32 park_value;
money32 park_value_history[128];
// SC6[12]
money32 park_value;
// Ignored in scenario
money32 park_value_history[128];
// SC6[13]
money32 completed_company_value;
uint32 total_admissions;
money32 income_from_admissions;
money32 company_value;
uint8 byte_01358750[16];
rct_award awards[4];
uint16 word_01358770;
uint16 word_01358772;
money16 land_price;
money16 construction_rights_price;
uint16 word_01358774;
uint8 pad_01358776[4];
uint8 pad_01358776[2];
uint32 dword_01358778[17];
uint32 dword_013587BC;
uint32 dword_013587C0;
uint32 dword_013587C4;
uint16 dword_013587C8;
uint8 pad_013587CA[16];
uint8 pad_013587CA[6];
uint32 dword_013587D0;
uint8 pad_013587D4[8];
uint8 pad_013587D4[4];
char scenario_completed_name[32];
money32 cash;
uint8 pad_013587FC[50];
@ -265,7 +276,7 @@ typedef struct {
char scenario_description[255];
uint8 byte_01359349;
uint8 current_interest_rate;
uint8 pad_0135934B[3];
uint8 pad_0135934B;
uint32 dword_0135934C;
uint16 park_entrance_x[4];
uint16 park_entrance_y[4];
@ -273,7 +284,7 @@ typedef struct {
uint8 park_entrance_direction[4];
uint8 scenario_filename[256];
uint8 saved_expansion_pack_names[3256];
rct_banner banners[250]
rct_banner banners[250];
char custom_strings[0x8000];
uint32 game_ticks_1;
rct_ride rides[255];
@ -284,7 +295,7 @@ typedef struct {
uint8 map_animations[6000];
uint8 byte_01389E10[6000];
uint16 num_map_animations;
uint8 pad_0138B580[2];
uint8 pad_0138B582[2];
uint16 word_0138B584;
uint16 word_0138B586;
uint16 word_0138B588;
@ -326,17 +337,17 @@ typedef struct {
uint16 word_0138B5CC;
uint16 word_0138B5CE[31];
uint8 ride_measurements[0x25860];
uint32 dword_13B0E6C;
uint16 word_13B0E70;
uint32 dword_13B0E72[0x6600]; // 512 bytes per staff peep
uint32 next_guest_index;
uint16 grass_and_scenery_tilepos;
uint32 patrol_areas[0x6600]; // 512 bytes per staff peep
uint8 byte_13CA672[116];
uint8 byte_13CA6E6[84];
uint8 byte_13CA73A[4];
uint8 unk_13CA73E;
uint8 pad_13CA73E;
uint8 pad_13CA73F;
uint8 byte_13CA740;
uint8 byte_13CA741;
uint8 byte_13CA7424[4];
uint8 byte_13CA742[4];
uint8 climate;
uint8 pad_013CA747;
uint16 climate_update_timer;
@ -354,9 +365,9 @@ typedef struct {
uint8 byte_13CE730[64];
uint32 dword_13CE770;
uint16 word_13CE774;
uint16 word_13CE776[217];
uint16 word_13CE776;
uint8 pad_13CE778[434];
} rct_s6_data;
*/
enum {
SCENARIO_FLAGS_VISIBLE = (1 << 0),
@ -413,6 +424,7 @@ void scenario_update();
unsigned int scenario_rand();
int scenario_prepare_for_save();
int scenario_save(char *path, int flags);
bool scenario_save_s6(char *path, rct_s6_data *s6);
void scenario_set_filename(const char *value);
void scenario_failure();
void scenario_success();

View File

@ -746,19 +746,11 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i
*ebx = 0;
return;
}
int ecx2 = map_element->properties.scenerymultiple.type >> 10;
rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.scenerymultiple.type & 0x3FF];
if(scenery_entry->large_scenery.var_11 != 0xFF){
uint8 banner_num = map_element->type & MAP_ELEMENT_QUADRANT_MASK;
banner_num |= (map_element->properties.scenerymultiple.colour[0] & 0xE0) >> 2;
banner_num |= (map_element->properties.scenerymultiple.colour[1] & 0xE0) >> 5;
if(gBanners[banner_num].type != BANNER_NULL){
window_close_by_number(WC_BANNER, banner_num);
gBanners[banner_num].type = BANNER_NULL;
user_string_free(gBanners[banner_num].string_idx);
}
}
map_element_remove_banner_entry(map_element);
int ecx2 = map_element->properties.scenerymultiple.type >> 10;
rct_scenery_entry* scenery_entry = g_largeSceneryEntries[map_element->properties.scenerymultiple.type & 0x3FF];
rct_xyz16 firstTile = {
.x = scenery_entry->large_scenery.tiles[ecx2].x_offset,
.y = scenery_entry->large_scenery.tiles[ecx2].y_offset,
@ -863,15 +855,13 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi
}
}
rct_banner *banner = &gBanners[map_element->properties.banner.index];
uint8 banner_type = banner->type;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
window_close_by_number(WC_BANNER, map_element->properties.banner.index);
user_string_free(banner->string_idx);
banner->type = BANNER_NULL;
uint8 bannerType = banner->type;
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
map_element_remove_banner_entry(map_element);
map_invalidate_tile(x, y, z, z + 32);
map_element_remove(map_element);
}
rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[banner_type];
rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[bannerType];
*ebx = (scenery_entry->banner.price * -3) / 4;
if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){
*ebx = 0;
@ -1836,15 +1826,7 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi,
return;
}
rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type];
if(scenery_entry->wall.var_0D != 0xFF){
rct_banner* banner = &gBanners[map_element->properties.fence.item[0]];
if(banner->type != BANNER_NULL){
window_close_by_number(WC_BANNER, map_element->properties.fence.item[0]);
banner->type = BANNER_NULL;
user_string_free(banner->string_idx);
}
}
map_element_remove_banner_entry(map_element);
map_invalidate_tile(x, y, map_element->base_height * 8, (map_element->base_height * 8) + 72);
map_element_remove(map_element);
*ebx = 0;
@ -2693,3 +2675,43 @@ void sub_6A7594()
RCT2_GLOBAL(0x00F3EFF4, uint32) = 0x00F3EFF8;
}
int map_element_get_banner_index(rct_map_element *mapElement)
{
rct_scenery_entry* sceneryEntry;
switch (map_element_get_type(mapElement)) {
case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE:
sceneryEntry = g_largeSceneryEntries[mapElement->properties.scenerymultiple.type & 0x3FF];
if (sceneryEntry->large_scenery.var_11 == 0xFF)
return -1;
return
(mapElement->type & MAP_ELEMENT_QUADRANT_MASK) |
((mapElement->properties.scenerymultiple.colour[0] & 0xE0) >> 2);
((mapElement->properties.scenerymultiple.colour[1] & 0xE0) >> 5);
case MAP_ELEMENT_TYPE_FENCE:
sceneryEntry = g_wallSceneryEntries[mapElement->properties.fence.type];
if (sceneryEntry->wall.var_0D == 0xFF)
return -1;
return mapElement->properties.fence.item[0];
case MAP_ELEMENT_TYPE_BANNER:
return mapElement->properties.banner.index;
default:
return -1;
}
}
void map_element_remove_banner_entry(rct_map_element *mapElement)
{
int bannerIndex = map_element_get_banner_index(mapElement);
if (bannerIndex == -1)
return;
rct_banner* banner = &gBanners[bannerIndex];
if (banner->type != BANNER_NULL) {
window_close_by_number(WC_BANNER, bannerIndex);
banner->type = BANNER_NULL;
user_string_free(banner->string_idx);
}
}

View File

@ -323,5 +323,7 @@ void map_remove_intersecting_walls(int x, int y, int z0, int z1, int direction);
void map_update_tiles();
void sub_6A7594();
int map_element_get_banner_index(rct_map_element *mapElement);
void map_element_remove_banner_entry(rct_map_element *mapElement);
#endif