mirror of https://github.com/OpenRCT2/OpenRCT2.git
improve saving of S6 data and remove ghost banners / user strings
This commit is contained in:
parent
40591fda50
commit
32046c3c0a
206
src/scenario.c
206
src/scenario.c
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue