diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index ae11c8b0c9..1c03cb38e3 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -2221,7 +2221,7 @@ STR_2213 :{SMALLFONT}{BLACK}Show list of entertainers in park STR_2214 :Construction not possible while game is paused! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C -STR_2217 :{WINDOW_COLOUR_2}{COMMA16}F +STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} STR_2220 :{WINDOW_COLOUR_2}Park Rating: {BLACK}{COMMA16} @@ -2371,7 +2371,7 @@ STR_2363 :Gridlines on Landscape STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off STR_2365 :The bank refuses to increase your loan! STR_2366 :Celsius ({DEGREE}C) -STR_2367 :Fahrenheit (F) +STR_2367 :Fahrenheit ({DEGREE}F) STR_2368 :None STR_2369 :Low STR_2370 :Average diff --git a/src/audio/audio.c b/src/audio/audio.c index ad7706c221..cc91211127 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -61,9 +61,9 @@ void audio_init() if (result >= 0) return; - log_fatal("SDL_Init %s", SDL_GetError()); - exit(-1); -} + log_fatal("SDL_Init %s", SDL_GetError()); + exit(-1); + } void audio_quit() { @@ -79,9 +79,9 @@ void audio_populate_devices() if (gAudioDeviceCount <= 0) return; - gAudioDeviceCount++; - gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); - safe_strncpy(gAudioDevices[0].name, language_get_string(5510), AUDIO_DEVICE_NAME_SIZE); + gAudioDeviceCount++; + gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); + safe_strncpy(gAudioDevices[0].name, language_get_string(5510), AUDIO_DEVICE_NAME_SIZE); for (int i = 1; i < gAudioDeviceCount; i++) { const char *utf8Name = SDL_GetAudioDeviceName(i - 1, SDL_FALSE); @@ -89,8 +89,8 @@ void audio_populate_devices() utf8Name = language_get_string(5511); safe_strncpy(gAudioDevices[i].name, utf8Name, AUDIO_DEVICE_NAME_SIZE); + } } -} int audio_play_sound_panned(int soundId, int pan, sint16 x, sint16 y, sint16 z) { @@ -137,9 +137,9 @@ rct_audio_params audio_get_params_from_location(int soundId, const rct_xyz16 *lo rct_xy16 pos2 = coordinate_3d_to_2d(location, rotation); rct_window *window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); while (true) { - window--; + window--; if (window < RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) - break; + break; rct_viewport *viewport = window->viewport; if (!viewport || !(viewport->flags & VIEWPORT_FLAG_SOUND_ON)) @@ -153,11 +153,11 @@ rct_audio_params audio_get_params_from_location(int soundId, const rct_xyz16 *lo if (vy < 0 || vy >= viewport->view_height || vx < 0 || vx >= viewport->view_width || params.volume < -10000) { params.in_range = false; return params; - } - } + } + } return params; -} + } int audio_play_sound(int soundId, int volume, int pan) { @@ -169,7 +169,7 @@ int audio_play_sound(int soundId, int volume, int pan) int x2 = pan << 16; uint16 screenWidth = max(64, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16)); mixerPan = ((x2 / screenWidth) - 0x8000) >> 4; - } + } Mixer_Play_Effect(soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(mixerPan), 1, 1); return 0; @@ -194,7 +194,7 @@ void audio_start_title_music() pathId = PATH_ID_CSS17; break; case 3: - if (rand() & 1) + if (util_rand() & 1) pathId = PATH_ID_CSS50; else pathId = PATH_ID_CSS17; @@ -260,10 +260,10 @@ void audio_init_ride_sounds_and_info() if (file == NULL) continue; - uint32 head; - SDL_RWread(file, &head, sizeof(head), 1); - SDL_RWclose(file); - RCT2_GLOBAL(0x014241BC, uint32) = 0; + uint32 head; + SDL_RWread(file, &head, sizeof(head), 1); + SDL_RWclose(file); + RCT2_GLOBAL(0x014241BC, uint32) = 0; if (head == 0x78787878) rideMusicInfo->length = 0; } @@ -323,7 +323,7 @@ void audio_stop_vehicle_sounds() if (gOpenRCT2Headless || RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) == -1) return; - for (int i = 0; i < countof(gVehicleSoundList); i++) { + for (int i = 0; i < countof(gVehicleSoundList); i++) { rct_vehicle_sound *vehicleSound = &gVehicleSoundList[i]; if (vehicleSound->id == 0xFFFF) continue; diff --git a/src/game.c b/src/game.c index 26b21f0956..a53f67f12b 100644 --- a/src/game.c +++ b/src/game.c @@ -269,6 +269,9 @@ void game_update() } else { if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { numUpdates = 0; + // Update the animation list. Note this does not + // increment the map animation. + map_animation_invalidate_all(); } } diff --git a/src/management/research.c b/src/management/research.c index 5873493565..83df0fd6a1 100644 --- a/src/management/research.c +++ b/src/management/research.c @@ -417,6 +417,12 @@ static void research_insert_researched(int entryIndex, int category) { rct_research_item *researchItem, *researchItem2; + researchItem = gResearchItems; + // First check to make sure that entry is not already accounted for + for (; researchItem->entryIndex != RESEARCHED_ITEMS_END; researchItem++) { + if (researchItem->entryIndex == entryIndex) + return; + } researchItem = gResearchItems; do { if (researchItem->entryIndex == RESEARCHED_ITEMS_SEPARATOR) { diff --git a/src/network/network.cpp b/src/network/network.cpp index 8f48eda7c6..265da30a25 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -844,7 +844,7 @@ std::string Network::GenerateAdvertiseKey() static char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char key[17]; for (int i = 0; i < 16; i++) { - int hexCharIndex = rand() % countof(hexChars); + int hexCharIndex = util_rand() % countof(hexChars); key[i] = hexChars[hexCharIndex]; } key[countof(key) - 1] = 0; @@ -872,8 +872,8 @@ void Network::AdvertiseRegister() request.method = HTTP_METHOD_POST; json_t *body = json_object(); - json_object_set(body, "key", json_string(advertise_key.c_str())); - json_object_set(body, "port", json_integer(listening_port)); + json_object_set_new(body, "key", json_string(advertise_key.c_str())); + json_object_set_new(body, "port", json_integer(listening_port)); request.body = body; http_request_json_async(&request, [](http_json_response *response) -> void { @@ -916,21 +916,21 @@ void Network::AdvertiseHeartbeat() request.method = HTTP_METHOD_PUT; json_t *body = json_object(); - json_object_set(body, "token", json_string(advertise_token.c_str())); - json_object_set(body, "players", json_integer(network_get_num_players())); + json_object_set_new(body, "token", json_string(advertise_token.c_str())); + json_object_set_new(body, "players", json_integer(network_get_num_players())); json_t *gameInfo = json_object(); - json_object_set(gameInfo, "mapSize", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint8) - 2)); - json_object_set(gameInfo, "day", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16))); - json_object_set(gameInfo, "month", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16))); - json_object_set(gameInfo, "guests", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))); - json_object_set(gameInfo, "parkValue", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32))); + json_object_set_new(gameInfo, "mapSize", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint8) - 2)); + json_object_set_new(gameInfo, "day", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16))); + json_object_set_new(gameInfo, "month", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16))); + json_object_set_new(gameInfo, "guests", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))); + json_object_set_new(gameInfo, "parkValue", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32))); if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { money32 cash = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32)); - json_object_set(gameInfo, "cash", json_integer(cash)); + json_object_set_new(gameInfo, "cash", json_integer(cash)); } - json_object_set(body, "gameInfo", gameInfo); + json_object_set_new(body, "gameInfo", gameInfo); request.body = body; gNetwork.last_heartbeat_time = SDL_GetTicks(); @@ -1096,20 +1096,20 @@ void Network::Server_Send_GAMEINFO(NetworkConnection& connection) *packet << (uint32)NETWORK_COMMAND_GAMEINFO; #ifndef DISABLE_HTTP json_t* obj = json_object(); - json_object_set(obj, "name", json_string(gConfigNetwork.server_name)); - json_object_set(obj, "requiresPassword", json_boolean(password.size() > 0)); - json_object_set(obj, "version", json_string(OPENRCT2_VERSION)); - json_object_set(obj, "players", json_integer(player_list.size())); - json_object_set(obj, "maxPlayers", json_integer(gConfigNetwork.maxplayers)); - json_object_set(obj, "description", json_string(gConfigNetwork.server_description)); - json_object_set(obj, "dedicated", json_boolean(gOpenRCT2Headless)); + json_object_set_new(obj, "name", json_string(gConfigNetwork.server_name)); + json_object_set_new(obj, "requiresPassword", json_boolean(password.size() > 0)); + json_object_set_new(obj, "version", json_string(OPENRCT2_VERSION)); + json_object_set_new(obj, "players", json_integer(player_list.size())); + json_object_set_new(obj, "maxPlayers", json_integer(gConfigNetwork.maxplayers)); + json_object_set_new(obj, "description", json_string(gConfigNetwork.server_description)); + json_object_set_new(obj, "dedicated", json_boolean(gOpenRCT2Headless)); // Provider details json_t* jsonProvider = json_object(); - json_object_set(jsonProvider, "name", json_string(gConfigNetwork.provider_name)); - json_object_set(jsonProvider, "email", json_string(gConfigNetwork.provider_email)); - json_object_set(jsonProvider, "website", json_string(gConfigNetwork.provider_website)); - json_object_set(obj, "provider", jsonProvider); + json_object_set_new(jsonProvider, "name", json_string(gConfigNetwork.provider_name)); + json_object_set_new(jsonProvider, "email", json_string(gConfigNetwork.provider_email)); + json_object_set_new(jsonProvider, "website", json_string(gConfigNetwork.provider_website)); + json_object_set_new(obj, "provider", jsonProvider); packet->WriteString(json_dumps(obj, 0)); json_decref(obj); diff --git a/src/peep/peep.c b/src/peep/peep.c index 57c2b46867..03a7544a22 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -1768,7 +1768,7 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ } if (ride->price > peep->cash_in_pocket){ - peep_insert_new_thought(peep, 0, peep->current_ride); + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, peep->current_ride); if (peep->destination_tolerence == 0){ remove_peep_from_queue(peep); peep_decrement_num_riders(peep); @@ -7983,7 +7983,7 @@ loc_69B119: if (value > ((money16)(scenario_rand() & 0x07))) { // "I'm not paying that much for x" uint8 thought_type = (shopItem >= 32 ? (PEEP_THOUGHT_TYPE_PHOTO2_MUCH + (shopItem - 32)) : (PEEP_THOUGHT_TYPE_BALLOON_MUCH + shopItem)); - peep_insert_new_thought(peep, shopItem, rideIndex); + peep_insert_new_thought(peep, thought_type, rideIndex); return 0; } } diff --git a/src/rct2.c b/src/rct2.c index 7781f5af7b..23e2b88af6 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -47,6 +47,7 @@ #include "ride/track.h" #include "scenario.h" #include "title.h" +#include "util/util.h" #include "world/map.h" #include "world/park.h" #include "world/climate.h" @@ -79,7 +80,7 @@ int rct2_init() RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32) = 0; RCT2_GLOBAL(0x009AC310, char*) = RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, char*); get_system_time(); - srand((unsigned int)time(0)); + util_srand((unsigned int)time(0)); RCT2_GLOBAL(0x009DEA69, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, short); RCT2_GLOBAL(0x009DEA6B, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, short); if (!rct2_init_directories()) diff --git a/src/rct2.h b/src/rct2.h index a7d8904734..660536a691 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -103,7 +103,7 @@ typedef utf16* utf16string; // The following constants are for automated build servers #define OPENRCT2_BUILD_NUMBER "" #define OPENRCT2_BUILD_SERVER "" -#define OPENRCT2_BRANCH "develop" +#define OPENRCT2_BRANCH "pre-release-0.0.3" #define OPENRCT2_COMMIT_SHA1 "" #define OPENRCT2_COMMIT_SHA1_SHORT "" #define OPENRCT2_MASTER_SERVER_URL "https://servers.openrct2.website" diff --git a/src/title.c b/src/title.c index bf2d8ff5a3..a6b35904f9 100644 --- a/src/title.c +++ b/src/title.c @@ -524,24 +524,24 @@ static uint8 *generate_random_script() int i, j; const int views = 16; - srand((unsigned int)time(NULL)); + util_srand((unsigned int)time(NULL)); uint8 *script = malloc(views * 8 + 2); i = 0; script[i++] = TITLE_SCRIPT_LOAD; for (j = 0; j < views; j++) { script[i++] = TITLE_SCRIPT_LOCATION; - script[i++] = 64 + (rand() % 128); - script[i++] = 64 + (rand() % 128); + script[i++] = 64 + (util_rand() % 128); + script[i++] = 64 + (util_rand() % 128); - int rotationCount = rand() % 4; + int rotationCount = util_rand() % 4; if (rotationCount > 0) { script[i++] = TITLE_SCRIPT_ROTATE; script[i++] = rotationCount; } script[i++] = TITLE_SCRIPT_WAIT; - script[i++] = 8 + (rand() % 6); + script[i++] = 8 + (util_rand() % 6); } script[i] = TITLE_SCRIPT_RESTART; diff --git a/src/util/util.c b/src/util/util.c index bfccdfa706..890423e0fd 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -220,3 +220,21 @@ bool str_is_null_or_empty(const char *str) { return str == NULL || str[0] == 0; } + +uint32 srand0, srand1, srand2, srand3; + +void util_srand(int source) { + srand0 = source; + srand1 = srand0 ^ (source >> 24); + srand2 = srand1 ^ (source >> 16); + srand3 = srand2 ^ (source >> 8); +} + +uint32 util_rand() { + uint32 temp = srand0 ^ (srand0 << 11); + srand0 = srand1; + srand1 = srand2; + srand2 = srand3; + srand3 = srand3 ^ (srand3 >> 19) ^ temp ^ (temp >> 8); + return srand3; +} \ No newline at end of file diff --git a/src/util/util.h b/src/util/util.h index 8eba3a2b3f..23ea66c2d2 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -44,4 +44,7 @@ char *safe_strncpy(char * destination, const char * source, size_t num); bool utf8_is_bom(const char *str); bool str_is_null_or_empty(const char *str); +void util_srand(int source); +uint32 util_rand(); + #endif diff --git a/src/windows/editor_inventions_list.c b/src/windows/editor_inventions_list.c index c88b5ae741..a8396b77d1 100644 --- a/src/windows/editor_inventions_list.c +++ b/src/windows/editor_inventions_list.c @@ -29,6 +29,7 @@ #include "../world/scenery.h" #include "../interface/themes.h" #include "../rct1.h" +#include "../util/util.h" #pragma region Widgets @@ -344,7 +345,7 @@ static void research_items_shuffle() // Shuffle list for (i = 0; i < numNonResearchedItems; i++) { - ri = rand() % numNonResearchedItems; + ri = util_rand() % numNonResearchedItems; if (ri == i) continue; diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index e0470072ad..ffe8457740 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -861,9 +861,9 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde break; case WIDX_FILTER_CLEAR_BUTTON: memset(_filter_string, 0, sizeof(_filter_string)); - + filter_update_counts(); w->scrolls->v_top = 0; - + visible_list_refresh(w); window_invalidate(w); break; case WIDX_LIST_SORT_TYPE: diff --git a/src/windows/guest.c b/src/windows/guest.c index 3c5870e649..2a9eb29bdd 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -35,6 +35,7 @@ #include "../interface/viewport.h" #include "../interface/widget.h" #include "../interface/window.h" +#include "../util/util.h" #include "../world/footpath.h" #include "../world/map.h" #include "../world/sprite.h" @@ -1089,7 +1090,7 @@ void window_guest_overview_update(rct_window* w){ // Create the "I have the strangest feeling I am being watched thought" if ((w->var_494 & 0xFFFF) >= 3840) { if (!(w->var_494 & 0x3FF)) { - int random = rand() & 0xFFFF; + int random = util_rand() & 0xFFFF; if (random <= 0x2AAA) { rct_peep* peep = GET_PEEP(w->number); peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_WATCHED, 0xFF); diff --git a/src/windows/land.c b/src/windows/land.c index 066c435944..f97044bcea 100644 --- a/src/windows/land.c +++ b/src/windows/land.c @@ -45,7 +45,7 @@ enum WINDOW_LAND_WIDGET_IDX { }; static rct_widget window_land_widgets[] = { - { WWT_FRAME, 0, 0, 97, 0, 143, -1, STR_NONE }, // panel / background + { WWT_FRAME, 0, 0, 97, 0, 159, -1, STR_NONE }, // panel / background { WWT_CAPTION, 0, 1, 96, 1, 14, STR_LAND, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, 85, 95, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button @@ -133,7 +133,7 @@ void window_land_open() if (window_find_by_class(WC_LAND) != NULL) return; - window = window_create(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 98, 29, 98, 144, &window_land_events, WC_LAND, 0); + window = window_create(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 98, 29, 98, 160, &window_land_events, WC_LAND, 0); window->widgets = window_land_widgets; window->enabled_widgets = (1 << WIDX_CLOSE) | diff --git a/src/windows/mapgen.c b/src/windows/mapgen.c index 2c46c69e47..03cb6a5e18 100644 --- a/src/windows/mapgen.c +++ b/src/windows/mapgen.c @@ -25,6 +25,7 @@ #include "../interface/viewport.h" #include "../interface/window.h" #include "../sprites.h" +#include "../util/util.h" #include "../world/mapgen.h" #include "../world/scenery.h" #include "dropdown.h" @@ -716,8 +717,8 @@ static void window_mapgen_random_mouseup(rct_window *w, int widgetIndex) mapgenSettings.wall = _randomTerrrain ? -1 : _wallTexture; mapgenSettings.trees = _placeTrees; - mapgenSettings.simplex_low = rand() % 4; - mapgenSettings.simplex_high = 12 + (rand() % (32 - 12)); + mapgenSettings.simplex_low = util_rand() % 4; + mapgenSettings.simplex_high = 12 + (util_rand() % (32 - 12)); mapgenSettings.simplex_base_freq = 1.75f; mapgenSettings.simplex_octaves = 6; diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index da8c8c4110..881c4a845c 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -34,6 +34,7 @@ #include "../network/network.h" #include "../network/twitch.h" #include "../scenario.h" +#include "../util/util.h" #include "../world/scenery.h" #include "../world/banner.h" #include "dropdown.h" @@ -1116,7 +1117,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin uint8 rotation = window_scenery_rotation; if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG4)){ - rotation = rand() & 0xFF; + rotation = util_rand() & 0xFF; } rotation -= get_current_rotation(); @@ -1194,7 +1195,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin uint8 rotation = window_scenery_rotation; if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG4)){ - rotation = rand() & 0xFF; + rotation = util_rand() & 0xFF; } rotation -= get_current_rotation(); @@ -1440,11 +1441,11 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w if (window_scenery_is_build_cluster_tool_on){ if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)){ parameter_2 &= 0xFF00; - parameter_2 |= rand() & 3; + parameter_2 |= util_rand() & 3; } - cur_grid_x += ((rand() % 16) - 8) * 32; - cur_grid_y += ((rand() % 16) - 8) * 32; + cur_grid_x += ((util_rand() % 16) - 8) * 32; + cur_grid_y += ((util_rand() % 16) - 8) * 32; if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG4)){ RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_ROTATION, uint16)++; diff --git a/src/world/balloon.c b/src/world/balloon.c index 88fdaf320a..1d05313edc 100644 --- a/src/world/balloon.c +++ b/src/world/balloon.c @@ -1,5 +1,6 @@ #include "../audio/audio.h" #include "../scenario.h" +#include "../util/util.h" #include "sprite.h" /** @@ -68,7 +69,7 @@ void balloon_press(rct_balloon *balloon) if (balloon->popped == 1) return; - uint32 random = rand(); + uint32 random = util_rand(); if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) { balloon_pop(balloon); return; diff --git a/src/world/climate.c b/src/world/climate.c index ed1cac08d2..787438bf90 100644 --- a/src/world/climate.c +++ b/src/world/climate.c @@ -27,6 +27,7 @@ #include "../localisation/date.h" #include "../scenario.h" #include "../interface/window.h" +#include "../util/util.h" #include "climate.h" enum { @@ -112,7 +113,7 @@ void climate_reset(int climate) _rainVolume = 1; } - climate_determine_future_weather(rand()); + climate_determine_future_weather(util_rand()); } sint8 step_weather_level(sint8 cur_weather_level, sint8 next_weather_level) { diff --git a/src/world/footpath.c b/src/world/footpath.c index adc78bdde1..ee57d5e0b4 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -890,7 +890,12 @@ static void footpath_connect_corners(int initialX, int initialY, rct_map_element direction = (direction + 1) & 3; x += TileDirectionDelta[direction].x; y += TileDirectionDelta[direction].y; - mapElement[3] = footpath_connect_corners_get_neighbour(x, y, z, (1 << (direction ^ 2)) | (1 << (((direction ^ 2) - 1) & 3))); + // First check link to previous tile + mapElement[3] = footpath_connect_corners_get_neighbour(x, y, z, (1 << (direction ^ 2))); + if (mapElement[3] == NULL) + continue; + // Second check link to initial tile + mapElement[3] = footpath_connect_corners_get_neighbour(x, y, z, (1 << ((direction + 1) & 3))); if (mapElement[3] == NULL) continue; @@ -906,7 +911,7 @@ static void footpath_connect_corners(int initialX, int initialY, rct_map_element mapElement[1]->properties.path.edges |= (1 << (direction + 4)); map_invalidate_element(x, y, mapElement[1]); - direction = (direction - 1) & 3; + direction = initialDirection; mapElement[0]->properties.path.edges |= (1 << (direction + 4)); map_invalidate_element(x, y, mapElement[0]); } @@ -1342,6 +1347,7 @@ void footpath_chain_ride_queue(int rideIndex, int entranceIndex, int x, int y, r mapElement->properties.path.ride_index = rideIndex; mapElement->properties.path.additions &= 0x8F; mapElement->properties.path.additions |= (entranceIndex & 7) << 4; + if (lastQueuePathElement == NULL) { lastQueuePathElement = mapElement; } @@ -1837,7 +1843,7 @@ static void footpath_remove_edges_towards_here(int x, int y, int z, int directio mapElement->properties.path.edges &= ~(1 << d); d = (((d - 4) + 1) & 3) + 4; mapElement->properties.path.edges &= ~(1 << d); - map_invalidate_tile(x, y, mapElement->base_height, mapElement->clearance_height); + map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8); if (isQueue) footpath_disconnect_queue_from_path(x, y, mapElement, -1); @@ -1857,7 +1863,7 @@ static void footpath_remove_edges_towards_here(int x, int y, int z, int directio d = ((direction + 1) & 3) + 4; mapElement->properties.path.edges &= ~(1 << d); - map_invalidate_tile(x, y, mapElement->base_height, mapElement->clearance_height); + map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8); break; } while (!map_element_is_last_for_tile(mapElement++)); } diff --git a/src/world/map.c b/src/world/map.c index 6efe9cb3c4..6af8a11c14 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -3137,7 +3137,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in // Supports cost RCT2_GLOBAL(0x00F4389A, money32) = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && gConfigCheat.build_in_pause_mode) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -4263,7 +4263,7 @@ repeat: continue; map_element_remove_banner_entry(mapElement); - map_invalidate_tile_zoom1(x, y, mapElement->base_height, mapElement->base_height + 72); + map_invalidate_tile_zoom1(x, y, mapElement->base_height * 8, mapElement->base_height * 8 + 72); map_element_remove(mapElement); goto repeat; } while (!map_element_is_last_for_tile(mapElement++)); @@ -4367,7 +4367,7 @@ void map_invalidate_tile_full(int x, int y) void map_invalidate_element(int x, int y, rct_map_element *mapElement) { - map_invalidate_tile(x, y, mapElement->base_height, mapElement->clearance_height); + map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8); } int map_get_tile_side(int mapX, int mapY) @@ -4510,7 +4510,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc update_park_fences(x, y - 32); update_park_fences(x, y + 32); - map_invalidate_tile(x, y, newElement->base_height, newElement->clearance_height); + map_invalidate_tile(x, y, newElement->base_height * 8, newElement->clearance_height * 8); map_animation_create(MAP_ANIMATION_TYPE_PARK_ENTRANCE, x, y, zLow); } @@ -4547,7 +4547,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc update_park_fences(x, y - 32); update_park_fences(x, y + 32); - map_invalidate_tile(x, y, newElement->base_height, newElement->clearance_height); + map_invalidate_tile(x, y, newElement->base_height * 8, newElement->clearance_height * 8); } x += TileDirectionDelta[(direction + 1) & 0x3].x * 2; @@ -4582,7 +4582,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc update_park_fences(x, y - 32); update_park_fences(x, y + 32); - map_invalidate_tile(x, y, newElement->base_height, newElement->clearance_height); + map_invalidate_tile(x, y, newElement->base_height * 8, newElement->clearance_height * 8); } return 0; diff --git a/src/world/map_animation.c b/src/world/map_animation.c index 0ce1832451..ab45491527 100644 --- a/src/world/map_animation.c +++ b/src/world/map_animation.c @@ -49,6 +49,10 @@ void map_animation_create(int type, int x, int y, int z) { rct_map_animation *aobj = &gAnimatedObjects[0]; int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16); + if (numAnimatedObjects >= 2000) { + log_error("Exceeded the maximum number of animations"); + return; + } for (int i = 0; i < numAnimatedObjects; i++, aobj++) { if (aobj->x != x) continue; @@ -190,7 +194,7 @@ static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ) if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_IS_CLOCK) { // Peep, looking at scenery - if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x3FF)) { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x3FF) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) { int direction = mapElement->type & 3; int x2 = x - TileDirectionDelta[direction].x; int y2 = y - TileDirectionDelta[direction].y; @@ -320,6 +324,9 @@ static bool map_animation_invalidate_track_onridephoto(int x, int y, int baseZ) if (mapElement->properties.track.type == TRACK_ELEM_ON_RIDE_PHOTO) { int z = mapElement->base_height * 8; map_invalidate_tile_zoom1(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8); + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + return false; + } if (mapElement->properties.track.sequence & 0xF0) { mapElement->properties.track.sequence -= 0x10; return false; @@ -446,7 +453,7 @@ static bool map_animation_invalidate_large_scenery(int x, int y, int baseZ) * * rct2: 0x006E5B50 */ -static bool map_animation_invalidate_wall_unknown(int x, int y, int baseZ) +static bool map_animation_invalidate_wall_door(int x, int y, int baseZ) { rct_map_element *mapElement; rct_scenery_entry *sceneryEntry; @@ -485,7 +492,9 @@ static bool map_animation_invalidate_wall_unknown(int x, int y, int baseZ) } } } - + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + return false; + } mapElement->properties.fence.item[2] = bl; if (di & 1) { int z = mapElement->base_height * 8; @@ -541,6 +550,6 @@ static const map_animation_invalidate_event_handler _animatedObjectEventHandlers map_animation_invalidate_remove, map_animation_invalidate_banner, map_animation_invalidate_large_scenery, - map_animation_invalidate_wall_unknown, + map_animation_invalidate_wall_door, map_animation_invalidate_wall }; diff --git a/src/world/mapgen.c b/src/world/mapgen.c index 6d89306220..4650b4307e 100644 --- a/src/world/mapgen.c +++ b/src/world/mapgen.c @@ -21,6 +21,7 @@ #include #include "../addresses.h" #include "../object.h" +#include "../util/util.h" #include "map.h" #include "map_helpers.h" #include "mapgen.h" @@ -126,7 +127,7 @@ void mapgen_generate(mapgen_settings *settings) int x, y, mapSize, floorTexture, wallTexture, waterLevel; rct_map_element *mapElement; - srand((unsigned int)time(NULL)); + util_srand((unsigned int)time(NULL)); mapSize = settings->mapSize; floorTexture = settings->floor; @@ -134,7 +135,7 @@ void mapgen_generate(mapgen_settings *settings) waterLevel = settings->waterLevel; if (floorTexture == -1) - floorTexture = BaseTerrain[rand() % countof(BaseTerrain)]; + floorTexture = BaseTerrain[util_rand() % countof(BaseTerrain)]; if (wallTexture == -1) { // Base edge type on surface type @@ -172,7 +173,7 @@ void mapgen_generate(mapgen_settings *settings) if (1) { mapgen_simplex(settings); - mapgen_smooth_height(2 + (rand() % 6)); + mapgen_smooth_height(2 + (util_rand() % 6)); } else { // Keep overwriting the map with rough cicular blobs of different sizes and heights. // This procedural method can produce intersecting contour like land and lakes. @@ -200,7 +201,7 @@ void mapgen_generate(mapgen_settings *settings) // Add sandy beaches int beachTexture = floorTexture; if (settings->floor == -1 && floorTexture == TERRAIN_GRASS) { - switch (rand() % 4) { + switch (util_rand() % 4) { case 0: beachTexture = TERRAIN_SAND; break; @@ -235,7 +236,7 @@ static void mapgen_place_tree(int type, int x, int y) mapElement = map_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8)); mapElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3); - mapElement->type = MAP_ELEMENT_TYPE_SCENERY | (rand() % 3); + mapElement->type = MAP_ELEMENT_TYPE_SCENERY | (util_rand() % 3); mapElement->properties.scenery.type = type; mapElement->properties.scenery.age = 0; mapElement->properties.scenery.colour_1 = 26; @@ -310,7 +311,7 @@ static void mapgen_place_trees() // Shuffle list for (i = 0; i < availablePositionsCount; i++) { - rindex = rand() % availablePositionsCount; + rindex = util_rand() % availablePositionsCount; if (rindex == i) continue; @@ -320,7 +321,7 @@ static void mapgen_place_trees() } // Place trees - float treeToLandRatio = (10 + (rand() % 30)) / 100.0f; + float treeToLandRatio = (10 + (util_rand() % 30)) / 100.0f; int numTrees = max(4, (int)(availablePositionsCount * treeToLandRatio)); mapSize = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, sint16); @@ -336,7 +337,7 @@ static void mapgen_place_trees() if (numGrassTreeIds == 0) break; - type = grassTreeIds[rand() % numGrassTreeIds]; + type = grassTreeIds[util_rand() % numGrassTreeIds]; break; case TERRAIN_SAND: @@ -345,15 +346,15 @@ static void mapgen_place_trees() if (numDesertTreeIds == 0) break; - if (rand() % 4 == 0) - type = desertTreeIds[rand() % numDesertTreeIds]; + if (util_rand() % 4 == 0) + type = desertTreeIds[util_rand() % numDesertTreeIds]; break; case TERRAIN_ICE: if (numSnowTreeIds == 0) break; - type = snowTreeIds[rand() % numSnowTreeIds]; + type = snowTreeIds[util_rand() % numSnowTreeIds]; break; } @@ -392,15 +393,15 @@ static void mapgen_blobs(int count, int lowSize, int highSize, int lowHeight, in int sizeRange = highSize - lowSize; int heightRange = highHeight - lowHeight; - int border = 2 + (rand() % 24); + int border = 2 + (util_rand() % 24); int borderRange = _heightSize - (border * 2); for (i = 0; i < count; i++) { - int radius = lowSize + (rand() % sizeRange); + int radius = lowSize + (util_rand() % sizeRange); mapgen_blob( - border + (rand() % borderRange), - border + (rand() % borderRange), + border + (util_rand() % borderRange), + border + (util_rand() % borderRange), (int)(M_PI * radius * radius), - lowHeight + (rand() % heightRange) + lowHeight + (util_rand() % heightRange) ); } } @@ -506,7 +507,7 @@ static void mapgen_blob(int cx, int cy, int size, int height) set_height(x, y, BLOB_HEIGHT); while (currentSize < size) { - if (rand() % 2 == 0) { + if (util_rand() % 2 == 0) { set_height(x, y, BLOB_HEIGHT); currentSize++; } @@ -655,7 +656,7 @@ static uint8 perm[512]; static void noise_rand() { for (int i = 0; i < countof(perm); i++) - perm[i] = rand() & 0xFF; + perm[i] = util_rand() & 0xFF; } static float fractal_noise(int x, int y, float frequency, int octaves, float lacunarity, float persistence) diff --git a/src/world/particle.c b/src/world/particle.c index 4d2a9b7938..ecec4ff98d 100644 --- a/src/world/particle.c +++ b/src/world/particle.c @@ -1,4 +1,5 @@ #include "../audio/audio.h" +#include "../util/util.h" #include "sprite.h" /** @@ -18,12 +19,12 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, int x, int y, i 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->var_26 = (util_rand() & 0xFF) * 12; + sprite->var_24 = (util_rand() & 0x7F) + 140; + sprite->var_2E = ((util_rand() & 0xFF) * 5) >> 8; + sprite->acceleration_x = (util_rand() & 0xFFFF) * 4; + sprite->acceleration_y = (util_rand() & 0xFFFF) * 4; + sprite->acceleration_z = (util_rand() & 0xFFFF) * 4 + 0x10000; sprite->velocity_x = 0; sprite->velocity_y = 0; sprite->velocity_z = 0;