mirror of https://github.com/OpenRCT2/OpenRCT2.git
commit
801db92a17
5
clean.sh
5
clean.sh
|
@ -3,8 +3,5 @@
|
|||
set -ev
|
||||
|
||||
sudo rm -rf /usr/local/cross-tools/i686-w64-mingw32
|
||||
#rm -rf .cache
|
||||
rm -rf .cache/*.patch
|
||||
rm -rf .cache/SDL2-2.0.3
|
||||
rm -rf .cache/i686-w64-mingw32-pkg-config
|
||||
rm -rf .cache
|
||||
rm -rf build
|
||||
|
|
|
@ -20,4 +20,5 @@
|
|||
- Feature: RollerCoaster Tycoon 1 scenarios can now be opened in the scenario editor or by using the 'edit' command line action.
|
||||
- Feature: Title sequence music can now be disabled or changed to the RollerCoaster Tycoon 1 theme music.
|
||||
- Feature: (Random) map generator available in scenario editor, accessible via the view menu.
|
||||
- Feature: Looping RollerCoaster now supports both "Powered launch (passing station)" and "Powered launch (without passing station)"
|
||||
- Fix: Litter bins now get full and require emptying by handymen.
|
||||
|
|
|
@ -55,7 +55,7 @@ if [[ `uname` == "Darwin" ]]; then
|
|||
if [[ ! -f $cachedir/$mingw_tar ]]; then
|
||||
wget "https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Automated Builds/$mingw_tar" --output-document $cachedir/$mingw_tar
|
||||
fi
|
||||
if [[ ! -d $ming_path ]]; then
|
||||
if [[ ! -d "$mingw_path" ]]; then
|
||||
|
||||
pushd /usr/local/
|
||||
sudo mkdir $mingw_name
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
<ClCompile Include="..\src\world\map_animation.c" />
|
||||
<ClCompile Include="..\src\world\map_helpers.c" />
|
||||
<ClCompile Include="..\src\world\park.c" />
|
||||
<ClCompile Include="..\src\world\scenery.c" />
|
||||
<ClCompile Include="..\src\world\sprite.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -203,6 +204,7 @@
|
|||
<ClInclude Include="..\src\world\climate.h" />
|
||||
<ClInclude Include="..\src\world\entrance.h" />
|
||||
<ClInclude Include="..\src\world\footpath.h" />
|
||||
<ClInclude Include="..\src\world\fountain.h" />
|
||||
<ClInclude Include="..\src\world\map.h" />
|
||||
<ClInclude Include="..\src\world\mapgen.h" />
|
||||
<ClInclude Include="..\src\world\map_animation.h" />
|
||||
|
|
|
@ -351,11 +351,9 @@
|
|||
<ClCompile Include="..\src\windows\sign.c">
|
||||
<Filter>Source\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\src\ride\station.c">
|
||||
<Filter>Source\Ride</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\src\windows\ride_construction.c">
|
||||
<Filter>Source\Windows</Filter>
|
||||
</ClCompile>
|
||||
|
@ -374,7 +372,7 @@
|
|||
<ClCompile Include="..\src\diagnostic.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\libspeex\resample.c;..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\src\windows\editor_bottom_toolbar.c">
|
||||
<Filter>Source\Windows</Filter>
|
||||
</ClCompile>
|
||||
|
@ -384,7 +382,7 @@
|
|||
<ClCompile Include="..\src\windows\editor_object_selection.c">
|
||||
<Filter>Source\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\libspeex\resample.c;..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\lib\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\src\localisation\user.c">
|
||||
<Filter>Source\Localisation</Filter>
|
||||
</ClCompile>
|
||||
|
@ -429,6 +427,9 @@
|
|||
<ClCompile Include="..\src\world\map_animation.c">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\world\scenery.c">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\management\award.h">
|
||||
|
@ -632,5 +633,8 @@
|
|||
<ClInclude Include="..\src\world\map_animation.h">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\world\fountain.h">
|
||||
<Filter>Source\World</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
20
readme.md
20
readme.md
|
@ -14,7 +14,7 @@ An open source clone of RollerCoaster Tycoon 2 built by decompiling the original
|
|||
- 1.1 - [Background](#11-background)
|
||||
- 1.2 - [Decompiling the game](#12-decompiling-the-game)
|
||||
- 1.3 - [Progress](#13-progress)
|
||||
- 1.4 - [Aim](#14-aim)
|
||||
- 1.4 - [Aim](#14-aim)
|
||||
- 2 - [Downloading the game / Building the source code](#2-building-the-source-code)
|
||||
- 2.1 - [Prerequisites](#21-prerequisites)
|
||||
- 2.2 - [Compiling and running](#22-compiling-and-running)
|
||||
|
@ -29,7 +29,7 @@ An open source clone of RollerCoaster Tycoon 2 built by decompiling the original
|
|||
# 1 Introduction
|
||||
|
||||
## 1.1 Background
|
||||
**OpenRCT2** is an attempt to decompile RollerCoaster Tycoon 2 into C. RollerCoaster Tycoon 2 was originally written in MASM and Visual C++ where functions related to interfacing with the operating system were written in C (supposedly 1%), with the rest of the game being written in pure x86 assembly. For an example of this method, OpenTTD was formed through a similar procedure; the original game, Transport Tycoon Deluxe, was decompiled into C which allowed for the addition of thousands of features to the game. RollerCoaster Tycoon 2 uses the third version of Chris Sawyer's engine, which shares some code with Transport Tycoon. This is reflected in the usage of OpenTTD 0.1 code such as the windowing system and graphics rendering. While the version of the engine used in Chris Sawyer's Locomotion is newer, OpenRCT2 is currently targeting the RollerCoaster Tycoon 2 engine to ease the decompilation process.
|
||||
**OpenRCT2** is an attempt to decompile RollerCoaster Tycoon 2 into C. RollerCoaster Tycoon 2 was originally written in MASM and Visual C++ where functions related to interfacing with the operating system were written in C (supposedly 1%), with the rest of the game being written in pure x86 assembly. For an example of this method, OpenTTD was formed through a similar procedure; the original game, Transport Tycoon Deluxe, was decompiled into C which allowed for the addition of thousands of features to the game. RollerCoaster Tycoon 2 uses the third version of Chris Sawyer's engine, which shares some code with Transport Tycoon. This is reflected in the usage of OpenTTD 0.1 code such as the windowing system and graphics rendering. While the version of the engine used in Chris Sawyer's Locomotion is newer, OpenRCT2 is currently targeting the RollerCoaster Tycoon 2 engine to ease the decompilation process.
|
||||
|
||||
## 1.2 Decompiling the game
|
||||
In order to decompile the game gradually without introducing new bugs, each procedure in RollerCoaster Tycoon 2 is to be re-written in C on an individual basis. To test the accuracy of the re-written procedures, the decompiled C procedures are compiled into a DLL (*openrct2.dll*) which exports an entry procedure mimicking the WinMain function in RollerCoaster Tycoon 2. The original executable *rct2.exe* has been patched so that *openrct2.dll* and WinMain are in the DLL import table and the WinMain export procedure in *openrct2.dll* is called at the start of the WinMain procedure in *rct2.exe* before returning. With this system implemented, starting rct2.exe calls the new DLL as part of its initialization; the DLL can then run all the decompiled code whilst still being able to read / write to the *rct2.exe* memory model and run *rct2.exe* procedures.
|
||||
|
@ -42,17 +42,19 @@ Currently, the windowing system, graphics rendering and basic game loop are bein
|
|||
As of 16th August 2014, various UI improvements have already been made, settings are now stored in a local INI file. More drawing functions have now been decompiled but still remain cryptic C, much of the game management have been decompiled (e.g. peep generation, awards, cash out) and almost half of the windows. A rough estimate based on number of functions in the original game and number of functions now in C tells us that the project is approximately 25% complete of its target goal of having the game run on 100% C code. More information can be found in [changes to original game](https://github.com/IntelOrca/OpenRCT2/wiki/Changes-to-original-game) and [window progress](https://github.com/IntelOrca/OpenRCT2/wiki/Window-progress).
|
||||
|
||||
## 1.4 Aim
|
||||
The aim is to completely decompile RollerCoaster Tycoon 2 into C so that cross-platform support, new features, and new gameplay can be added in a similar fashion to OpenTTD. With the addition of SDL2, the game can already be run in a resizeable window (which was not possible originally). Once the game has been fully decompiled, additional gameplay features, gameplay tweaks, and improvements can be introduced. The following is only a brief, non-exhaustive list of the possibilities - there is much more possible:
|
||||
The aim is to completely decompile RollerCoaster Tycoon 2 into C so that cross-platform support, new features, and new gameplay can be added in a similar fashion to OpenTTD. With the addition of SDL2, the game can already be run in a resizeable window (which was not possible originally). Once the game has been fully decompiled, additional gameplay features, gameplay tweaks, and improvements can be introduced. The following is only a brief, non-exhaustive list of the possibilities - there are many more:
|
||||
|
||||
- Improved peep path-finding
|
||||
- Increased window / ride / object / map / construction limits
|
||||
- More sandbox-friendly gameplay
|
||||
- Editing available objects
|
||||
- Improved title sequence
|
||||
- Re-introduction of RollerCoaster Tycoon 1 mechanics
|
||||
- Shuttle Loop compatibility
|
||||
- Have Fun! objective
|
||||
- Finish building five coasters objective
|
||||
- Using the mountain tool during the game
|
||||
- Translation into more languages
|
||||
- Re-introduction of RollerCoaster Tycoon 1 mechanics:
|
||||
- Shuttle Loop compatibility
|
||||
- Have Fun! objective
|
||||
- Finish building five coasters objective
|
||||
- Using the mountain tool during the game
|
||||
|
||||
# 2 Downloading the game / Building the source code
|
||||
|
||||
|
@ -122,7 +124,7 @@ In general, small changes that improve code quality and make it easier to reason
|
|||
While decompilation is an ongoing process, this does not prohibit changes being made to the game. New features or bugfixes can be added, with caution, if the underlying code has been decompiled. When implementing these changes, ensure that comments are added to clearly identify where code has been intentionally changed so that it functions differently to the original game; this is essential to ensuring all research from reverse-engineering can still be applied.
|
||||
|
||||
## 3.5 Translation
|
||||
You can translate the game into other languages by editing the language files in the data directory. Please join discussions and submit pull requests to https://github.com/OpenRCT2/Localisation.
|
||||
Translations are in progress for German, Dutch, French, Hungarian, Polish, Spanish, Swedish, Italian, and more. You can translate the game into other languages by editing the language files in the data directory. Please join discussions and submit pull requests to https://github.com/OpenRCT2/Localisation.
|
||||
|
||||
# 4 License
|
||||
**OpenRCT2** is licensed under the GNU General Public License version 3.
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#define RCT2_ADDRESS_DSOUND_GUID 0x009AAC5D
|
||||
|
||||
#define RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER 0x009AAC6E
|
||||
// When all sounds reversed replace with gConfigSound.ride_music
|
||||
#define RCT2_ADDRESS_CONFIG_MUSIC 0x009AAC72
|
||||
|
||||
#define RCT2_ADDRESS_CONFIG_FLAGS 0x009AAC74
|
||||
|
@ -309,7 +310,7 @@
|
|||
#define RCT2_ADDRESS_SPRITES_NEXT_INDEX 0x013573BC
|
||||
#define RCT2_ADDRESS_SPRITES_START_VEHICLE 0x013573BE
|
||||
#define RCT2_ADDRESS_SPRITES_START_PEEP 0x013573C0
|
||||
#define RCT2_ADDRESS_SPRITES_START_TEXTFX 0x013573C2
|
||||
#define RCT2_ADDRESS_SPRITES_START_MISC 0x013573C2
|
||||
#define RCT2_ADDRESS_SPRITES_START_LITTER 0x013573C4
|
||||
|
||||
#define RCT2_ADDRESS_PARK_NAME 0x013573D4
|
||||
|
@ -396,6 +397,8 @@
|
|||
#define RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION 0x0138869E
|
||||
#define RCT2_ADDRESS_RIDE_MEASUREMENTS 0x0138B60C
|
||||
|
||||
#define RCT2_ADDRESS_GRASS_SCENERY_TILEPOS 0x013B0E70
|
||||
|
||||
#define RCT2_ADDRESS_CLIMATE 0x013CA746
|
||||
#define RCT2_ADDRESS_CURRENT_WEATHER 0x013CA74A
|
||||
#define RCT2_ADDRESS_NEXT_WEATHER 0x013CA74B
|
||||
|
|
|
@ -1768,6 +1768,18 @@ void audio_init2(int device)
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= 1 << 4;
|
||||
config_save_default();
|
||||
}
|
||||
|
||||
// When all sound code is reversed this can be removed.
|
||||
if (!gConfigSound.sound){
|
||||
toggle_all_sounds();
|
||||
}
|
||||
|
||||
// When all sound code is reversed this can be removed.
|
||||
if (!gConfigSound.ride_music){
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) ^= 1;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) == 0)
|
||||
stop_ride_music();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1794,19 +1806,34 @@ void audio_close()
|
|||
}
|
||||
}
|
||||
|
||||
/* rct2: 0x006BAB8A */
|
||||
void toggle_all_sounds(){
|
||||
// When all sound code is reversed replace with gConfigSound.sound
|
||||
RCT2_GLOBAL(0x009AF59D, uint8) ^= 1;
|
||||
if (RCT2_GLOBAL(0x009AF59D, uint8) == 0) {
|
||||
stop_title_music();
|
||||
pause_sounds();
|
||||
}
|
||||
else{
|
||||
unpause_sounds();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BABB4
|
||||
*/
|
||||
void pause_sounds()
|
||||
{
|
||||
if (++RCT2_GLOBAL(0x009AF59C, uint8) == 1) {
|
||||
// When all sound code is reversed replace with gConfigSound.sound
|
||||
RCT2_GLOBAL(0x009AF59C, uint8) = 1;
|
||||
if (RCT2_GLOBAL(0x009AF59C, uint8) == 1) {
|
||||
stop_other_sounds();
|
||||
stop_vehicle_sounds();
|
||||
stop_ride_music();
|
||||
stop_crowd_sound();
|
||||
}
|
||||
g_sounds_disabled = 1;
|
||||
gConfigSound.sound = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1815,8 +1842,9 @@ void pause_sounds()
|
|||
*/
|
||||
void unpause_sounds()
|
||||
{
|
||||
RCT2_GLOBAL(0x009AF59C, uint8)--;
|
||||
g_sounds_disabled = 0;
|
||||
// When all sound code is reversed replace with gConfigSound.sound
|
||||
RCT2_GLOBAL(0x009AF59C, uint8) = 0;
|
||||
gConfigSound.sound = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -218,13 +218,10 @@ void audio_init1();
|
|||
void audio_init2(int device);
|
||||
void audio_close();
|
||||
void pause_sounds();
|
||||
void toggle_all_sounds();
|
||||
void unpause_sounds();
|
||||
void stop_vehicle_sounds();
|
||||
|
||||
// 0x009AF59C probably does the same job
|
||||
// once it's confirmed and calls in pause_sounds() are reversed, it can be used instead of this
|
||||
int g_sounds_disabled;
|
||||
|
||||
typedef enum {
|
||||
SOUND_LIFT_1 = 0,
|
||||
SOUND_TRACK_FRICTION_1 = 1,
|
||||
|
|
|
@ -172,6 +172,8 @@ config_property_definition _soundDefinitions[] = {
|
|||
{ offsetof(sound_configuration, forced_software_buffering), "forced_software_buffering", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
|
||||
{ offsetof(sound_configuration, sound_quality), "sound_quality", CONFIG_VALUE_TYPE_UINT8, 2, NULL },
|
||||
{ offsetof(sound_configuration, title_music), "title_music", CONFIG_VALUE_TYPE_UINT8, 2, NULL },
|
||||
{ offsetof(sound_configuration, sound), "sound", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
|
||||
{ offsetof(sound_configuration, ride_music), "ride_music", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
|
||||
};
|
||||
|
||||
config_section_definition _sectionDefinitions[] = {
|
||||
|
|
|
@ -141,6 +141,8 @@ typedef struct {
|
|||
sint8 forced_software_buffering;
|
||||
sint8 sound_quality;
|
||||
uint8 title_music;
|
||||
uint8 sound;
|
||||
uint8 ride_music;
|
||||
} sound_configuration;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -707,7 +707,7 @@ static int editor_read_s4(rct1_s4 *src)
|
|||
|
||||
read((void*)0x0135A8F4, &src->string_table, 0x2F51C);
|
||||
memset((void*)0x013CA672, 0, 204);
|
||||
read((void*)0x0138B580, &src->animated_objects, 0x258F2);
|
||||
read((void*)0x0138B580, &src->map_animations, 0x258F2);
|
||||
read((void*)0x013C6A72, &src->patrol_areas, sizeof(src->patrol_areas));
|
||||
|
||||
char *esi = (char*)0x13C6A72;
|
||||
|
|
|
@ -308,11 +308,11 @@ void game_logic_update()
|
|||
sub_68B089();
|
||||
scenario_update();
|
||||
climate_update();
|
||||
fountain_update_all();
|
||||
map_update_tiles();
|
||||
sub_6A876D();
|
||||
peep_update_all();
|
||||
vehicle_update_all();
|
||||
texteffect_update_all();
|
||||
sprite_misc_update_all();
|
||||
ride_update_all();
|
||||
park_update();
|
||||
research_update();
|
||||
|
|
|
@ -751,20 +751,55 @@ void sub_688485(){
|
|||
|
||||
}
|
||||
|
||||
int sub_0x686806(rct_sprite* sprite, int eax, int ecx, int edx){
|
||||
int sub_0x686806(rct_sprite* sprite, int eax, int image_id, int ecx, int edx){
|
||||
int ebp = (eax >> 8) & 0xFF;
|
||||
edx <<= 16;
|
||||
ebp += RCT2_GLOBAL(0x9DEA56, uint16);
|
||||
RCT2_GLOBAL(0xF1AD28, uint32) = 0;
|
||||
RCT2_GLOBAL(0xF1AD2C, uint32) = 0;
|
||||
edx = (edx >> 16) | (ebp << 16);
|
||||
ebp = RCT2_GLOBAL(0xEE7888, uint32);
|
||||
if ((uint32)ebp >= RCT2_GLOBAL(0xEE7880, uint32)) return 1;
|
||||
//686840 not finished
|
||||
|
||||
//Not a paint struct but something similar
|
||||
paint_struct* ps = RCT2_GLOBAL(0xEE7888, paint_struct*);
|
||||
|
||||
if ((uint32)ps >= RCT2_GLOBAL(0xEE7880, uint32)) return 1;
|
||||
|
||||
ps->image_id = image_id;
|
||||
|
||||
rct_g1_element *g1Element = &RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element)[image_id & 0x7FFFF];
|
||||
|
||||
eax = (eax & 0xFF) + RCT2_GLOBAL(0x9DE568, uint16);
|
||||
ecx = (ecx & 0xFF) + RCT2_GLOBAL(0x9DE56C, uint16);
|
||||
|
||||
int x = ecx - eax;
|
||||
int y = (ecx + eax) / 2 - (edx & 0xFFFF);
|
||||
|
||||
ps->x = x;
|
||||
ps->y = y;
|
||||
|
||||
int left = x + g1Element->x_offset;
|
||||
int bottom = y + g1Element->y_offset;
|
||||
|
||||
int right = left + g1Element->width;
|
||||
int top = bottom + g1Element->height;
|
||||
|
||||
RCT2_GLOBAL(0xF1AD1C, uint16) = left;
|
||||
RCT2_GLOBAL(0xF1AD1E, uint16) = bottom;
|
||||
|
||||
rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
|
||||
|
||||
if (right <= dpi->x)return 1;
|
||||
if (top <= dpi->y)return 1;
|
||||
if (left > dpi->x + dpi->width) return 1;
|
||||
if (bottom > dpi->y + dpi->height) return 1;
|
||||
|
||||
RCT2_GLOBAL(0x9DE568, uint16);
|
||||
//686918 not finished
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Litter Paint Setup??
|
||||
* rct2: 0x006736FC
|
||||
|
@ -829,8 +864,8 @@ void sub_0x69E8B0(uint32 eax, uint32 ecx){
|
|||
eax = (eax & 0x1FE0) << 3 | (ecx >> 5);
|
||||
int sprite_idx = RCT2_ADDRESS(0xF1EF60, uint16)[eax];
|
||||
if (sprite_idx == SPRITE_INDEX_NULL) return;
|
||||
|
||||
for (rct_sprite* spr = &g_sprite_list[sprite_idx]; sprite_idx != SPRITE_INDEX_NULL; sprite_idx = spr->unknown.var_02){
|
||||
|
||||
for (rct_sprite* spr = &g_sprite_list[sprite_idx]; sprite_idx != SPRITE_INDEX_NULL; sprite_idx = spr->unknown.next_in_quadrant){
|
||||
spr = &g_sprite_list[sprite_idx];
|
||||
dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
|
||||
|
||||
|
@ -858,7 +893,7 @@ void sub_0x69E8B0(uint32 eax, uint32 ecx){
|
|||
case SPRITE_IDENTIFIER_PEEP:
|
||||
RCT2_CALLPROC_X(0x68F0FB, eax, ebx, ecx, edx, (int)spr, (int)dpi, ebp);
|
||||
break;
|
||||
case SPRITE_IDENTIFIER_FLOATING_TEXT:
|
||||
case SPRITE_IDENTIFIER_MISC:
|
||||
RCT2_CALLPROC_X(0x672AC9, eax, ebx, ecx, edx, (int)spr, (int)dpi, ebp);
|
||||
break;
|
||||
case SPRITE_IDENTIFIER_LITTER:
|
||||
|
|
|
@ -67,7 +67,7 @@ int viewport_interaction_get_item_left(int x, int y, viewport_interaction_info *
|
|||
switch (sprite->unknown.sprite_identifier) {
|
||||
case SPRITE_IDENTIFIER_VEHICLE:
|
||||
vehicle = &(sprite->vehicle);
|
||||
if (vehicle->var_D6 != 255)
|
||||
if (vehicle->ride_subtype != 255)
|
||||
vehicle_set_map_toolbar(vehicle);
|
||||
else
|
||||
info->type = VIEWPORT_INTERACTION_ITEM_NONE;
|
||||
|
@ -131,8 +131,17 @@ int viewport_interaction_left_click(int x, int y)
|
|||
case SPRITE_IDENTIFIER_PEEP:
|
||||
window_guest_open(info.peep);
|
||||
break;
|
||||
case SPRITE_IDENTIFIER_FLOATING_TEXT:
|
||||
balloon_pop(info.sprite);
|
||||
case SPRITE_IDENTIFIER_MISC:
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0) {
|
||||
switch (info.sprite->unknown.misc_identifier) {
|
||||
case SPRITE_MISC_BALLOON:
|
||||
balloon_press(&info.sprite->balloon);
|
||||
break;
|
||||
case SPRITE_MISC_DUCK:
|
||||
duck_press(&info.sprite->duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
|
@ -399,7 +408,7 @@ static void viewport_interaction_remove_footpath(rct_map_element *mapElement, in
|
|||
|
||||
w = window_find_by_class(WC_FOOTPATH);
|
||||
if (w != NULL)
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
|
||||
mapElement2 = map_get_first_element_at(x / 32, y / 32);
|
||||
do {
|
||||
|
|
|
@ -128,27 +128,7 @@ rct_widget *window_get_scroll_widget(rct_window *w, int scrollIndex)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
static void RCT2_CALLPROC_WE_UPDATE(int address, rct_window* w)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm {
|
||||
push address
|
||||
push w
|
||||
mov esi, w
|
||||
call[esp + 4]
|
||||
add esp, 8
|
||||
}
|
||||
#else
|
||||
__asm__ ( "\
|
||||
push %[address]\n\
|
||||
mov eax, %[w] \n\
|
||||
push eax \n\
|
||||
mov esi, %[w] \n\
|
||||
call [esp+4] \n\
|
||||
add esp, 8 \n\
|
||||
" : [address] "+m" (address), [w] "+m" (w) : : "eax", "esi" );
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006ED7B0
|
||||
|
@ -160,7 +140,7 @@ void window_dispatch_update_all()
|
|||
RCT2_GLOBAL(0x01423604, sint32)++;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16)++;
|
||||
for (w = RCT2_LAST_WINDOW; w >= g_window_list; w--)
|
||||
RCT2_CALLPROC_WE_UPDATE(w->event_handlers[WE_UPDATE], w);
|
||||
window_event_update_call(w);
|
||||
|
||||
RCT2_CALLPROC_EBPSAFE(0x006EE411); // handle_text_input
|
||||
}
|
||||
|
@ -1691,6 +1671,33 @@ void window_event_invalidate_call(rct_window* w)
|
|||
RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
|
||||
}
|
||||
|
||||
static void window_event_call_address(int address, rct_window *w)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm {
|
||||
push address
|
||||
push w
|
||||
mov esi, w
|
||||
call[esp + 4]
|
||||
add esp, 8
|
||||
}
|
||||
#else
|
||||
__asm__ ( "\
|
||||
push %[address]\n\
|
||||
mov eax, %[w] \n\
|
||||
push eax \n\
|
||||
mov esi, %[w] \n\
|
||||
call [esp+4] \n\
|
||||
add esp, 8 \n\
|
||||
" : [address] "+m" (address), [w] "+m" (w) : : "eax", "esi" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void window_event_update_call(rct_window *w)
|
||||
{
|
||||
window_event_call_address(w->event_handlers[WE_UPDATE], w);
|
||||
}
|
||||
|
||||
/**
|
||||
* rct2: New function not from rct2
|
||||
* Bubbles an item one position up in the window list.
|
||||
|
|
|
@ -579,6 +579,7 @@ void window_event_mouse_up_call(rct_window* w, int widgetIndex);
|
|||
void window_event_resize_call(rct_window* w);
|
||||
void window_event_mouse_down_call(rct_window* w, int widgetIndex);
|
||||
void window_event_invalidate_call(rct_window* w);
|
||||
void window_event_update_call(rct_window *w);
|
||||
|
||||
void sub_6EA73F();
|
||||
|
||||
|
|
|
@ -127,14 +127,14 @@ void finance_pay_ride_upkeep()
|
|||
FOR_ALL_RIDES(i, ride) {
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)) {
|
||||
ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
ride->var_196 = 25855; // durability?
|
||||
ride->reliability = RIDE_INITIAL_RELIABILITY;
|
||||
|
||||
}
|
||||
if (ride->status != RIDE_STATUS_CLOSED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) {
|
||||
sint16 upkeep = ride->upkeep_cost;
|
||||
if (upkeep != -1) {
|
||||
ride->total_profit -= upkeep;
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
finance_payment(upkeep, RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS);
|
||||
}
|
||||
}
|
||||
|
@ -297,4 +297,4 @@ void game_command_set_current_loan(int* eax, int* ebx, int* ecx, int* edx, int*
|
|||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,8 +92,9 @@ void marketing_update()
|
|||
|
||||
// This sets the string parameters for the marketing types that have an argument.
|
||||
if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) {
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaignItem, uint16);
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaignItem, uint32);
|
||||
rct_ride* ride = GET_RIDE(campaignItem);
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = ride->name;
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments;
|
||||
} else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) {
|
||||
campaignItem += 2016;
|
||||
if (campaignItem >= 2048)
|
||||
|
|
18
src/object.c
18
src/object.c
|
@ -439,7 +439,7 @@ int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dp
|
|||
chunk += 0x60;
|
||||
}
|
||||
|
||||
uint8* peep_loading_positions = chunk;
|
||||
sint8* peep_loading_positions = chunk;
|
||||
// Peep loading positions variable size
|
||||
// 4 different vehicle subtypes are available
|
||||
for (int i = 0; i < 4; ++i){
|
||||
|
@ -644,7 +644,7 @@ int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dp
|
|||
no_positions = *((uint16*)peep_loading_positions);
|
||||
peep_loading_positions += 2;
|
||||
}
|
||||
rideVehicleEntry->var_61 = (uint32)peep_loading_positions;
|
||||
rideVehicleEntry->peep_loading_positions = peep_loading_positions;
|
||||
peep_loading_positions += no_positions;
|
||||
}
|
||||
}
|
||||
|
@ -718,7 +718,7 @@ int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dp
|
|||
}
|
||||
rideVehicleEntry->var_02 = 0;
|
||||
rideVehicleEntry->var_03 = 0;
|
||||
rideVehicleEntry->var_61 = 0;
|
||||
rideVehicleEntry->peep_loading_positions = 0;
|
||||
}
|
||||
|
||||
ride_type->var_1AE = 0;
|
||||
|
@ -839,18 +839,18 @@ int paint_small_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
|
|||
|
||||
int image_id = scenery_type->image;
|
||||
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_HAS_PRIMARY_COLOUR){
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR){
|
||||
image_id |= 0x20D00000;
|
||||
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
|
||||
image_id |= 0x92000000;
|
||||
}
|
||||
|
||||
x = 56;
|
||||
y = scenery_type->small_scenery.height / 4 + 78;
|
||||
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG1){
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG2){
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE){
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE){
|
||||
y -= 12;
|
||||
}
|
||||
}
|
||||
|
@ -860,7 +860,7 @@ int paint_small_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
|
|||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG10){
|
||||
image_id = scenery_type->image + 0x44500004;
|
||||
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
|
||||
image_id |= 0x92000000;
|
||||
|
||||
gfx_draw_sprite(dpi, image_id, x, y, 0);
|
||||
|
@ -869,7 +869,7 @@ int paint_small_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo*
|
|||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG8){
|
||||
image_id = scenery_type->image + 4;
|
||||
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
|
||||
image_id |= 0x92000000;
|
||||
|
||||
gfx_draw_sprite(dpi, image_id, x, y, 0);
|
||||
|
|
2767
src/peep/peep.c
2767
src/peep/peep.c
File diff suppressed because it is too large
Load Diff
|
@ -209,6 +209,7 @@ enum PEEP_STATE {
|
|||
};
|
||||
|
||||
enum PEEP_ACTION_EVENTS {
|
||||
PEEP_ACTION_CHECK_TIME = 0,
|
||||
// If no food then check watch
|
||||
PEEP_ACTION_EAT_FOOD = 1,
|
||||
PEEP_ACTION_SHAKE_HEAD = 2,
|
||||
|
@ -344,18 +345,21 @@ typedef struct {
|
|||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 var_01;
|
||||
uint16 var_02; // 0x02
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09; // 0x09
|
||||
// Height from center of sprite to bottom
|
||||
uint8 sprite_height_negative; // 0x09
|
||||
uint16 sprite_index; // 0x0A
|
||||
uint16 var_0C;
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 var_14; // 0x14
|
||||
uint8 var_15; // 0x15
|
||||
// Width from center of sprite to edge
|
||||
uint8 sprite_width; // 0x14
|
||||
// Height from center of sprite to top
|
||||
uint8 sprite_height_positive; // 0x15
|
||||
sint16 sprite_left; // 0x16
|
||||
sint16 sprite_top; // 0x18
|
||||
sint16 sprite_right; // 0x1A
|
||||
|
@ -391,12 +395,13 @@ typedef struct {
|
|||
uint8 hunger; // 0x3E
|
||||
uint8 thirst; // 0x3F
|
||||
uint8 bathroom; // 0x40
|
||||
uint8 pad_41[0x2];
|
||||
uint8 var_41;
|
||||
uint8 var_42;
|
||||
uint8 intensity; // 0x43
|
||||
uint8 nausea_tolerance; // 0x44
|
||||
uint8 var_45; // Some sort of flags?
|
||||
money16 paid_on_drink; // 0x46
|
||||
uint8 pad_48[0x10];
|
||||
uint8 var_48[16];
|
||||
uint32 item_extra_flags; // 0x58
|
||||
uint8 photo2_ride_ref; // 0x5C
|
||||
uint8 photo3_ride_ref; // 0x5D
|
||||
|
@ -407,28 +412,34 @@ typedef struct {
|
|||
uint8 current_train; // 0x6A
|
||||
union{
|
||||
struct{
|
||||
uint8 current_car; // 0x6B
|
||||
uint8 current_seat; // 0x6C
|
||||
uint8 current_car; // 0x6B
|
||||
uint8 current_seat; // 0x6C
|
||||
};
|
||||
uint16 time_to_sitdown; //0x6B
|
||||
uint16 time_to_sitdown; //0x6B
|
||||
struct{
|
||||
uint8 time_to_stand; //0x6B
|
||||
uint8 standing_flags; //0x6C
|
||||
};
|
||||
};
|
||||
uint8 var_6D; // 0x6D
|
||||
uint8 var_6E; // 0x6E
|
||||
uint8 action_sprite_type; // 0x6E
|
||||
uint8 var_6F;
|
||||
uint8 var_70;
|
||||
uint8 action_sprite_image_offset; // 0x70
|
||||
uint8 action; // 0x71
|
||||
uint8 action_frame; // 0x72
|
||||
uint8 var_73;
|
||||
uint16 var_74;
|
||||
union {
|
||||
uint16 var_74; // time getting to ride to fix
|
||||
uint16 next_in_queue; // 0x74
|
||||
};
|
||||
uint8 var_76;
|
||||
uint8 pad_77;
|
||||
uint8 var_78;
|
||||
uint8 pad_79;
|
||||
uint16 var_7A; // time waiting in line possibly
|
||||
union{
|
||||
uint8 maze_last_edge; // 0x78
|
||||
uint8 var_78;
|
||||
};
|
||||
uint8 var_79;
|
||||
uint16 time_in_queue; // 0x7A
|
||||
uint8 rides_been_on[32]; // 0x7C
|
||||
// 255 bit bitmap of every ride the peep has been on see
|
||||
// window_peep_rides_update for how to use.
|
||||
|
@ -436,7 +447,7 @@ typedef struct {
|
|||
money32 cash_in_pocket; // 0xA0
|
||||
money32 cash_spent; // 0xA4
|
||||
sint32 time_in_park; // 0xA8
|
||||
uint8 var_AC; // 0xAC
|
||||
sint8 var_AC; // 0xAC
|
||||
uint8 previous_ride; // 0xAD
|
||||
uint16 previous_ride_time_out; // 0xAE
|
||||
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
|
||||
|
@ -454,7 +465,7 @@ typedef struct {
|
|||
uint32 flags; // 0xC8
|
||||
uint32 var_CC;
|
||||
uint8 pad_D0[0x10];
|
||||
uint8 var_E0; // 0xE0
|
||||
uint8 no_action_frame_no; // 0xE0
|
||||
uint8 var_E1;
|
||||
uint8 var_E2; // 0xE2
|
||||
uint8 var_E3;
|
||||
|
@ -479,10 +490,10 @@ typedef struct {
|
|||
uint8 no_of_food; // 0xEC
|
||||
uint8 no_of_drinks; // 0xED
|
||||
uint8 no_of_souvenirs; // 0xEE
|
||||
uint8 pad_EF;
|
||||
uint8 var_EF;
|
||||
uint8 voucher_type; // 0xF0
|
||||
uint8 voucher_arguments; // 0xF1 ride_id or string_offset_id
|
||||
uint8 pad_F2;
|
||||
uint8 var_F2;
|
||||
uint8 var_F3;
|
||||
uint8 var_F4;
|
||||
uint8 days_in_queue; // 0xF5
|
||||
|
@ -490,7 +501,8 @@ typedef struct {
|
|||
uint8 umbrella_colour; // 0xF7
|
||||
uint8 hat_colour; // 0xF8
|
||||
uint8 favourite_ride; // 0xF9
|
||||
uint16 pad_FA;
|
||||
uint8 var_FA;
|
||||
uint8 pad_FB;
|
||||
uint32 item_standard_flags; // 0xFC
|
||||
} rct_peep;
|
||||
|
||||
|
|
|
@ -107,9 +107,9 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
|
|||
move_sprite_to_list((rct_sprite *)newPeep, SPRITE_LINKEDLIST_OFFSET_PEEP);
|
||||
|
||||
newPeep->sprite_identifier = 1;
|
||||
newPeep->var_09 = 0x0F;
|
||||
newPeep->var_15 = 5;
|
||||
newPeep->var_14 = 8;
|
||||
newPeep->sprite_height_negative = 0x0F;
|
||||
newPeep->sprite_height_positive = 5;
|
||||
newPeep->sprite_width = 8;
|
||||
newPeep->sprite_direction = 0;
|
||||
|
||||
sprite_move(_ax, *ecx, _dx, (rct_sprite*)newPeep);
|
||||
|
@ -122,9 +122,9 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
|
|||
newPeep->var_45 = 0;
|
||||
newPeep->action = 0xFF;
|
||||
newPeep->var_6D = 0;
|
||||
newPeep->var_70 = 0;
|
||||
newPeep->var_E0 = 0;
|
||||
newPeep->var_6E = 0;
|
||||
newPeep->action_sprite_image_offset = 0;
|
||||
newPeep->no_action_frame_no = 0;
|
||||
newPeep->action_sprite_type = 0;
|
||||
newPeep->var_C4 = 0;
|
||||
newPeep->type = PEEP_TYPE_STAFF;
|
||||
newPeep->var_2A = 0;
|
||||
|
@ -176,9 +176,9 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
|
|||
newPeep->sprite_type = _eax;
|
||||
|
||||
_edx = RCT2_ADDRESS(0x0098270C, uint32)[_eax * 2];
|
||||
newPeep->var_14 = *((uint8*)_edx);
|
||||
newPeep->var_09 = *((uint8*)(_edx + 1));
|
||||
newPeep->var_15 = *((uint8*)(_edx + 2));
|
||||
newPeep->sprite_width = *((uint8*)_edx);
|
||||
newPeep->sprite_height_negative = *((uint8*)(_edx + 1));
|
||||
newPeep->sprite_height_positive = *((uint8*)(_edx + 2));
|
||||
|
||||
sprite_move( newPeep->x, newPeep->y, newPeep->z, (rct_sprite*)newPeep);
|
||||
invalidate_sprite((rct_sprite*)newPeep);
|
||||
|
|
|
@ -40,6 +40,13 @@ enum STAFF_TYPE {
|
|||
STAFF_TYPE_ENTERTAINER
|
||||
};
|
||||
|
||||
enum STAFF_ORDERS{
|
||||
STAFF_ORDERS_SWEEPING = (1 << 0),
|
||||
STAFF_ORDERS_WATER_FLOWERS = (1 << 1),
|
||||
STAFF_ORDERS_EMPTY_BINS = (1 << 2),
|
||||
STAFF_ORDERS_MOWING = (1 << 3)
|
||||
};
|
||||
|
||||
void game_command_update_staff_colour(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_hire_new_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
|
|
|
@ -174,8 +174,8 @@ typedef struct {
|
|||
uint16 view_y;
|
||||
uint8 view_zoom;
|
||||
uint8 view_rotation;
|
||||
uint8 animated_objects[6000];
|
||||
uint32 num_animated_objects;
|
||||
uint8 map_animations[6000];
|
||||
uint32 num_map_animations;
|
||||
uint8 unk_1CADBC[12];
|
||||
uint16 scrolling_text_step;
|
||||
uint32 unk_1CADCA;
|
||||
|
|
108
src/ride/ride.c
108
src/ride/ride.c
|
@ -210,7 +210,7 @@ void ride_update_favourited_stat()
|
|||
if (peep->favourite_ride != 0xff) {
|
||||
ride = &g_ride_list[peep->favourite_ride];
|
||||
ride->guests_favourite++;
|
||||
ride->var_14D |= 1;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER;
|
||||
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ static void ride_clear_for_construction(int rideIndex)
|
|||
ride_measurement_clear(ride);
|
||||
|
||||
ride->lifecycle_flags &= ~(RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN);
|
||||
ride->var_14D |= 0x0C;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
|
||||
ride_remove_cable_lift(ride);
|
||||
ride_remove_vehicles(ride);
|
||||
|
@ -764,7 +764,7 @@ static void ride_remove_peeps(int rideIndex)
|
|||
|
||||
ride->num_riders = 0;
|
||||
ride->var_15D = 0;
|
||||
ride->var_14D |= 4;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN;
|
||||
}
|
||||
|
||||
int sub_6C683D(int* x, int* y, int z, int direction, int type, int esi, int edi, int ebp)
|
||||
|
@ -1136,10 +1136,10 @@ static void ride_update(int rideIndex)
|
|||
ride->var_126 = ride->var_124;
|
||||
ride->var_124 = ride->var_120;
|
||||
ride->var_120 = 0;
|
||||
ride->var_14D |= 1;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER;
|
||||
|
||||
ride->income_per_hour = ride_calculate_income_per_hour(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
if (ride->upkeep_cost != (money16)0xFFFF)
|
||||
ride->profit = (ride->income_per_hour - ((money32)ride->upkeep_cost * 16));
|
||||
|
@ -1208,7 +1208,7 @@ void ride_update_popularity(rct_ride* ride, uint8 pop_amount){
|
|||
ride->popularity = ride->popularity_next;
|
||||
ride->popularity_next = 0;
|
||||
ride->popularity_time_out = 0;
|
||||
ride->var_14D |= 1;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1245,10 +1245,12 @@ static void ride_spiral_slide_update(rct_ride *ride)
|
|||
|
||||
mapElement = ride_get_station_start_track_element(ride, i);
|
||||
int rotation = ((mapElement->type & 3) << 2) | RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8);
|
||||
x += RCT2_GLOBAL(0x0098DDB8 + (rotation * 4), uint16);
|
||||
y += RCT2_GLOBAL(0x0098DDBA + (rotation * 4), uint16);
|
||||
x *= 32;
|
||||
y *= 32;
|
||||
x += RCT2_GLOBAL(0x0098DDB8 + (rotation * 4), sint16);
|
||||
y += RCT2_GLOBAL(0x0098DDBA + (rotation * 4), sint16);
|
||||
|
||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||
gfx_invalidate_scrollingtext(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1309,13 +1311,35 @@ static void ride_inspection_update(rct_ride *ride)
|
|||
}
|
||||
}
|
||||
|
||||
static int get_age_penalty(rct_ride *ride) {
|
||||
int years;
|
||||
years = date_get_year(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) - ride->build_date);
|
||||
switch (years) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return ride->unreliability_factor / 8;
|
||||
case 2:
|
||||
return ride->unreliability_factor / 4;
|
||||
case 3:
|
||||
case 4:
|
||||
return ride->unreliability_factor / 2;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
return ride->unreliability_factor;
|
||||
default:
|
||||
return ride->unreliability_factor * 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AC622
|
||||
*/
|
||||
static void ride_breakdown_update(int rideIndex)
|
||||
{
|
||||
int agePenalty, years, ax, breakdownReason;
|
||||
int breakdownReason, unreliabilityAccumulator;
|
||||
rct_ride *ride = GET_RIDE(rideIndex);
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 255)
|
||||
|
@ -1335,7 +1359,7 @@ static void ride_breakdown_update(int rideIndex)
|
|||
ride->var_1A0 +
|
||||
ride->var_1A2 +
|
||||
ride->var_1A3;
|
||||
ride->var_199 = min(ax / 2, 100);
|
||||
ride->downtime = min(ax / 2, 100);
|
||||
|
||||
ride->var_1A3 = ride->var_1A2;
|
||||
ride->var_1A2 = ride->var_1A1;
|
||||
|
@ -1345,7 +1369,7 @@ static void ride_breakdown_update(int rideIndex)
|
|||
ride->var_19E = ride->var_19D;
|
||||
ride->var_19D = ride->var_19C;
|
||||
ride->var_19C = 0;
|
||||
ride->var_14D |= 32;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
}
|
||||
|
||||
if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))
|
||||
|
@ -1354,38 +1378,17 @@ static void ride_breakdown_update(int rideIndex)
|
|||
return;
|
||||
|
||||
// Calculate breakdown probability?
|
||||
ax = ride->var_198;
|
||||
agePenalty;
|
||||
years = date_get_year(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) - ride->build_date);
|
||||
switch (years) {
|
||||
case 0:
|
||||
agePenalty = 0;
|
||||
break;
|
||||
case 1:
|
||||
agePenalty = ax >> 3;
|
||||
break;
|
||||
case 2:
|
||||
agePenalty = ax >> 2;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
agePenalty = ax >> 1;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
agePenalty = ax >> 0;
|
||||
break;
|
||||
default:
|
||||
agePenalty = ax << 1;
|
||||
break;
|
||||
}
|
||||
ax += agePenalty;
|
||||
ride->var_196 = max(0, ride->var_196 - ax);
|
||||
ride->var_14D |= 32;
|
||||
unreliabilityAccumulator = ride->unreliability_factor + get_age_penalty(ride);
|
||||
ride->reliability = max(0, ride->reliability - unreliabilityAccumulator);
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
|
||||
// Random probability of a breakdown
|
||||
if (ride->var_196 == 0 || (int)(scenario_rand() & 0x2FFFFF) <= 25856 - ride->var_196) {
|
||||
// Random probability of a breakdown. Roughly this is 1 in
|
||||
//
|
||||
// (25000 - reliability) / 3 000 000
|
||||
//
|
||||
// a 0.8% chance, less the breakdown factor which accumulates as the game
|
||||
// continues.
|
||||
if (ride->reliability == 0 || (int)(scenario_rand() & 0x2FFFFF) <= 1 + RIDE_INITIAL_RELIABILITY - ride->reliability) {
|
||||
breakdownReason = ride_get_new_breakdown_problem(ride);
|
||||
if (breakdownReason != -1)
|
||||
ride_prepare_breakdown(rideIndex, breakdownReason);
|
||||
|
@ -1443,9 +1446,8 @@ static int ride_get_new_breakdown_problem(rct_ride *ride)
|
|||
if (ride->num_vehicles != 1)
|
||||
return -1;
|
||||
|
||||
// Again the probability is lower, this time if young or two other unknown reasons...
|
||||
monthsOld = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint8) - ride->build_date;
|
||||
if (monthsOld < 16 || ride->var_196 > 12800 || ride->lifecycle_flags & RIDE_LIFECYCLE_SIX_FLAGS)
|
||||
if (monthsOld < 16 || ride->reliability > (50 << 8) || ride->lifecycle_flags & RIDE_LIFECYCLE_SIX_FLAGS)
|
||||
return -1;
|
||||
|
||||
return BREAKDOWN_BRAKES_FAILURE;
|
||||
|
@ -1580,7 +1582,7 @@ static void ride_mechanic_status_update(int rideIndex, int mechanicStatus)
|
|||
breakdownReason == BREAKDOWN_CONTROL_FAILURE
|
||||
) {
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_BROKEN_DOWN;
|
||||
ride->var_14D |= 0x2C;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE | RIDE_INVALIDATE_RIDE_LIST | RIDE_INVALIDATE_RIDE_MAIN;
|
||||
ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING;
|
||||
ride->breakdown_reason = breakdownReason;
|
||||
ride_breakdown_add_news_item(rideIndex);
|
||||
|
@ -1602,7 +1604,7 @@ static void ride_mechanic_status_update(int rideIndex, int mechanicStatus)
|
|||
mechanic->current_ride != rideIndex
|
||||
) {
|
||||
ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING;
|
||||
ride->var_14D |= 0x20;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
ride_mechanic_status_update(rideIndex, RIDE_MECHANIC_STATUS_CALLING);
|
||||
}
|
||||
break;
|
||||
|
@ -1618,7 +1620,7 @@ static void ride_mechanic_status_update(int rideIndex, int mechanicStatus)
|
|||
)
|
||||
) {
|
||||
ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING;
|
||||
ride->var_14D |= 0x20;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
ride_mechanic_status_update(rideIndex, RIDE_MECHANIC_STATUS_CALLING);
|
||||
}
|
||||
break;
|
||||
|
@ -1639,7 +1641,7 @@ static void ride_call_mechanic(int rideIndex, rct_peep *mechanic, int forInspect
|
|||
peep_window_state_update(mechanic);
|
||||
mechanic->sub_state = 0;
|
||||
ride->mechanic_status = RIDE_MECHANIC_STATUS_HEADING;
|
||||
ride->var_14D |= 0x20;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
ride->mechanic = mechanic->sprite_index;
|
||||
mechanic->current_ride = rideIndex;
|
||||
mechanic->current_ride_station = ride->inspection_station;
|
||||
|
@ -1882,7 +1884,7 @@ void ride_measurement_update(rct_ride_measurement *measurement)
|
|||
return;
|
||||
|
||||
measurement->flags &= ~RIDE_MEASUREMENT_FLAG_UNLOADING;
|
||||
if (measurement->var_0B == vehicle->var_4B)
|
||||
if (measurement->current_station == vehicle->current_station)
|
||||
measurement->current_item = 0;
|
||||
}
|
||||
|
||||
|
@ -1966,7 +1968,7 @@ void ride_measurements_update()
|
|||
vehicle = &(g_sprite_list[spriteIndex].vehicle);
|
||||
if (vehicle->status == VEHICLE_STATUS_DEPARTING || vehicle->status == VEHICLE_STATUS_STOPPING) {
|
||||
measurement->vehicle_index = j;
|
||||
measurement->var_0B = vehicle->var_4B;
|
||||
measurement->current_station = vehicle->current_station;
|
||||
measurement->flags |= RIDE_MEASUREMENT_FLAG_RUNNING;
|
||||
measurement->flags &= ~RIDE_MEASUREMENT_FLAG_UNLOADING;
|
||||
ride_measurement_update(measurement);
|
||||
|
@ -3479,7 +3481,7 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
|
|||
ride->status = RIDE_STATUS_CLOSED;
|
||||
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
|
||||
ride->race_winner = 0xFFFF;
|
||||
ride->var_14D |= (1 << 2) | (1 << 3);
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
window_invalidate_by_number(WC_RIDE, rideIndex);
|
||||
}
|
||||
*ebx = 0;
|
||||
|
@ -3500,7 +3502,7 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
|
|||
ride->race_winner = 0xFFFF;
|
||||
ride->status = targetStatus;
|
||||
ride_get_measurement(rideIndex, NULL);
|
||||
ride->var_14D |= (1 << 2) | (1 << 3);
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
window_invalidate_by_number(WC_RIDE, rideIndex);
|
||||
}
|
||||
*ebx = 0;
|
||||
|
|
|
@ -82,12 +82,14 @@ typedef struct{
|
|||
uint32 var_4C; // 0x4C , 0x66
|
||||
uint32 no_vehicle_images; // 0x50 , 0x6A
|
||||
uint8 no_seating_rows; // 0x54 , 0x6E
|
||||
uint8 pad_55[0x7];
|
||||
uint8 pad_55[0x5];
|
||||
uint8 var_5A; // 0x5A , 0x74
|
||||
uint8 pad_5B; // 0x5B , 0x75
|
||||
uint8 var_5C; // 0x5C , 0x76
|
||||
uint8 var_5D; // 0x5D , 0x77
|
||||
uint8 pad_5E[0x2];
|
||||
uint8 var_60; // 0x60 , 0x7A
|
||||
uint32 var_61; // 0x61 , 0x7B
|
||||
sint8* peep_loading_positions; // 0x61 , 0x7B
|
||||
} rct_ride_type_vehicle;
|
||||
|
||||
/**
|
||||
|
@ -103,12 +105,13 @@ typedef struct {
|
|||
uint8 var_00C;
|
||||
uint8 var_00D;
|
||||
uint8 var_00E;
|
||||
uint8 var_00F;
|
||||
uint8 var_010;
|
||||
uint8 min_cars_in_train; // 0x00F
|
||||
uint8 max_cars_in_train; // 0x010
|
||||
uint8 var_011;
|
||||
uint8 var_012;
|
||||
uint8 var_013;
|
||||
uint8 pad_014[0x6];
|
||||
uint8 var_014;
|
||||
uint8 pad_015[0x5];
|
||||
rct_ride_type_vehicle vehicles[4]; // 0x1A
|
||||
uint32 var_1AE;
|
||||
sint8 excitement_multipler; // 0x1B2
|
||||
|
@ -148,7 +151,8 @@ typedef struct {
|
|||
uint8 var_066[4];
|
||||
uint16 entrances[4]; // 0x06A
|
||||
uint16 exits[4]; // 0x072
|
||||
uint8 pad_07A[0x0C];
|
||||
uint16 first_peep_in_queue[4]; // 0x07A
|
||||
uint8 pad_082[4];
|
||||
uint16 vehicles[32]; // 0x086 Points to the first car in the train
|
||||
uint8 depart_flags; // 0x0C6
|
||||
|
||||
|
@ -218,12 +222,13 @@ typedef struct {
|
|||
ride_rating nausea; // 0x144
|
||||
};
|
||||
};
|
||||
uint16 reliability; // 0x146
|
||||
uint16 value; // 0x146
|
||||
uint16 var_148;
|
||||
uint8 satisfaction; // 0x14A
|
||||
uint8 satisfaction_time_out; // 0x14B
|
||||
uint8 satisfaction_next; // 0x14C
|
||||
uint8 var_14D;
|
||||
// Various flags stating whether a window needs to be refreshed
|
||||
uint8 window_invalidate_flags; // 0x14D
|
||||
uint8 pad_14E[0x02];
|
||||
uint32 total_customers; // 0x150
|
||||
money32 total_profit; // 0x154
|
||||
|
@ -237,7 +242,9 @@ typedef struct {
|
|||
uint16 slide_peep; // 0x15E
|
||||
uint16 maze_tiles; // 0x15E
|
||||
};
|
||||
uint8 pad_160[0x16];
|
||||
uint8 pad_160[0xE];
|
||||
uint8 slide_peep_t_shirt_colour;// 0x16E
|
||||
uint8 pad_16F[0x7];
|
||||
uint8 var_176;
|
||||
uint8 pad_177[0x9];
|
||||
sint16 build_date; // 0x180
|
||||
|
@ -253,10 +260,14 @@ typedef struct {
|
|||
uint8 broken_car; // 0x192
|
||||
uint8 breakdown_reason; // 0x193
|
||||
money16 price_secondary; // 0x194
|
||||
uint16 var_196;
|
||||
// used in computing excitement, nausea, etc
|
||||
uint8 var_198;
|
||||
uint8 var_199;
|
||||
// Starts at RIDE_INITIAL_RELIABILITY and decreases from there. Right shift
|
||||
// this number by 8 to get a reliability percentage 0-100
|
||||
uint16 reliability;
|
||||
// Small constant used to increase the unreliability as the game continues,
|
||||
// making breakdowns more and more likely.
|
||||
uint8 unreliability_factor;
|
||||
// Range from [0, 100]
|
||||
uint8 downtime; // 0x199
|
||||
uint8 inspection_interval; // 0x19A
|
||||
uint8 last_inspection; // 0x19B
|
||||
uint8 var_19C;
|
||||
|
@ -309,7 +320,7 @@ typedef struct {
|
|||
uint16 num_items; // 0x0006
|
||||
uint16 current_item; // 0x0008
|
||||
uint8 vehicle_index; // 0x000A
|
||||
uint8 var_0B;
|
||||
uint8 current_station; // 0x000B
|
||||
sint8 vertical[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x000C
|
||||
sint8 lateral[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x12CC
|
||||
uint8 velocity[RIDE_MEASUREMENT_MAX_ITEMS]; // 0x258C
|
||||
|
@ -358,7 +369,7 @@ enum {
|
|||
RIDE_TYPE_MINI_SUSPENDED_COASTER,
|
||||
RIDE_TYPE_BUMPER_BOATS,
|
||||
RIDE_TYPE_WOODEN_WILD_MOUSE,
|
||||
RIDE_TYPE_STEEPLECHASE,
|
||||
RIDE_TYPE_STEEPLECHASE = 10,
|
||||
RIDE_TYPE_CAR_RIDE,
|
||||
RIDE_TYPE_LAUNCHED_FREEFALL,
|
||||
RIDE_TYPE_BOBSLEIGH_COASTER,
|
||||
|
@ -368,7 +379,7 @@ enum {
|
|||
RIDE_TYPE_MINE_TRAIN_COASTER,
|
||||
RIDE_TYPE_CHAIRLIFT,
|
||||
RIDE_TYPE_CORKSCREW_ROLLER_COASTER,
|
||||
RIDE_TYPE_MAZE,
|
||||
RIDE_TYPE_MAZE = 20,
|
||||
RIDE_TYPE_SPIRAL_SLIDE,
|
||||
RIDE_TYPE_GO_KARTS,
|
||||
RIDE_TYPE_LOG_FLUME,
|
||||
|
@ -378,7 +389,7 @@ enum {
|
|||
RIDE_TYPE_SWINGING_INVERTER_SHIP,
|
||||
RIDE_TYPE_FOOD_STALL,
|
||||
RIDE_TYPE_1D,
|
||||
RIDE_TYPE_DRINK_STALL,
|
||||
RIDE_TYPE_DRINK_STALL = 30,
|
||||
RIDE_TYPE_1F,
|
||||
RIDE_TYPE_SHOP,
|
||||
RIDE_TYPE_MERRY_GO_ROUND,
|
||||
|
@ -388,7 +399,7 @@ enum {
|
|||
RIDE_TYPE_FERRIS_WHEEL,
|
||||
RIDE_TYPE_MOTION_SIMULATOR,
|
||||
RIDE_TYPE_3D_CINEMA,
|
||||
RIDE_TYPE_TOP_SPIN,
|
||||
RIDE_TYPE_TOP_SPIN = 40,
|
||||
RIDE_TYPE_SPACE_RINGS,
|
||||
RIDE_TYPE_REVERSE_FREEFALL_COASTER,
|
||||
RIDE_TYPE_ELEVATOR,
|
||||
|
@ -398,7 +409,7 @@ enum {
|
|||
RIDE_TYPE_HAUNTED_HOUSE,
|
||||
RIDE_TYPE_FIRST_AID,
|
||||
RIDE_TYPE_CIRCUS_SHOW,
|
||||
RIDE_TYPE_GHOST_TRAIN,
|
||||
RIDE_TYPE_GHOST_TRAIN = 50,
|
||||
RIDE_TYPE_TWISTER_ROLLER_COASTER,
|
||||
RIDE_TYPE_WOODEN_ROLLER_COASTER,
|
||||
RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER,
|
||||
|
@ -408,7 +419,7 @@ enum {
|
|||
RIDE_TYPE_FLYING_ROLLER_COASTER,
|
||||
RIDE_TYPE_3A,
|
||||
RIDE_TYPE_VIRGINIA_REEL,
|
||||
RIDE_TYPE_SPLASH_BOATS,
|
||||
RIDE_TYPE_SPLASH_BOATS = 60,
|
||||
RIDE_TYPE_MINI_HELICOPTERS,
|
||||
RIDE_TYPE_LAY_DOWN_ROLLER_COASTER,
|
||||
RIDE_TYPE_SUSPENDED_MONORAIL,
|
||||
|
@ -418,7 +429,7 @@ enum {
|
|||
RIDE_TYPE_MINI_GOLF,
|
||||
RIDE_TYPE_GIGA_COASTER,
|
||||
RIDE_TYPE_ROTO_DROP,
|
||||
RIDE_TYPE_FLYING_SAUCERS,
|
||||
RIDE_TYPE_FLYING_SAUCERS = 70,
|
||||
RIDE_TYPE_CROOKED_HOUSE,
|
||||
RIDE_TYPE_MONORAIL_CYCLES,
|
||||
RIDE_TYPE_COMPACT_INVERTED_COASTER,
|
||||
|
@ -428,7 +439,7 @@ enum {
|
|||
RIDE_TYPE_MAGIC_CARPET,
|
||||
RIDE_TYPE_SUBMARINE_RIDE,
|
||||
RIDE_TYPE_RIVER_RAFTS,
|
||||
RIDE_TYPE_50,
|
||||
RIDE_TYPE_50 = 80,
|
||||
RIDE_TYPE_ENTERPRISE,
|
||||
RIDE_TYPE_52,
|
||||
RIDE_TYPE_53,
|
||||
|
@ -438,7 +449,7 @@ enum {
|
|||
RIDE_TYPE_MINI_ROLLER_COASTER,
|
||||
RIDE_TYPE_MINE_RIDE,
|
||||
RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER,
|
||||
RIDE_TYPE_90
|
||||
RIDE_TYPE_90 = 90
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -605,6 +616,16 @@ enum {
|
|||
RIDE_INSPECTION_NEVER
|
||||
};
|
||||
|
||||
// Flags used by ride->window_invalidate_flags
|
||||
enum {
|
||||
RIDE_INVALIDATE_RIDE_CUSTOMER = 1,
|
||||
RIDE_INVALIDATE_RIDE_INCOME = 1 << 1,
|
||||
RIDE_INVALIDATE_RIDE_MAIN = 1 << 2,
|
||||
RIDE_INVALIDATE_RIDE_LIST = 1 << 3,
|
||||
RIDE_INVALIDATE_RIDE_OPERATING = 1 << 4,
|
||||
RIDE_INVALIDATE_RIDE_MAINTENANCE = 1 << 5,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8 main;
|
||||
uint8 additional;
|
||||
|
@ -661,7 +682,8 @@ enum {
|
|||
#define MAX_RIDES 255
|
||||
|
||||
#define MAX_RIDE_MEASUREMENTS 8
|
||||
#define RIDE_RELIABILITY_UNDEFINED 0xFFFF
|
||||
#define RIDE_VALUE_UNDEFINED 0xFFFF
|
||||
#define RIDE_INITIAL_RELIABILITY ((100 << 8) - 1)
|
||||
|
||||
#define STATION_DEPART_FLAG (1 << 7)
|
||||
#define STATION_DEPART_MASK (~STATION_DEPART_FLAG)
|
||||
|
@ -721,7 +743,8 @@ int sub_6C683D(int* x, int* y, int z, int direction, int type, int esi, int edi,
|
|||
void ride_set_map_tooltip(rct_map_element *mapElement);
|
||||
int ride_music_params_update(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint16 sampleRate, uint32 position, uint8 *tuneId);
|
||||
void ride_music_update_final();
|
||||
|
||||
rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex);
|
||||
rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int z);
|
||||
void ride_set_status(int rideIndex, int status);
|
||||
void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void ride_set_name(int rideIndex, const char *name);
|
||||
|
|
|
@ -49,7 +49,7 @@ static void ride_ratings_update_state_4();
|
|||
static void ride_ratings_update_state_5();
|
||||
static void loc_6B5BB2();
|
||||
static void ride_ratings_calculate(rct_ride *ride);
|
||||
static void ride_ratings_reliability_calculate(rct_ride *ride);
|
||||
static void ride_ratings_calculate_value(rct_ride *ride);
|
||||
|
||||
static int sub_6C6402(rct_map_element *mapElement, int *x, int *y, int *z)
|
||||
{
|
||||
|
@ -283,7 +283,7 @@ static void ride_ratings_update_state_3()
|
|||
|
||||
ride_ratings_calculate(ride);
|
||||
RCT2_CALLPROC_X(0x00655F64, 0, 0, 0, 0, 0, (int)ride, 0);
|
||||
ride_ratings_reliability_calculate(ride);
|
||||
ride_ratings_calculate_value(ride);
|
||||
|
||||
window_invalidate_by_number(WC_RIDE, _rideRatingsCurrentRide);
|
||||
_rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE;
|
||||
|
@ -372,7 +372,7 @@ static void ride_ratings_calculate(rct_ride *ride)
|
|||
}
|
||||
}
|
||||
|
||||
static void ride_ratings_reliability_calculate(rct_ride *ride)
|
||||
static void ride_ratings_calculate_value(rct_ride *ride)
|
||||
{
|
||||
rct_ride *ride2;
|
||||
int i, otherRidesOfSameType;
|
||||
|
@ -380,7 +380,7 @@ static void ride_ratings_reliability_calculate(rct_ride *ride)
|
|||
if (ride->excitement == (ride_rating)0xFFFF)
|
||||
return;
|
||||
|
||||
int reliability =
|
||||
int value =
|
||||
(((ride->excitement * RCT2_GLOBAL(0x0097CD1E + (ride->type * 6), sint16)) * 32) >> 15) +
|
||||
(((ride->intensity * RCT2_GLOBAL(0x0097CD20 + (ride->type * 6), sint16)) * 32) >> 15) +
|
||||
(((ride->nausea * RCT2_GLOBAL(0x0097CD22 + (ride->type * 6), sint16)) * 32) >> 15);
|
||||
|
@ -389,19 +389,19 @@ static void ride_ratings_reliability_calculate(rct_ride *ride)
|
|||
|
||||
// New ride reward
|
||||
if (monthsOld <= 12) {
|
||||
reliability += 10;
|
||||
value += 10;
|
||||
if (monthsOld <= 4)
|
||||
reliability += 20;
|
||||
value += 20;
|
||||
}
|
||||
|
||||
// Old ride penalty
|
||||
if (monthsOld >= 40) reliability -= reliability / 4;
|
||||
if (monthsOld >= 64) reliability -= reliability / 4;
|
||||
if (monthsOld >= 40) value -= value / 4;
|
||||
if (monthsOld >= 64) value -= value / 4;
|
||||
if (monthsOld < 200) {
|
||||
if (monthsOld >= 88) reliability -= reliability / 4;
|
||||
if (monthsOld >= 104) reliability -= reliability / 4;
|
||||
if (monthsOld >= 120) reliability -= reliability / 2;
|
||||
if (monthsOld >= 128) reliability -= reliability / 2;
|
||||
if (monthsOld >= 88) value -= value / 4;
|
||||
if (monthsOld >= 104) value -= value / 4;
|
||||
if (monthsOld >= 120) value -= value / 2;
|
||||
if (monthsOld >= 128) value -= value / 2;
|
||||
}
|
||||
|
||||
// Other ride of same type penalty
|
||||
|
@ -411,9 +411,9 @@ static void ride_ratings_reliability_calculate(rct_ride *ride)
|
|||
otherRidesOfSameType++;
|
||||
}
|
||||
if (otherRidesOfSameType > 1)
|
||||
reliability -= reliability / 4;
|
||||
value -= value / 4;
|
||||
|
||||
ride->reliability = max(0, reliability);
|
||||
ride->value = max(0, value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -564,12 +564,16 @@ static void ride_ratings_apply_intensity_penalty(rating_tuple *ratings)
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00655FD6
|
||||
*/
|
||||
static void sub_655FD6(rct_ride *ride)
|
||||
static void set_unreliability_factor(rct_ride *ride)
|
||||
{
|
||||
ride->var_198 += (ride->lift_hill_speed - RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]) * 2;
|
||||
// The higher the number, the lower the breakdown
|
||||
// possibility. Range is [3, 7]. values are here:
|
||||
// https://gist.github.com/kevinburke/123977c4884ccadbec70. Consider
|
||||
// inlining this per ride
|
||||
uint8 lift_speed_adjustment = RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4];
|
||||
ride->unreliability_factor += (ride->lift_hill_speed - lift_speed_adjustment) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -752,13 +756,13 @@ static void ride_ratings_calculate_mine_train_coaster(rct_ride *ride)
|
|||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
return;
|
||||
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(2,90);
|
||||
ratings.intensity = RIDE_RATING(2,30);
|
||||
ratings.nausea = RIDE_RATING(2,10);
|
||||
ratings.excitement = RIDE_RATING(2,90);
|
||||
ratings.intensity = RIDE_RATING(2,30);
|
||||
ratings.nausea = RIDE_RATING(2,10);
|
||||
|
||||
// Apply length of ride factor
|
||||
totalLength = (ride->length[0] + ride->length[1] + ride->length[2] + ride->length[3]) >> 16;
|
||||
|
@ -856,7 +860,7 @@ static void ride_ratings_calculate_mine_train_coaster(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= sub_65E72D(ride) << 5;
|
||||
|
@ -868,8 +872,8 @@ static void ride_ratings_calculate_maze(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 8;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 8;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,30);
|
||||
|
@ -889,7 +893,7 @@ static void ride_ratings_calculate_maze(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -901,8 +905,8 @@ static void ride_ratings_calculate_spiral_slide(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 8;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 8;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,50);
|
||||
|
@ -924,7 +928,7 @@ static void ride_ratings_calculate_spiral_slide(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 2 << 5;
|
||||
|
@ -936,8 +940,8 @@ static void ride_ratings_calculate_pirate_ship(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 10;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 10;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,50);
|
||||
|
@ -956,7 +960,7 @@ static void ride_ratings_calculate_pirate_ship(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -968,8 +972,8 @@ static void ride_ratings_calculate_inverter_ship(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(2,50);
|
||||
|
@ -988,7 +992,7 @@ static void ride_ratings_calculate_inverter_ship(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -997,19 +1001,19 @@ static void ride_ratings_calculate_inverter_ship(rct_ride *ride)
|
|||
static void ride_ratings_calculate_food_stall(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_drink_stall(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_shop(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_merry_go_round(rct_ride *ride)
|
||||
|
@ -1018,8 +1022,8 @@ static void ride_ratings_calculate_merry_go_round(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
int unk = ride->var_0D0 * 5;
|
||||
ratings.excitement = unk + RIDE_RATING(0,60) + ((ride_ratings_get_scenery_score(ride) * 19521) >> 16);
|
||||
|
@ -1032,7 +1036,7 @@ static void ride_ratings_calculate_merry_go_round(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 7 << 5;
|
||||
|
@ -1041,13 +1045,13 @@ static void ride_ratings_calculate_merry_go_round(rct_ride *ride)
|
|||
static void ride_ratings_calculate_information_kiosk(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_bathroom(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_ferris_wheel(rct_ride *ride)
|
||||
|
@ -1056,8 +1060,8 @@ static void ride_ratings_calculate_ferris_wheel(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
int unk = ride->var_0D0 * 25;
|
||||
ratings.excitement = unk + RIDE_RATING(0,60) + ((ride_ratings_get_scenery_score(ride) * 41831) >> 16);
|
||||
|
@ -1070,7 +1074,7 @@ static void ride_ratings_calculate_ferris_wheel(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -1082,8 +1086,8 @@ static void ride_ratings_calculate_motion_simulator(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 21;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 21;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
if (ride->mode == RIDE_MODE_FILM_THRILL_RIDERS) {
|
||||
|
@ -1102,7 +1106,7 @@ static void ride_ratings_calculate_motion_simulator(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 7 << 5;
|
||||
|
@ -1114,8 +1118,8 @@ static void ride_ratings_calculate_3d_cinema(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 21;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 21;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
switch (ride->mode) {
|
||||
|
@ -1143,7 +1147,7 @@ static void ride_ratings_calculate_3d_cinema(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 7 << 5;
|
||||
|
@ -1155,8 +1159,8 @@ static void ride_ratings_calculate_top_spin(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 19;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 19;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
switch (ride->mode) {
|
||||
|
@ -1186,7 +1190,7 @@ static void ride_ratings_calculate_top_spin(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -1198,8 +1202,8 @@ static void ride_ratings_calculate_space_rings(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 7;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 7;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,50);
|
||||
|
@ -1214,7 +1218,7 @@ static void ride_ratings_calculate_space_rings(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -1228,8 +1232,8 @@ static void ride_ratings_calculate_elevator(rct_ride *ride)
|
|||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
return;
|
||||
|
||||
ride->var_198 = 15;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 15;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,11);
|
||||
|
@ -1249,7 +1253,7 @@ static void ride_ratings_calculate_elevator(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 7 << 5;
|
||||
|
@ -1261,7 +1265,7 @@ static void ride_ratings_calculate_elevator(rct_ride *ride)
|
|||
static void ride_ratings_calculate_atm(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_twist(rct_ride *ride)
|
||||
|
@ -1270,8 +1274,8 @@ static void ride_ratings_calculate_twist(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,13);
|
||||
|
@ -1290,7 +1294,7 @@ static void ride_ratings_calculate_twist(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -1302,8 +1306,8 @@ static void ride_ratings_calculate_haunted_house(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 8;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 8;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
ratings.excitement = RIDE_RATING(3,41);
|
||||
ratings.intensity = RIDE_RATING(1,53);
|
||||
|
@ -1315,7 +1319,7 @@ static void ride_ratings_calculate_haunted_house(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0xE0;
|
||||
|
@ -1330,8 +1334,8 @@ static void ride_ratings_calculate_mini_golf(rct_ride *ride)
|
|||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED))
|
||||
return;
|
||||
|
||||
ride->var_198 = 0;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 0;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(1,50);
|
||||
|
@ -1373,7 +1377,7 @@ static void ride_ratings_calculate_mini_golf(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= sub_65E72D(ride) << 5;
|
||||
|
@ -1382,7 +1386,7 @@ static void ride_ratings_calculate_mini_golf(rct_ride *ride)
|
|||
static void ride_ratings_calculate_first_aid(rct_ride *ride)
|
||||
{
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
}
|
||||
|
||||
static void ride_ratings_calculate_circus_show(rct_ride *ride)
|
||||
|
@ -1391,8 +1395,8 @@ static void ride_ratings_calculate_circus_show(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 9;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 9;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
ratings.excitement = RIDE_RATING(2,10);
|
||||
ratings.intensity = RIDE_RATING(0,30);
|
||||
|
@ -1404,7 +1408,7 @@ static void ride_ratings_calculate_circus_show(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 7 << 5;
|
||||
|
@ -1416,8 +1420,8 @@ static void ride_ratings_calculate_crooked_house(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 5;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 5;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
ratings.excitement = RIDE_RATING(2,15);
|
||||
ratings.intensity = RIDE_RATING(0,62);
|
||||
|
@ -1429,7 +1433,7 @@ static void ride_ratings_calculate_crooked_house(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0xE0;
|
||||
|
@ -1441,8 +1445,8 @@ static void ride_ratings_calculate_magic_carpet(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 16;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 16;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(2,45);
|
||||
|
@ -1461,7 +1465,7 @@ static void ride_ratings_calculate_magic_carpet(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 0 << 5;
|
||||
|
@ -1473,8 +1477,8 @@ static void ride_ratings_calculate_enterprise(rct_ride *ride)
|
|||
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED;
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS;
|
||||
ride->var_198 = 22;
|
||||
sub_655FD6(ride);
|
||||
ride->unreliability_factor = 22;
|
||||
set_unreliability_factor(ride);
|
||||
|
||||
// Base ratings
|
||||
ratings.excitement = RIDE_RATING(3,60);
|
||||
|
@ -1493,7 +1497,7 @@ static void ride_ratings_calculate_enterprise(rct_ride *ride)
|
|||
ride->ratings = ratings;
|
||||
|
||||
ride->upkeep_cost = ride_compute_upkeep(ride);
|
||||
ride->var_14D |= 2;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME;
|
||||
|
||||
ride->inversions &= 0x1F;
|
||||
ride->inversions |= 3 << 5;
|
||||
|
|
|
@ -128,7 +128,7 @@ static void ride_update_station_bumpercar(rct_ride *ride, int stationIndex)
|
|||
// Begin the match
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
|
||||
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
|
||||
ride->var_14D |= 12;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ static void ride_update_station_race(rct_ride *ride, int stationIndex)
|
|||
if (vehicle->num_peeps != 0) {
|
||||
peep = &(g_sprite_list[vehicle->peep[0]].peep);
|
||||
ride->race_winner = peep->sprite_index;
|
||||
ride->var_14D |= 12;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
}
|
||||
|
||||
// Race is over
|
||||
|
@ -214,7 +214,7 @@ static void ride_update_station_race(rct_ride *ride, int stationIndex)
|
|||
ride_race_init_vehicle_speeds(ride);
|
||||
ride->lifecycle_flags |= RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
|
||||
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
|
||||
ride->var_14D |= 12;
|
||||
ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -234,9 +234,9 @@ static void ride_race_init_vehicle_speeds(rct_ride *ride)
|
|||
vehicle = &g_sprite_list[ride->vehicles[i]].vehicle;
|
||||
vehicle->var_48 &= ~(1 << 6);
|
||||
|
||||
rideEntry = GET_RIDE_ENTRY(vehicle->var_D6);
|
||||
rideEntry = GET_RIDE_ENTRY(vehicle->ride_subtype);
|
||||
|
||||
vehicle->speed = (scenario_rand() & 16) - 8 + rideEntry->vehicles[vehicle->var_31].var_5C;
|
||||
vehicle->speed = (scenario_rand() & 16) - 8 + rideEntry->vehicles[vehicle->vehicle_type].var_5C;
|
||||
|
||||
if (vehicle->num_peeps != 0) {
|
||||
rct_peep *peep = &g_sprite_list[vehicle->peep[0]].peep;
|
||||
|
@ -315,4 +315,4 @@ rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int
|
|||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -735,7 +735,7 @@ void load_track_scenery_objects(){
|
|||
object_load(-1, &scenery_entry->scenery_object, 0);
|
||||
}
|
||||
// Skip object and location/direction/colour
|
||||
scenery_entry += sizeof(rct_track_scenery);
|
||||
track_elements += sizeof(rct_track_scenery);
|
||||
}
|
||||
|
||||
reset_loaded_objects();
|
||||
|
@ -1227,7 +1227,7 @@ int copy_scenery_to_track(uint8** track_pointer){
|
|||
{
|
||||
int temp_y = y;
|
||||
y = x;
|
||||
x = -y;
|
||||
x = -temp_y;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
@ -1238,7 +1238,7 @@ int copy_scenery_to_track(uint8** track_pointer){
|
|||
{
|
||||
int temp_x = x;
|
||||
x = y;
|
||||
y = -x;
|
||||
y = -temp_x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
190
src/ride/track.h
190
src/ride/track.h
|
@ -216,6 +216,196 @@ enum {
|
|||
TRACK_CORKSCREW_DOWN = 224
|
||||
};
|
||||
|
||||
enum {
|
||||
TRACK_ELEM_FLAT,
|
||||
TRACK_ELEM_END_STATION,
|
||||
TRACK_ELEM_BEGIN_STATION,
|
||||
TRACK_ELEM_MIDDLE_STATION,
|
||||
TRACK_ELEM_25_DEG_UP,
|
||||
TRACK_ELEM_60_DEG_UP,
|
||||
TRACK_ELEM_FLAT_TO_25_DEG_UP,
|
||||
TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP,
|
||||
TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP,
|
||||
TRACK_ELEM_25_DEG_UP_TO_FLAT,
|
||||
TRACK_ELEM_25_DEG_DOWN,
|
||||
TRACK_ELEM_60_DEG_DOWN,
|
||||
TRACK_ELEM_FLAT_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN,
|
||||
TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_FLAT,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES,
|
||||
TRACK_ELEM_FLAT_TO_LEFT_BANK,
|
||||
TRACK_ELEM_FLAT_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_LEFT_BANK_TO_FLAT,
|
||||
TRACK_ELEM_RIGHT_BANK_TO_FLAT,
|
||||
TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES,
|
||||
TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES,
|
||||
TRACK_ELEM_LEFT_BANK_TO_25_DEG_UP,
|
||||
TRACK_ELEM_RIGHT_BANK_TO_25_DEG_UP,
|
||||
TRACK_ELEM_25_DEG_UP_TO_LEFT_BANK,
|
||||
TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_LEFT_BANK_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_RIGHT_BANK_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANK,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_LEFT_BANK,
|
||||
TRACK_ELEM_RIGHT_BANK,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN,
|
||||
TRACK_ELEM_S_BEND_LEFT,
|
||||
TRACK_ELEM_S_BEND_RIGHT,
|
||||
TRACK_ELEM_LEFT_VERTICAL_LOOP,
|
||||
TRACK_ELEM_RIGHT_VERTICAL_LOOP,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE,
|
||||
TRACK_ELEM_LEFT_TWIST_DOWN_TO_UP,
|
||||
TRACK_ELEM_RIGHT_TWIST_DOWN_TO_UP,
|
||||
TRACK_ELEM_LEFT_TWIST_UP_TO_DOWN,
|
||||
TRACK_ELEM_RIGHT_TWIST_UP_TO_DOWN,
|
||||
TRACK_ELEM_HALF_LOOP_UP,
|
||||
TRACK_ELEM_HALF_LOOP_DOWN,
|
||||
TRACK_ELEM_LEFT_CORKSCREW_UP,
|
||||
TRACK_ELEM_RIGHT_CORKSCREW_UP,
|
||||
TRACK_ELEM_LEFT_CORKSCREW_DOWN,
|
||||
TRACK_ELEM_RIGHT_CORKSCREW_DOWN,
|
||||
TRACK_ELEM_FLAT_TO_60_DEG_UP,
|
||||
TRACK_ELEM_60_DEG_UP_TO_FLAT,
|
||||
TRACK_ELEM_FLAT_TO_60_DEG_DOWN,
|
||||
TRACK_ELEM_60_DEG_DOWN_TO_FLAT,
|
||||
TRACK_ELEM_TOWER_BASE,
|
||||
TRACK_ELEM_TOWER_SECTION,
|
||||
TRACK_ELEM_FLAT_COVERED,
|
||||
TRACK_ELEM_25_DEG_UP_COVERED,
|
||||
TRACK_ELEM_60_DEG_UP_COVERED,
|
||||
TRACK_ELEM_FLAT_TO_25_DEG_UP_COVERED,
|
||||
TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED,
|
||||
TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED,
|
||||
TRACK_ELEM_25_DEG_UP_TO_FLAT_COVERED,
|
||||
TRACK_ELEM_25_DEG_DOWN_COVERED,
|
||||
TRACK_ELEM_60_DEG_DOWN_COVERED,
|
||||
TRACK_ELEM_FLAT_TO_25_DEG_DOWN_COVERED,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED,
|
||||
TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED,
|
||||
TRACK_ELEM_25_DEG_DOWN_TO_FLAT_COVERED,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED,
|
||||
TRACK_ELEM_S_BEND_LEFT_COVERED,
|
||||
TRACK_ELEM_S_BEND_RIGHT_COVERED,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED,
|
||||
TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL,
|
||||
TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL,
|
||||
TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL,
|
||||
TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL,
|
||||
TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE,
|
||||
TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE,
|
||||
TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE,
|
||||
TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_LARGE,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN,
|
||||
TRACK_ELEM_BRAKES,
|
||||
TRACK_ELEM_ROTATION_CONTROL_TOGGLE,
|
||||
TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP,
|
||||
TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP,
|
||||
TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_DOWN,
|
||||
TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_DOWN,
|
||||
TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_UP,
|
||||
TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN,
|
||||
TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN,
|
||||
TRACK_ELEM_25_DEG_UP_LEFT_BANKED,
|
||||
TRACK_ELEM_25_DEG_UP_RIGHT_BANKED,
|
||||
TRACK_ELEM_WATERFALL,
|
||||
TRACK_ELEM_RAPIDS,
|
||||
TRACK_ELEM_ON_RIDE_PHOTO,
|
||||
TRACK_ELEM_25_DEG_DOWN_LEFT_BANKED,
|
||||
TRACK_ELEM_25_DEG_DOWN_RIGHT_BANKED,
|
||||
TRACK_ELEM_WATER_SPLASH,
|
||||
TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE,
|
||||
TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE,
|
||||
TRACK_ELEM_WHIRLPOOL,
|
||||
TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE,
|
||||
TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122,
|
||||
TRACK_ELEM_CABLE_LIFT_HILL,
|
||||
TRACK_ELEM_REVERSE_WHOA_BELLY_SLOPE,
|
||||
TRACK_ELEM_REVERSE_WHOA_BELLY_VERTICAL,
|
||||
TRACK_ELEM_90_DEG_UP,
|
||||
TRACK_ELEM_90_DEG_DOWN,
|
||||
TRACK_ELEM_60_DEG_UP_TO_90_DEG_UP,
|
||||
TRACK_ELEM_90_DEG_DOWN_TO_60_DEG_DOWN,
|
||||
TRACK_ELEM_90_DEG_UP_TO_60_DEG_UP,
|
||||
TRACK_ELEM_60_DEG_DOWN_TO_90_DEG_DOWN,
|
||||
TRACK_ELEM_BRAKE_FOR_DROP,
|
||||
TRACK_ELEM_LEFT_EIGHTH_TO_DIAG,
|
||||
TRACK_ELEM_RIGHT_EIGHTH_TO_DIAG,
|
||||
TRACK_ELEM_LEFT_EIGHTH_TO_ORTHOGONAL,
|
||||
TRACK_ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL,
|
||||
TRACK_ELEM_LEFT_EIGHTH_BANK_TO_DIAG,
|
||||
TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_DIAG,
|
||||
TRACK_ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL,
|
||||
TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL,
|
||||
TRACK_ELEM_DIAG_FLAT,
|
||||
TRACK_ELEM_DIAG_25_DEG_UP,
|
||||
TRACK_ELEM_DIAG_60_DEG_UP,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_25_DEG_UP,
|
||||
TRACK_ELEM_DIAG_25_DEG_UP_TO_60_DEG_UP,
|
||||
TRACK_ELEM_DIAG_60_DEG_UP_TO_25_DEG_UP,
|
||||
TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_25_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_60_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_25_DEG_DOWN_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP,
|
||||
TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_LEFT_BANK,
|
||||
TRACK_ELEM_DIAG_FLAT_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_DIAG_LEFT_BANK_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_RIGHT_BANK_TO_FLAT,
|
||||
TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP,
|
||||
TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP,
|
||||
TRACK_ELEM_DIAG_25_DEG_UP_TO_LEFT_BANK,
|
||||
TRACK_ELEM_DIAG_25_DEG_UP_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN,
|
||||
TRACK_ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK,
|
||||
TRACK_ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_DIAG_LEFT_BANK,
|
||||
TRACK_ELEM_DIAG_RIGHT_BANK,
|
||||
TRACK_ELEM_LOG_FLUME_REVERSER,
|
||||
TRACK_ELEM_SPINNING_TUNNEL,
|
||||
TRACK_ELEM_LEFT_BARREL_ROLL_UP_TO_DOWN,
|
||||
TRACK_ELEM_RIGHT_BARREL_ROLL_UP_TO_DOWN,
|
||||
TRACK_ELEM_LEFT_BARREL_ROLL_DOWN_TO_UP,
|
||||
TRACK_ELEM_RIGHT_BARREL_ROLL_DOWN_TO_UP,
|
||||
TRACK_ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP,
|
||||
TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK,
|
||||
TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK,
|
||||
TRACK_ELEM_POWERED_LIFT,
|
||||
TRACK_ELEM_LEFT_LARGE_HALF_LOOP_UP,
|
||||
TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_UP,
|
||||
TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_DOWN,
|
||||
TRACK_ELEM_LEFT_LARGE_HALF_LOOP_DOWN
|
||||
};
|
||||
|
||||
extern const rct_trackdefinition *gTrackDefinitions;
|
||||
|
||||
void track_load_list(ride_list_item item);
|
||||
|
|
|
@ -99,9 +99,8 @@ void vehicle_update_sound_params(rct_vehicle* vehicle)
|
|||
|
||||
sint32 v19 = vehicle->velocity;
|
||||
|
||||
int testaddr = (vehicle->var_31 * 0x65);
|
||||
testaddr += (int)RCT2_ADDRESS(0x009ACFA4, rct_ride_type*)[vehicle->var_D6];
|
||||
uint8 test = ((uint8*)testaddr)[0x74];
|
||||
rct_ride_type* ride_type = GET_RIDE_ENTRY(vehicle->ride_subtype);
|
||||
uint8 test = ride_type->vehicles[vehicle->vehicle_type].var_5A;
|
||||
|
||||
if (test & 1) {
|
||||
v19 *= 2;
|
||||
|
@ -633,4 +632,9 @@ rct_vehicle *vehicle_get_head(rct_vehicle *vehicle)
|
|||
}
|
||||
|
||||
return vehicle;
|
||||
}
|
||||
|
||||
int vehicle_is_used_in_pairs(rct_vehicle *vehicle)
|
||||
{
|
||||
return vehicle->num_seats & VEHICLE_SEAT_PAIR_FLAG;
|
||||
}
|
|
@ -26,31 +26,41 @@
|
|||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 var_01;
|
||||
uint8 pad_02[0x02];
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 pad_09;
|
||||
// Height from center of sprite to bottom
|
||||
uint8 sprite_height_negative; // 0x09
|
||||
uint16 sprite_index; // 0x0A
|
||||
uint8 pad_0C[2];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 pad_14[0x02];
|
||||
// Width from center of sprite to edge
|
||||
uint8 sprite_width; // 0x14
|
||||
// Height from center of sprite to top
|
||||
uint8 sprite_height_positive; // 0x15
|
||||
sint16 sprite_left; // 0x16
|
||||
sint16 sprite_top; // 0x18
|
||||
sint16 sprite_right; // 0x1A
|
||||
sint16 sprite_bottom; // 0x1C
|
||||
uint8 sprite_direction; // 0x1E
|
||||
uint8 pad_1F[0x09];
|
||||
uint8 var_1F;
|
||||
uint8 pad_20[0x08];
|
||||
sint32 velocity; // 0x28
|
||||
uint8 pad_2C[0x04];
|
||||
uint8 ride; // 0x30
|
||||
uint8 var_31;
|
||||
uint8 vehicle_type; // 0x31
|
||||
uint8 pad_32[0x02];
|
||||
uint16 var_34;
|
||||
sint16 var_36;
|
||||
uint8 pad_38[0x06];
|
||||
//x related
|
||||
uint16 var_38;
|
||||
// y related
|
||||
uint16 var_3A;
|
||||
// z related
|
||||
uint16 var_3C;
|
||||
uint16 next_vehicle_on_train; // 0x3E
|
||||
uint16 prev_vehicle_on_train; // 0x40
|
||||
uint16 pad_42;
|
||||
|
@ -58,14 +68,16 @@ typedef struct {
|
|||
uint16 var_46;
|
||||
uint16 var_48;
|
||||
uint8 pad_4A;
|
||||
uint8 var_4B;
|
||||
uint8 current_station; // 0x4B
|
||||
uint8 pad_4C[0x4];
|
||||
uint8 status; // 0x50
|
||||
uint8 var_51;
|
||||
uint16 peep[32]; // 0x52
|
||||
uint8 pad_92[0x21];
|
||||
uint8 peep_tshirt_colours[32]; // 0x92
|
||||
uint8 num_seats; // 0xB2
|
||||
uint8 num_peeps; // 0xB3
|
||||
uint8 pad_B4[0x07];
|
||||
uint8 next_free_seat; // 0xB4
|
||||
uint8 pad_B5[0x06];
|
||||
uint8 sound1_id; // 0xBB
|
||||
uint8 sound1_volume; // 0xBC
|
||||
uint8 sound2_id; // 0xBD
|
||||
|
@ -78,10 +90,11 @@ typedef struct {
|
|||
uint8 var_CD;
|
||||
union {
|
||||
uint8 var_CE;
|
||||
uint8 num_laps; // 0xCE
|
||||
uint8 num_laps; // 0xCE
|
||||
};
|
||||
uint8 pad_CF[0x07];
|
||||
uint8 var_D6;
|
||||
uint8 pad_CF[0x06];
|
||||
uint8 var_D5;
|
||||
uint8 ride_subtype; // 0xD6
|
||||
} rct_vehicle;
|
||||
|
||||
enum {
|
||||
|
@ -118,13 +131,16 @@ enum {
|
|||
VEHICLE_STATUS_STOPPED_BY_BLOCK_BRAKES
|
||||
};
|
||||
|
||||
#define VEHICLE_SEAT_PAIR_FLAG 0x80
|
||||
#define VEHICLE_SEAT_NUM_MASK 0x7F
|
||||
|
||||
void vehicle_update_all();
|
||||
int sub_6BC2F3(rct_vehicle* vehicle);
|
||||
void sub_6BB9FF(rct_vehicle* vehicle);
|
||||
void vehicle_sounds_update();
|
||||
void vehicle_get_g_forces(rct_vehicle *vehicle, int *verticalG, int *lateralG);
|
||||
void vehicle_set_map_toolbar(rct_vehicle *vehicle);
|
||||
|
||||
int vehicle_is_used_in_pairs(rct_vehicle *vehicle);
|
||||
rct_vehicle *vehicle_get_head(rct_vehicle *vehicle);
|
||||
|
||||
/** Helper macro until rides are stored in this module. */
|
||||
|
|
|
@ -281,9 +281,9 @@ typedef struct {
|
|||
uint16 saved_view_x;
|
||||
uint16 saved_view_y;
|
||||
uint16 saved_view_zoom_and_rotation;
|
||||
uint8 byte_013886A0[6000];
|
||||
uint8 map_animations[6000];
|
||||
uint8 byte_01389E10[6000];
|
||||
uint16 word_0138B580;
|
||||
uint16 num_map_animations;
|
||||
uint8 pad_0138B580[2];
|
||||
uint16 word_0138B584;
|
||||
uint16 word_0138B586;
|
||||
|
|
|
@ -266,7 +266,6 @@ static void DrawOpenRCT2(int x, int y)
|
|||
void game_handle_input();
|
||||
void title_update()
|
||||
{
|
||||
|
||||
screenshot_check();
|
||||
title_handle_keyboard_input();
|
||||
|
||||
|
|
|
@ -355,7 +355,12 @@ static void cheat_renew_rides()
|
|||
rct_ride *ride;
|
||||
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
{
|
||||
// Set build date to current date (so the ride is brand new)
|
||||
ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
// Set reliability to 100
|
||||
ride->reliability = (100 << 8);
|
||||
}
|
||||
window_invalidate_by_class(WC_RIDE);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ static void window_footpath_close()
|
|||
|
||||
window_get_register(w);
|
||||
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
viewport_set_visibility(0);
|
||||
map_invalidate_map_selection_tiles();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
|
||||
|
@ -258,7 +258,7 @@ static void window_footpath_mouseup()
|
|||
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
tool_cancel();
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
map_invalidate_map_selection_tiles();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND;
|
||||
|
@ -273,7 +273,7 @@ static void window_footpath_mouseup()
|
|||
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
tool_cancel();
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
map_invalidate_map_selection_tiles();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL;
|
||||
|
@ -369,7 +369,7 @@ static void window_footpath_dropdown()
|
|||
|
||||
// Set selected path id
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = pathId;
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
window_invalidate(w);
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ static void window_footpath_tooldrag()
|
|||
window_tool_get_registers(w, widgetIndex, x, y);
|
||||
|
||||
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
|
||||
RCT2_CALLPROC_X(0x006A82C5, x, y, 0, 0, (int)w, 0, 0);
|
||||
window_footpath_place_path_at_point(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -441,7 +441,8 @@ static void window_footpath_toolup()
|
|||
window_tool_get_registers(w, widgetIndex, x, y);
|
||||
|
||||
if (widgetIndex == WIDX_CONSTRUCT_ON_LAND) {
|
||||
RCT2_CALLPROC_X(0x006A8380, x, y, 0, 0, (int)w, 0, 0);
|
||||
// The function at 0x006A8380 in rct2 is just the following:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,7 +642,7 @@ static void window_footpath_show_footpath_types_dialog(rct_window *w, rct_widget
|
|||
*/
|
||||
static void window_footpath_mousedown_direction(int direction)
|
||||
{
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8) = (direction - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) & 3;
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
window_footpath_set_enabled_and_pressed_widgets();
|
||||
|
@ -653,7 +654,7 @@ static void window_footpath_mousedown_direction(int direction)
|
|||
*/
|
||||
static void window_footpath_mousedown_slope(int slope)
|
||||
{
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) = slope;
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
window_footpath_set_enabled_and_pressed_widgets();
|
||||
|
@ -675,7 +676,7 @@ static void window_footpath_set_provisional_path_at_point(int x, int y)
|
|||
|
||||
if (z == 0) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0);
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
} else {
|
||||
// Check for change
|
||||
if ((RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & (1 << 1)) && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_X, uint16) == x && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Y, uint16) == y && RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_Z, uint8) == mapElement->base_height)
|
||||
|
@ -689,7 +690,7 @@ static void window_footpath_set_provisional_path_at_point(int x, int y)
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, uint16) = x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, uint16) = y;
|
||||
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
|
||||
// Set provisional path
|
||||
slope = RCT2_ADDRESS(0x0098D8B4, uint8)[mapElement->properties.surface.slope & 0x1F];
|
||||
|
@ -714,7 +715,7 @@ static void window_footpath_place_path_at_point(int x, int y)
|
|||
if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) != 0)
|
||||
return;
|
||||
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
|
||||
get_map_coordinates_from_pos(x, y, 0xFFDE, &x, &y, &z, &mapElement);
|
||||
if (z == 0)
|
||||
|
@ -755,14 +756,17 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY)
|
|||
return;
|
||||
|
||||
if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) {
|
||||
// ?
|
||||
uint8 dl = ((mapElement->properties.surface.slope & 0x0F) << direction) & 0xFF;
|
||||
uint8 dh = dl;
|
||||
dl = (dl >> 4) & 0x0F;
|
||||
dh = (dh & 0x0F) | dl;
|
||||
// If we start the path on a slope, the arrow is slightly raised, so we
|
||||
// expect the path to be slightly raised as well.
|
||||
uint8_t slope = mapElement->properties.surface.slope;
|
||||
z = mapElement->base_height;
|
||||
if ((dh & 0x0C) == 0x0C)
|
||||
if (slope & 0x10) {
|
||||
// Steep diagonal slope
|
||||
z += 4;
|
||||
} else if (slope & 0x0f) {
|
||||
// Normal slope
|
||||
z += 2;
|
||||
}
|
||||
} else {
|
||||
z = mapElement->base_height;
|
||||
if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) {
|
||||
|
@ -787,12 +791,66 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY)
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Construct a piece of footpath while in bridge building mode.
|
||||
* rct2: 0x006A79B7
|
||||
*/
|
||||
static void window_footpath_construct()
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A79B7);
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
footpath_provisional_update();
|
||||
|
||||
int type, x, y, z, slope;
|
||||
footpath_get_next_path_info(&type, &x, &y, &z, &slope);
|
||||
|
||||
// Try to place the path at the desired location
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 0x498;
|
||||
money32 cost = footpath_place(type, x, y, z, slope, 0);
|
||||
|
||||
if (cost != MONEY32_UNDEFINED) {
|
||||
// It is possible, let's remove walls between the old and new piece of path
|
||||
uint8 direction = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8);
|
||||
map_remove_intersecting_walls(x, y, z, z + 4 + (slope & 0xf ? 2 : 0), direction ^ 2);
|
||||
map_remove_intersecting_walls(
|
||||
x - TileDirectionDelta[direction].x,
|
||||
y - TileDirectionDelta[direction].y,
|
||||
z, z + 4, direction
|
||||
);
|
||||
}
|
||||
|
||||
// Actually place the path now
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 0x498;
|
||||
cost = footpath_place(type, x, y, z, slope, GAME_COMMAND_FLAG_APPLY);
|
||||
|
||||
if (cost != MONEY32_UNDEFINED) {
|
||||
sound_play_panned(
|
||||
SOUND_PLACE_ITEM,
|
||||
0x8001,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16)
|
||||
);
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) == 0) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS, uint8) = 0xff;
|
||||
} else {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_VALID_DIRECTIONS, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_DIRECTION, uint8);
|
||||
}
|
||||
|
||||
if (RCT2_GLOBAL(0x00F3EFA4, uint8) & 2)
|
||||
viewport_set_visibility(1);
|
||||
|
||||
// If we have just built an upwards slope, the next path to construct is
|
||||
// a bit higher. Note that the z returned by footpath_get_next_path_info
|
||||
// already is lowered if we are building a downwards slope.
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_SLOPE, uint8) == 2)
|
||||
z += 2;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_X, uint16) = x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Y, uint16) = y;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCT_PATH_FROM_Z, uint16) = z << 3;
|
||||
}
|
||||
|
||||
window_footpath_set_enabled_and_pressed_widgets();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -894,7 +952,7 @@ static void window_footpath_remove()
|
|||
rct_map_element *mapElement;
|
||||
|
||||
_window_footpath_cost = MONEY32_UNDEFINED;
|
||||
sub_6A7831();
|
||||
footpath_provisional_update();
|
||||
|
||||
mapElement = footpath_get_map_element_to_remove();
|
||||
if (mapElement != NULL)
|
||||
|
|
|
@ -1235,8 +1235,8 @@ void window_guest_overview_tool_down(){
|
|||
peep_window_state_update(peep);
|
||||
peep->action = 0xFF;
|
||||
peep->var_6D = 0;
|
||||
peep->var_70 = 0;
|
||||
peep->var_6E = 0xFF;
|
||||
peep->action_sprite_image_offset = 0;
|
||||
peep->action_sprite_type = 0xFF;
|
||||
peep->var_C4 = 0;
|
||||
|
||||
peep->happiness_growth_rate -= 10;
|
||||
|
@ -1268,8 +1268,8 @@ void window_guest_overview_tool_abort(){
|
|||
peep_window_state_update(peep);
|
||||
peep->action = 0xFF;
|
||||
peep->var_6D = 0;
|
||||
peep->var_70 = 0;
|
||||
peep->var_6E = 0;
|
||||
peep->action_sprite_image_offset = 0;
|
||||
peep->action_sprite_type = 0;
|
||||
peep->var_C4 = 0;
|
||||
}
|
||||
|
||||
|
@ -2152,7 +2152,7 @@ void window_guest_inventory_paint(){
|
|||
no_items++;
|
||||
|
||||
RCT2_GLOBAL(0x13CE952, uint32) = 5089 + i;
|
||||
RCT2_GLOBAL(0x13CE956, uint16) = 2188;
|
||||
RCT2_GLOBAL(0x13CE956, uint16) = 2188 + i;
|
||||
RCT2_GLOBAL(0x13CE958, uint16) = RCT2_GLOBAL(0x13573D4, uint16);
|
||||
RCT2_GLOBAL(0x13CE95A, uint32) = RCT2_GLOBAL(0x13573D8, uint32);
|
||||
|
||||
|
|
|
@ -100,13 +100,13 @@ static void* window_new_campaign_events[] = {
|
|||
uint8 window_new_campaign_rides[MAX_RIDES];
|
||||
uint8 window_new_campaign_shop_items[64];
|
||||
|
||||
int ride_reliability_compare(const void *a, const void *b)
|
||||
int ride_value_compare(const void *a, const void *b)
|
||||
{
|
||||
rct_ride *rideA, *rideB;
|
||||
|
||||
rideA = GET_RIDE(*((uint8*)a));
|
||||
rideB = GET_RIDE(*((uint8*)b));
|
||||
return rideB->reliability - rideA->reliability;
|
||||
return rideB->value - rideA->value;
|
||||
}
|
||||
|
||||
int ride_name_compare(const void *a, const void *b)
|
||||
|
@ -179,7 +179,7 @@ void window_new_campaign_open(sint16 campaignType)
|
|||
|
||||
// Take top 40 most reliable rides
|
||||
if (numApplicableRides > 40) {
|
||||
qsort(window_new_campaign_rides, countof(window_new_campaign_rides), sizeof(uint8), ride_reliability_compare);
|
||||
qsort(window_new_campaign_rides, countof(window_new_campaign_rides), sizeof(uint8), ride_value_compare);
|
||||
numApplicableRides = 40;
|
||||
}
|
||||
|
||||
|
@ -413,4 +413,4 @@ static void window_new_campaign_paint()
|
|||
// Total price
|
||||
money32 totalPrice = AdvertisingCampaignPricePerWeek[w->campaign.campaign_type] * w->campaign.no_weeks;
|
||||
gfx_draw_string_left(dpi, STR_MARKETING_TOTAL_COST, &totalPrice, 0, x, y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -446,7 +446,7 @@ void window_new_ride_focus(ride_list_item rideItem)
|
|||
|
||||
ride_list_item *listItem = (ride_list_item*)0x00F43523;
|
||||
while (listItem->type != RIDE_TYPE_NULL) {
|
||||
if (listItem->type == rideItem.type && listItem->entry_index == rideItem.type) {
|
||||
if (listItem->type == rideItem.type && listItem->entry_index == rideItem.entry_index) {
|
||||
RCT2_GLOBAL(0x00F43825, uint8) = rideItem.type;
|
||||
RCT2_GLOBAL(0x00F43826, uint8) = rideItem.entry_index;
|
||||
w->new_ride.highlighted_ride_id = (rideItem.entry_index << 8) | rideItem.type;
|
||||
|
|
|
@ -345,14 +345,17 @@ static void window_options_mouseup()
|
|||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_SOUND_CHECKBOX:
|
||||
if (g_sounds_disabled)
|
||||
unpause_sounds();
|
||||
else
|
||||
pause_sounds();
|
||||
toggle_all_sounds();
|
||||
config_save_default();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_MUSIC_CHECKBOX:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) ^= 1;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) == 0)
|
||||
stop_ride_music();
|
||||
|
||||
gConfigSound.ride_music ^= 1;
|
||||
config_save_default();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
}
|
||||
|
@ -730,7 +733,7 @@ static void window_options_invalidate()
|
|||
// sound quality: low/medium/high
|
||||
RCT2_GLOBAL(0x013CE952 + 10, uint16) = STR_SOUND_LOW + gConfigSound.sound_quality;
|
||||
|
||||
widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, !g_sounds_disabled);
|
||||
widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, gConfigSound.sound);
|
||||
widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8));
|
||||
|
||||
window_options_widgets[WIDX_SOUND].type = WWT_DROPDOWN;
|
||||
|
|
|
@ -1568,7 +1568,7 @@ static void window_park_stats_paint()
|
|||
y += 10;
|
||||
|
||||
// Draw number of rides / attractions
|
||||
if (w->list_information_type != -1) {
|
||||
if (w->list_information_type != (uint16)-1) {
|
||||
RCT2_GLOBAL(0x013CE952, uint32) = w->list_information_type;
|
||||
gfx_draw_string_left(dpi, STR_NUMBER_OF_RIDES_LABEL, (void*)0x013CE952, 0, x, y);
|
||||
}
|
||||
|
@ -1941,8 +1941,9 @@ static void window_park_set_page(rct_window *w, int page)
|
|||
window_park_set_disabled_tabs(w);
|
||||
window_invalidate(w);
|
||||
|
||||
RCT2_CALLPROC_X(w->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)w, 0, 0);
|
||||
RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
|
||||
window_event_resize_call(w);
|
||||
window_event_invalidate_call(w);
|
||||
window_event_update_call(w);
|
||||
if (listen != 0 && w->viewport != NULL)
|
||||
w->viewport->flags |= VIEWPORT_FLAG_SOUND_ON;
|
||||
}
|
||||
|
|
|
@ -1901,7 +1901,7 @@ static void window_ride_main_update(rct_window *w)
|
|||
|
||||
// Update status
|
||||
ride = GET_RIDE(w->number);
|
||||
if (!(ride->var_14D & 4)) {
|
||||
if (!(ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAIN)) {
|
||||
if (w->ride.view == 0)
|
||||
return;
|
||||
|
||||
|
@ -1923,7 +1923,7 @@ static void window_ride_main_update(rct_window *w)
|
|||
}
|
||||
}
|
||||
|
||||
ride->var_14D &= ~4;
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MAIN;
|
||||
widget_invalidate(w, WIDX_STATUS);
|
||||
}
|
||||
|
||||
|
@ -2070,7 +2070,7 @@ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *argumen
|
|||
stringId += 23;
|
||||
|
||||
RCT2_GLOBAL((int)arguments + 4, uint16) = RideNameConvention[ride->type].station_name;
|
||||
RCT2_GLOBAL((int)arguments + 6, uint16) = vehicle->var_4B + 1;
|
||||
RCT2_GLOBAL((int)arguments + 6, uint16) = vehicle->current_station + 1;
|
||||
if (ride->num_stations > 1)
|
||||
RCT2_GLOBAL((int)arguments + 4, uint16) += 6;
|
||||
|
||||
|
@ -2390,7 +2390,7 @@ static void window_ride_vehicle_dropdown()
|
|||
break;
|
||||
case WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = 1019;
|
||||
game_do_command(0, (1 << 8) | 1, 0, ((rideEntry->var_00F + dropdownIndex) << 8) | w->number, GAME_COMMAND_9, 0, 0);
|
||||
game_do_command(0, (1 << 8) | 1, 0, ((rideEntry->min_cars_in_train + dropdownIndex) << 8) | w->number, GAME_COMMAND_9, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2461,7 +2461,7 @@ static void window_ride_vehicle_invalidate()
|
|||
}
|
||||
|
||||
// Cars per train
|
||||
if (rideEntry->var_012 + 1 < rideEntry->var_010) {
|
||||
if (rideEntry->var_012 + 1 < rideEntry->max_cars_in_train) {
|
||||
window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].image = carsPerTrain > 1 ? 1023 : 1022;
|
||||
window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN].type = WWT_DROPDOWN;
|
||||
window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
|
||||
|
@ -2950,8 +2950,8 @@ static void window_ride_operating_update(rct_window *w)
|
|||
widget_invalidate(w, WIDX_TAB_3);
|
||||
|
||||
ride = GET_RIDE(w->number);
|
||||
if (ride->var_14D & 10) {
|
||||
ride->var_14D &= ~10;
|
||||
if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_OPERATING) {
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_OPERATING;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
|
@ -3360,8 +3360,8 @@ static void window_ride_maintenance_update(rct_window *w)
|
|||
widget_invalidate(w, WIDX_TAB_4);
|
||||
|
||||
ride = GET_RIDE(w->number);
|
||||
if (ride->var_14D & 20) {
|
||||
ride->var_14D &= ~20;
|
||||
if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAINTENANCE) {
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MAINTENANCE;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
|
@ -3434,13 +3434,12 @@ static void window_ride_maintenance_paint()
|
|||
x = w->x + widget->left + 4;
|
||||
y = w->y + widget->top + 4;
|
||||
|
||||
reliability = ride->var_196 >> 8;
|
||||
reliability = ride->reliability >> 8;
|
||||
gfx_draw_string_left(dpi, STR_RELIABILITY_LABEL_1757, &reliability, 0, x, y);
|
||||
window_ride_maintenance_draw_bar(w, dpi, x + 103, y, max(10, reliability), 14);
|
||||
y += 11;
|
||||
|
||||
// Down time
|
||||
downTime = ride->var_199;
|
||||
downTime = ride->downtime;
|
||||
gfx_draw_string_left(dpi, STR_DOWN_TIME_LABEL_1889, &downTime, 0, x, y);
|
||||
window_ride_maintenance_draw_bar(w, dpi, x + 103, y, downTime, 28);
|
||||
y += 26;
|
||||
|
@ -3740,7 +3739,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
|
|||
dropdownWidget->bottom - dropdownWidget->top + 1,
|
||||
w->colours[1],
|
||||
0,
|
||||
rideEntry->var_010 > 1 ? 3 : 2,
|
||||
rideEntry->max_cars_in_train > 1 ? 3 : 2,
|
||||
widget->right - dropdownWidget->left
|
||||
);
|
||||
|
||||
|
@ -5452,8 +5451,8 @@ static void window_ride_income_update(rct_window *w)
|
|||
widget_invalidate(w, WIDX_TAB_9);
|
||||
|
||||
ride = GET_RIDE(w->number);
|
||||
if (ride->var_14D & 2) {
|
||||
ride->var_14D &= ~2;
|
||||
if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_INCOME) {
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_INCOME;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
|
@ -5736,8 +5735,8 @@ static void window_ride_customer_update(rct_window *w)
|
|||
widget_invalidate(w, WIDX_TAB_10);
|
||||
|
||||
ride = GET_RIDE(w->number);
|
||||
if (ride->var_14D & 1) {
|
||||
ride->var_14D &= ~1;
|
||||
if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_CUSTOMER) {
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_CUSTOMER;
|
||||
window_invalidate(w);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -507,13 +507,13 @@ static void window_ride_list_scrollpaint()
|
|||
case INFORMATION_TYPE_RELIABILITY:
|
||||
// edx = RCT2_GLOBAL(0x009ACFA4 + (ride->var_001 * 4), uint32);
|
||||
|
||||
RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->var_196 >> 8;
|
||||
RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->reliability >> 8;
|
||||
formatSecondary = STR_RELIABILITY_LABEL;
|
||||
break;
|
||||
case INFORMATION_TYPE_DOWN_TIME:
|
||||
// edx = RCT2_GLOBAL(0x009ACFA4 + (ride->var_001 * 4), uint32);
|
||||
|
||||
RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->var_199;
|
||||
RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->downtime;
|
||||
formatSecondary = STR_DOWN_TIME_LABEL;
|
||||
break;
|
||||
case INFORMATION_TYPE_GUESTS_FAVOURITE:
|
||||
|
@ -579,8 +579,8 @@ static void window_ride_list_refresh_list(rct_window *w)
|
|||
continue;
|
||||
|
||||
countA++;
|
||||
if (ride->var_14D & 8) {
|
||||
ride->var_14D &= ~8;
|
||||
if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_LIST) {
|
||||
ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_LIST;
|
||||
countB++;
|
||||
}
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ static void window_ride_list_refresh_list(rct_window *w)
|
|||
case INFORMATION_TYPE_RELIABILITY:
|
||||
while (--current_list_position >= 0) {
|
||||
otherRide = &g_ride_list[w->list_item_positions[current_list_position]];
|
||||
if (ride->var_196 >> 8 <= otherRide->var_196 >> 8)
|
||||
if (ride->reliability >> 8 <= otherRide->reliability >> 8)
|
||||
break;
|
||||
|
||||
window_bubble_list_item(w, current_list_position);
|
||||
|
@ -670,7 +670,7 @@ static void window_ride_list_refresh_list(rct_window *w)
|
|||
case INFORMATION_TYPE_DOWN_TIME:
|
||||
while (--current_list_position >= 0) {
|
||||
otherRide = &g_ride_list[w->list_item_positions[current_list_position]];
|
||||
if (ride->var_199 <= otherRide->var_199)
|
||||
if (ride->downtime <= otherRide->downtime)
|
||||
break;
|
||||
|
||||
window_bubble_list_item(w, current_list_position);
|
||||
|
|
|
@ -931,10 +931,10 @@ void window_scenery_invalidate()
|
|||
} else if (tabSelectedSceneryId < 0x100) {
|
||||
sceneryEntry = g_smallSceneryEntries[tabSelectedSceneryId];
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & (SMALL_SCENERY_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG10)) {
|
||||
if (sceneryEntry->small_scenery.flags & (SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG10)) {
|
||||
window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN;
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_HAS_SECONDARY_COLOUR)
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR)
|
||||
window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLORBTN;
|
||||
}
|
||||
}
|
||||
|
@ -1145,18 +1145,18 @@ void window_scenery_scrollpaint()
|
|||
|
||||
uint32 imageId = sceneryEntry->image + window_scenery_rotation;
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_HAS_PRIMARY_COLOUR) {
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) {
|
||||
imageId |= (window_scenery_primary_colour << 19) | 0x20000000;
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_HAS_SECONDARY_COLOUR) {
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) {
|
||||
imageId |= (window_scenery_secondary_colour << 24) | 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 spriteTop = (sceneryEntry->small_scenery.height / 4) + 0x2B;
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG1 &&
|
||||
sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG2) {
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE &&
|
||||
sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) {
|
||||
spriteTop -= 0x0C;
|
||||
}
|
||||
|
||||
|
|
|
@ -641,7 +641,7 @@ static void window_sign_small_dropdown()
|
|||
((w->var_492 & 0x7) << 5);
|
||||
map_element->flags |= ((w->var_492 & 0x18) << 2);
|
||||
|
||||
RCT2_CALLPROC_X(0x6EC847, x, 0, y, 0, map_element->clearance_height << 3, map_element->base_height << 3, 0);
|
||||
sub_6EC847(x, y, map_element->base_height * 8, map_element->clearance_height * 8);
|
||||
window_invalidate(w);
|
||||
}
|
||||
|
||||
|
|
|
@ -1158,8 +1158,8 @@ void window_staff_overview_tool_down(){
|
|||
peep_window_state_update(peep);
|
||||
peep->action = 0xFF;
|
||||
peep->var_6D = 0;
|
||||
peep->var_70 = 0;
|
||||
peep->var_6E = 0;
|
||||
peep->action_sprite_image_offset = 0;
|
||||
peep->action_sprite_type = 0;
|
||||
peep->var_C4 = 0;
|
||||
|
||||
tool_cancel();
|
||||
|
@ -1196,8 +1196,8 @@ void window_staff_overview_tool_abort(){
|
|||
peep_window_state_update(peep);
|
||||
peep->action = 0xFF;
|
||||
peep->var_6D = 0;
|
||||
peep->var_70 = 0;
|
||||
peep->var_6E = 0;
|
||||
peep->action_sprite_image_offset = 0;
|
||||
peep->action_sprite_type = 0;
|
||||
peep->var_C4 = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -459,7 +459,7 @@ void footpath_provisional_remove()
|
|||
*
|
||||
* rct2: 0x006A7831
|
||||
*/
|
||||
void sub_6A7831()
|
||||
void footpath_provisional_update()
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) & PROVISIONAL_PATH_FLAG_SHOW_ARROW) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS, uint8) &= ~PROVISIONAL_PATH_FLAG_SHOW_ARROW;
|
||||
|
|
|
@ -45,7 +45,7 @@ money32 footpath_place(int type, int x, int y, int z, int slope, int flags);
|
|||
void footpath_remove(int x, int y, int z, int flags);
|
||||
money32 footpath_provisional_set(int type, int x, int y, int z, int slope);
|
||||
void footpath_provisional_remove();
|
||||
void sub_6A7831();
|
||||
void footpath_provisional_update();
|
||||
void sub_68A0C9(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John, Peter Hill
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
|
@ -19,19 +19,427 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "../addresses.h"
|
||||
#include "../game.h"
|
||||
#include "../common.h"
|
||||
#include "../scenario.h"
|
||||
#include "fountain.h"
|
||||
#include "map.h"
|
||||
#include "scenery.h"
|
||||
#include "sprite.h"
|
||||
|
||||
enum {
|
||||
PATTERN_CYCLIC_SQUARES,
|
||||
PATTERN_CONTINUOUS_CHASERS,
|
||||
PATTERN_BOUNCING_PAIRS,
|
||||
PATTERN_SPROUTING_BLOOMS,
|
||||
PATTERN_RACING_PAIRS,
|
||||
PATTERN_SPLITTING_CHASERS,
|
||||
PATTERN_DOPEY_JUMPERS,
|
||||
PATTERN_FAST_RANDOM_CHASERS
|
||||
};
|
||||
|
||||
enum {
|
||||
FOUNTAIN_FLAG_FAST = 1 << 0,
|
||||
FOUNTAIN_FLAG_GOTO_EDGE = 1 << 1,
|
||||
FOUNTAIN_FLAG_SPLIT = 1 << 2,
|
||||
FOUNTAIN_FLAG_TERMINATE = 1 << 3,
|
||||
FOUNTAIN_FLAG_BOUNCE = 1 << 4,
|
||||
FOUNTAIN_FLAG_7 = 1 << 7
|
||||
};
|
||||
|
||||
const rct_xy16 dword_97F000[] = {
|
||||
{ -32, 0 },
|
||||
{ -32, -32 },
|
||||
{ 0, 0 },
|
||||
{ -32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, -32 },
|
||||
{ 0, -32 },
|
||||
{ -32, -32 },
|
||||
};
|
||||
|
||||
const rct_xy16 dword_97F020[] = {
|
||||
{ 32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 32 },
|
||||
{ 32, 32 },
|
||||
{ 32, 32 },
|
||||
{ 32, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 32 }
|
||||
};
|
||||
|
||||
// rct2: 0x0097F040
|
||||
const uint8 _fountainDirections[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
|
||||
|
||||
// rct2: 0x0097F048
|
||||
const uint8 _fountainDirectionFlags[] = { 0, 0, FOUNTAIN_FLAG_7, FOUNTAIN_FLAG_7, FOUNTAIN_FLAG_7, FOUNTAIN_FLAG_7, 0, 0 };
|
||||
|
||||
// rct2: 0x0097F050
|
||||
const uint8 _fountainPatternFlags[] = {
|
||||
FOUNTAIN_FLAG_TERMINATE, // PATTERN_CYCLIC_SQUARES
|
||||
FOUNTAIN_FLAG_FAST | FOUNTAIN_FLAG_GOTO_EDGE, // PATTERN_CONTINUOUS_CHASERS
|
||||
FOUNTAIN_FLAG_BOUNCE, // PATTERN_BOUNCING_PAIRS
|
||||
FOUNTAIN_FLAG_FAST | FOUNTAIN_FLAG_SPLIT, // PATTERN_SPROUTING_BLOOMS
|
||||
FOUNTAIN_FLAG_GOTO_EDGE, // PATTERN_RACING_PAIRS
|
||||
FOUNTAIN_FLAG_FAST | FOUNTAIN_FLAG_GOTO_EDGE | FOUNTAIN_FLAG_SPLIT, // PATTERN_SPLITTING_CHASERS
|
||||
0, // PATTERN_DOPEY_JUMPERS
|
||||
FOUNTAIN_FLAG_FAST // PATTERN_FAST_RANDOM_CHASERS
|
||||
};
|
||||
|
||||
static void jumping_fountain_continue(rct_jumping_fountain *jumpingFountain);
|
||||
static bool is_jumping_fountain(int type, int x, int y, int z);
|
||||
|
||||
static void jumping_fountain_goto_edge(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections);
|
||||
static void jumping_fountain_bounce(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections);
|
||||
static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections);
|
||||
static void jumping_fountain_random(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections);
|
||||
static void jumping_fountain_create_next(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int direction);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006646E1
|
||||
* rct2: 0x00673DBA (water)
|
||||
* rct2: 0x00673F51 (snow)
|
||||
*/
|
||||
void fountain_update_all()
|
||||
void jumping_fountain_begin(int type, int x, int y, rct_map_element *mapElement)
|
||||
{
|
||||
int ignoreScreenFlags = SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & ignoreScreenFlags)
|
||||
int i, randomIndex;
|
||||
int z = mapElement->base_height * 8;
|
||||
|
||||
// Change pattern approximately every 51 seconds
|
||||
int pattern = (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) >> 11) & 7;
|
||||
switch (pattern) {
|
||||
case PATTERN_CYCLIC_SQUARES:
|
||||
// 0, 1, 2, 3
|
||||
for (i = 0; i < 4; i++) {
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + dword_97F020[i].x,
|
||||
y + dword_97F020[i].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
}
|
||||
break;
|
||||
case PATTERN_BOUNCING_PAIRS:
|
||||
// random [0, 2 or 1, 3]
|
||||
randomIndex = scenario_rand() & 1;
|
||||
for (i = randomIndex; i < 4; i += 2) {
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + dword_97F020[i].x,
|
||||
y + dword_97F020[i].y,
|
||||
z,
|
||||
_fountainDirections[i],
|
||||
_fountainDirectionFlags[i] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
}
|
||||
break;
|
||||
case PATTERN_RACING_PAIRS:
|
||||
// random [0 - 3 and 4 - 7]
|
||||
z = mapElement->base_height * 8;
|
||||
randomIndex = scenario_rand() & 3;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + dword_97F020[randomIndex].x,
|
||||
y + dword_97F020[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
randomIndex += 4;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + dword_97F020[randomIndex].x,
|
||||
y + dword_97F020[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// random [0 - 7]
|
||||
randomIndex = scenario_rand() & 7;
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x + dword_97F020[randomIndex].x,
|
||||
y + dword_97F020[randomIndex].y,
|
||||
z,
|
||||
_fountainDirections[randomIndex],
|
||||
_fountainDirectionFlags[randomIndex] | _fountainPatternFlags[pattern],
|
||||
0
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067396A (water)
|
||||
* rct2: 0x006739A4 (snow)
|
||||
*/
|
||||
void jumping_fountain_create(int type, int x, int y, int z, int direction, int flags, int iteration)
|
||||
{
|
||||
rct_jumping_fountain *jumpingFountain;
|
||||
|
||||
jumpingFountain = (rct_jumping_fountain*)create_sprite(SPRITE_IDENTIFIER_MISC);
|
||||
if (jumpingFountain == NULL)
|
||||
return;
|
||||
|
||||
// Probably not just fountains... may include scenery aging and grass growth.
|
||||
RCT2_CALLPROC_EBPSAFE(0x006646EE);
|
||||
jumpingFountain->iteration = iteration;
|
||||
jumpingFountain->var_2E = direction;
|
||||
jumpingFountain->flags = flags;
|
||||
jumpingFountain->sprite_direction = direction << 3;
|
||||
jumpingFountain->var_14 = 33;
|
||||
jumpingFountain->var_09 = 36;
|
||||
jumpingFountain->var_15 = 12;
|
||||
jumpingFountain->sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, (rct_sprite*)jumpingFountain);
|
||||
jumpingFountain->misc_identifier = type == JUMPING_FOUNTAIN_TYPE_SNOW ?
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_SNOW :
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_WATER;
|
||||
jumpingFountain->var_26 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x006733CB (water)
|
||||
* rct: 0x00673407 (snow)
|
||||
*/
|
||||
void jumping_fountain_update(rct_jumping_fountain *jumpingFountain)
|
||||
{
|
||||
int original_var_26a = jumpingFountain->var_26a;
|
||||
jumpingFountain->var_26a += 160;
|
||||
if (original_var_26a <= 255 - 160)
|
||||
return;
|
||||
|
||||
sub_6EC60B((rct_sprite*)jumpingFountain);
|
||||
jumpingFountain->var_26b++;
|
||||
|
||||
switch (jumpingFountain->misc_identifier) {
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
if (jumpingFountain->var_26b == 11 && (jumpingFountain->flags & FOUNTAIN_FLAG_FAST))
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
|
||||
if (jumpingFountain->var_26b == 16 && !(jumpingFountain->flags & FOUNTAIN_FLAG_FAST))
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
if (jumpingFountain->var_26b == 16)
|
||||
jumping_fountain_continue(jumpingFountain);
|
||||
break;
|
||||
}
|
||||
|
||||
if (jumpingFountain->var_26b == 16)
|
||||
sprite_remove((rct_sprite*)jumpingFountain);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006739DE (water)
|
||||
* rct2: 0x00673BCC (snow)
|
||||
*/
|
||||
static void jumping_fountain_continue(rct_jumping_fountain *jumpingFountain)
|
||||
{
|
||||
int direction = (jumpingFountain->sprite_direction >> 3) & 7;
|
||||
int x = jumpingFountain->x + TileDirectionDelta[direction].x;
|
||||
int y = jumpingFountain->y + TileDirectionDelta[direction].y;
|
||||
int z = jumpingFountain->z;
|
||||
|
||||
int type = jumpingFountain->misc_identifier == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW ?
|
||||
JUMPING_FOUNTAIN_TYPE_SNOW :
|
||||
JUMPING_FOUNTAIN_TYPE_WATER;
|
||||
|
||||
int availableDirections = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (is_jumping_fountain(type, x + dword_97F000[i].x, y + dword_97F000[i].y, z))
|
||||
availableDirections |= 1 << i;
|
||||
}
|
||||
|
||||
if (availableDirections == 0)
|
||||
return;
|
||||
|
||||
if (jumpingFountain->flags & FOUNTAIN_FLAG_TERMINATE)
|
||||
return;
|
||||
|
||||
if (jumpingFountain->flags & FOUNTAIN_FLAG_GOTO_EDGE) {
|
||||
jumping_fountain_goto_edge(jumpingFountain, x, y, z, availableDirections);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jumpingFountain->flags & FOUNTAIN_FLAG_BOUNCE) {
|
||||
jumping_fountain_bounce(jumpingFountain, x, y, z, availableDirections);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jumpingFountain->flags & FOUNTAIN_FLAG_SPLIT) {
|
||||
jumping_fountain_split(jumpingFountain, x, y, z, availableDirections);
|
||||
return;
|
||||
}
|
||||
|
||||
jumping_fountain_random(jumpingFountain, x, y, z, availableDirections);
|
||||
}
|
||||
|
||||
static bool is_jumping_fountain(int type, int x, int y, int z)
|
||||
{
|
||||
z = z >> 3;
|
||||
|
||||
int pathBitFlagMask = type == JUMPING_FOUNTAIN_TYPE_SNOW ?
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW :
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER;
|
||||
|
||||
rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_PATH)
|
||||
continue;
|
||||
if (mapElement->base_height != z)
|
||||
continue;
|
||||
if (mapElement->properties.path.additions & 0x80)
|
||||
continue;
|
||||
|
||||
int additions = mapElement->properties.path.additions & 0x0F;
|
||||
if (additions == 0)
|
||||
continue;
|
||||
|
||||
rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1];
|
||||
if (!(sceneryEntry->path_bit.var_06 & pathBitFlagMask))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673B6E
|
||||
*/
|
||||
static void jumping_fountain_goto_edge(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections)
|
||||
{
|
||||
int direction = (jumpingFountain->sprite_direction >> 3) << 1;
|
||||
if (availableDirections & (1 << direction)) {
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
return;
|
||||
}
|
||||
|
||||
direction++;
|
||||
if (availableDirections & (1 << direction)) {
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 randomIndex = scenario_rand();
|
||||
if ((randomIndex & 0xFFFF) < 0x3333)
|
||||
return;
|
||||
|
||||
if (jumpingFountain->flags & FOUNTAIN_FLAG_SPLIT) {
|
||||
jumping_fountain_split(jumpingFountain, x, y, z, availableDirections);
|
||||
return;
|
||||
}
|
||||
|
||||
direction = randomIndex & 7;
|
||||
while (!(availableDirections & (1 << direction)))
|
||||
direction = (direction + 1) & 7;
|
||||
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673B45
|
||||
*/
|
||||
static void jumping_fountain_bounce(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections)
|
||||
{
|
||||
jumpingFountain->iteration++;
|
||||
if (jumpingFountain->iteration >= 8)
|
||||
return;
|
||||
|
||||
int direction = ((jumpingFountain->sprite_direction >> 3) ^ 2) << 1;
|
||||
if (availableDirections & (1 << direction)) {
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
return;
|
||||
}
|
||||
|
||||
direction++;
|
||||
if (availableDirections & (1 << direction))
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673ACE
|
||||
*/
|
||||
static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections)
|
||||
{
|
||||
if (jumpingFountain->iteration >= 3)
|
||||
return;
|
||||
|
||||
int type = jumpingFountain->misc_identifier == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW ?
|
||||
JUMPING_FOUNTAIN_TYPE_SNOW :
|
||||
JUMPING_FOUNTAIN_TYPE_WATER;
|
||||
|
||||
int direction = ((jumpingFountain->sprite_direction >> 3) ^ 2) << 1;
|
||||
availableDirections &= ~(1 << direction);
|
||||
direction++;
|
||||
availableDirections &= ~(1 << direction);
|
||||
|
||||
for (direction = 0; direction < 8; direction++) {
|
||||
if (availableDirections & (1 << direction)) {
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x, y, z,
|
||||
direction >> 1,
|
||||
jumpingFountain->flags & ~FOUNTAIN_FLAG_7,
|
||||
jumpingFountain->iteration + 1
|
||||
);
|
||||
}
|
||||
direction++;
|
||||
if (availableDirections & (1 << direction)) {
|
||||
jumping_fountain_create(
|
||||
type,
|
||||
x, y, z,
|
||||
direction >> 1,
|
||||
jumpingFountain->flags | FOUNTAIN_FLAG_7,
|
||||
jumpingFountain->iteration + 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673AAC
|
||||
*/
|
||||
static void jumping_fountain_random(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections)
|
||||
{
|
||||
uint32 randomIndex = scenario_rand();
|
||||
if ((randomIndex & 0xFFFF) < 0x2000)
|
||||
return;
|
||||
|
||||
int direction = randomIndex & 7;
|
||||
while (!(availableDirections & (1 << direction)))
|
||||
direction = (direction + 1) & 7;
|
||||
|
||||
jumping_fountain_create_next(jumpingFountain, x, y, z, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673B45
|
||||
*/
|
||||
static void jumping_fountain_create_next(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int direction)
|
||||
{
|
||||
int flags = jumpingFountain->flags & ~FOUNTAIN_FLAG_7;
|
||||
if (direction & 1)
|
||||
flags |= FOUNTAIN_FLAG_7;
|
||||
|
||||
int type = jumpingFountain->misc_identifier == SPRITE_MISC_JUMPING_FOUNTAIN_SNOW ?
|
||||
JUMPING_FOUNTAIN_TYPE_SNOW :
|
||||
JUMPING_FOUNTAIN_TYPE_WATER;
|
||||
|
||||
jumping_fountain_create(type, x, y, z, direction >> 1, flags, jumpingFountain->iteration);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _WORLD_FOUNTAIN_H_
|
||||
#define _WORLD_FOUNTAIN_H_
|
||||
|
||||
#include "../common.h"
|
||||
#include "map.h"
|
||||
#include "sprite.h"
|
||||
|
||||
enum {
|
||||
JUMPING_FOUNTAIN_TYPE_WATER,
|
||||
JUMPING_FOUNTAIN_TYPE_SNOW
|
||||
};
|
||||
|
||||
void jumping_fountain_begin(int type, int x, int y, rct_map_element *mapElement);
|
||||
void jumping_fountain_create(int type, int x, int y, int z, int direction, int flags, int iteration);
|
||||
void jumping_fountain_update(rct_jumping_fountain *jumpingFountain);
|
||||
|
||||
#endif
|
111
src/world/map.c
111
src/world/map.c
|
@ -24,6 +24,7 @@
|
|||
#include "../localisation/date.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../management/finance.h"
|
||||
#include "../scenario.h"
|
||||
#include "banner.h"
|
||||
#include "climate.h"
|
||||
#include "map.h"
|
||||
|
@ -48,6 +49,8 @@ int _sub_6A876D_save_y;
|
|||
|
||||
static void tiles_init();
|
||||
static void sub_6A87BB(int x, int y);
|
||||
static void map_update_grass_length(int x, int y, rct_map_element *mapElement);
|
||||
static void map_set_grass_length(int x, int y, rct_map_element *mapElement, int length);
|
||||
|
||||
void map_element_iterator_begin(map_element_iterator *it)
|
||||
{
|
||||
|
@ -194,7 +197,7 @@ void map_init(int size)
|
|||
map_element_set_terrain_edge(map_element, TERRAIN_EDGE_ROCK);
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(0x013B0E70, sint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GRASS_SCENERY_TILEPOS, sint16) = 0;
|
||||
_sub_6A876D_save_x = 0;
|
||||
_sub_6A876D_save_y = 0;
|
||||
RCT2_GLOBAL(0x01358830, sint16) = size * 32 - 32;
|
||||
|
@ -1117,4 +1120,110 @@ void map_remove_intersecting_walls(int x, int y, int z0, int z1, int direction)
|
|||
map_element_remove(mapElement);
|
||||
mapElement -= 1;
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates grass length, scenery age and jumping fountains.
|
||||
*
|
||||
* rct2: 0x006646E1
|
||||
*/
|
||||
void map_update_tiles()
|
||||
{
|
||||
int ignoreScreenFlags = SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & ignoreScreenFlags)
|
||||
return;
|
||||
|
||||
// Update 43 more tiles
|
||||
for (int j = 0; j < 43; j++) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
uint16 interleaved_xy = RCT2_GLOBAL(RCT2_ADDRESS_GRASS_SCENERY_TILEPOS, sint16);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
x = (x << 1) | (interleaved_xy & 1);
|
||||
interleaved_xy >>= 1;
|
||||
y = (y << 1) | (interleaved_xy & 1);
|
||||
interleaved_xy >>= 1;
|
||||
}
|
||||
|
||||
rct_map_element *mapElement = map_get_surface_element_at(x, y);
|
||||
if (mapElement != NULL) {
|
||||
map_update_grass_length(x * 32, y * 32, mapElement);
|
||||
scenery_update_tile(x * 32, y * 32);
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GRASS_SCENERY_TILEPOS, sint16)++;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GRASS_SCENERY_TILEPOS, sint16) &= 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006647A1
|
||||
*/
|
||||
static void map_update_grass_length(int x, int y, rct_map_element *mapElement)
|
||||
{
|
||||
// Check if tile is grass
|
||||
if ((mapElement->properties.surface.terrain & 0xE0) && !(mapElement->type & 3))
|
||||
return;
|
||||
|
||||
int grassLength = mapElement->properties.surface.grass_length & 7;
|
||||
|
||||
// Check if grass is underwater or outside park
|
||||
int waterHeight = (mapElement->properties.surface.terrain & 0x1F) * 2;
|
||||
if (waterHeight > mapElement->base_height || !map_is_location_in_park(x, y)) {
|
||||
if (grassLength != GRASS_LENGTH_CLEAR_0)
|
||||
map_set_grass_length(x, y, mapElement, GRASS_LENGTH_CLEAR_0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Grass can't grow any further
|
||||
if (grassLength == GRASS_LENGTH_CLUMPS_2)
|
||||
return;
|
||||
|
||||
int z0 = mapElement->base_height;
|
||||
int z1 = mapElement->base_height + 2;
|
||||
if (mapElement->properties.surface.slope & 0x10)
|
||||
z1 += 2;
|
||||
|
||||
// Check objects above grass
|
||||
rct_map_element *mapElementAbove = mapElement;
|
||||
for (;;) {
|
||||
if (mapElementAbove->flags & MAP_ELEMENT_FLAG_LAST_TILE) {
|
||||
// Grow grass
|
||||
if (mapElement->properties.surface.grass_length < 0xF0) {
|
||||
mapElement->properties.surface.grass_length += 0x10;
|
||||
} else {
|
||||
mapElement->properties.surface.grass_length += 0x10;
|
||||
mapElement->properties.surface.grass_length ^= 8;
|
||||
if (mapElement->properties.surface.grass_length & 8) {
|
||||
// Random growth rate
|
||||
mapElement->properties.surface.grass_length |= scenario_rand() & 0x70;
|
||||
} else {
|
||||
// Increase length
|
||||
map_set_grass_length(x, y, mapElement, grassLength + 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mapElementAbove++;
|
||||
if (map_element_get_type(mapElementAbove) == MAP_ELEMENT_TYPE_FENCE)
|
||||
continue;
|
||||
if (z0 >= mapElementAbove->clearance_height)
|
||||
continue;
|
||||
if (z1 < mapElementAbove->base_height)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void map_set_grass_length(int x, int y, rct_map_element *mapElement, int length)
|
||||
{
|
||||
int z0, z1;
|
||||
|
||||
mapElement->properties.surface.grass_length = length;
|
||||
z0 = mapElement->base_height * 8;
|
||||
z1 = z0 + 16;
|
||||
sub_6EC847(x, y, z0, z1);
|
||||
}
|
|
@ -39,8 +39,13 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
uint8 type; //4
|
||||
uint8 sequence; //5
|
||||
uint8 colour; //6
|
||||
union{
|
||||
struct{
|
||||
uint8 sequence; //5
|
||||
uint8 colour; //6
|
||||
};
|
||||
uint16 maze_entry; // 5
|
||||
};
|
||||
uint8 ride_index; //7
|
||||
} rct_map_element_track_properties;
|
||||
|
||||
|
@ -267,8 +272,6 @@ rct_map_element *map_element_insert(int x, int y, int z, int flags);
|
|||
int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl);
|
||||
int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl);
|
||||
|
||||
void fountain_update_all();
|
||||
|
||||
void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp);
|
||||
|
||||
|
@ -286,5 +289,6 @@ int map_element_iterator_next(map_element_iterator *it);
|
|||
void map_element_iterator_restart_for_tile(map_element_iterator *it);
|
||||
|
||||
void map_remove_intersecting_walls(int x, int y, int z0, int z1, int direction);
|
||||
void map_update_tiles();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,45 +21,52 @@
|
|||
#include "../addresses.h"
|
||||
#include "../ride/ride.h"
|
||||
#include "../ride/ride_data.h"
|
||||
#include "../ride/track.h"
|
||||
#include "map_animation.h"
|
||||
#include "map.h"
|
||||
#include "scenery.h"
|
||||
#include "sprite.h"
|
||||
|
||||
rct_animated_object *gAnimatedObjects = (rct_animated_object*)0x013886A0;
|
||||
|
||||
typedef bool (*map_animation_invalidate_event_handler)(int x, int y, int baseZ);
|
||||
|
||||
static bool map_animation_invalidate_ride_entrance(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_queue_banner(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_park_entrance(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_remove(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_banner(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_large_scenery(int x, int y, int baseZ);
|
||||
static bool sub_6E5B50(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate_wall(int x, int y, int baseZ);
|
||||
static bool map_animation_invalidate(rct_map_animation *obj);
|
||||
|
||||
/** rct2: 0x009819DC */
|
||||
const uint32 _animatedObjectEventHandlers[] = {
|
||||
(uint32)map_animation_invalidate_ride_entrance, // ride entrance
|
||||
(uint32)map_animation_invalidate_queue_banner, // queue banner
|
||||
(uint32)map_animation_invalidate_small_scenery, // small scenery + peep
|
||||
(uint32)map_animation_invalidate_park_entrance, // park entrance
|
||||
0x006CE29E, // track
|
||||
0x006CE2F3, // track
|
||||
0x006CE39D, // track
|
||||
0x006CE348, // track
|
||||
0x006CE3FA, // track
|
||||
(uint32)map_animation_invalidate_remove, // simply return true
|
||||
(uint32)map_animation_invalidate_banner, // banner
|
||||
(uint32)map_animation_invalidate_large_scenery, // large scenery
|
||||
(uint32)sub_6E5B50, // wall
|
||||
(uint32)map_animation_invalidate_wall // wall
|
||||
};
|
||||
static const map_animation_invalidate_event_handler _animatedObjectEventHandlers[MAP_ANIMATION_TYPE_COUNT];
|
||||
|
||||
rct_map_animation *gAnimatedObjects = (rct_map_animation*)0x013886A0;
|
||||
|
||||
static bool map_animation_invalidate(rct_animated_object *obj);
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068AF67
|
||||
*
|
||||
* @param type (dh)
|
||||
* @param x (ax)
|
||||
* @param y (cx)
|
||||
* @param z (dl)
|
||||
*/
|
||||
void map_animation_create(int type, int x, int y, int z)
|
||||
{
|
||||
rct_map_animation *aobj = &gAnimatedObjects[0];
|
||||
int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
|
||||
for (; numAnimatedObjects > 0; aobj++) {
|
||||
if (aobj->x != x)
|
||||
continue;
|
||||
if (aobj->y != y)
|
||||
continue;
|
||||
if (aobj->baseZ != z)
|
||||
continue;
|
||||
|
||||
// Animation already exists
|
||||
return;
|
||||
}
|
||||
|
||||
// Create new animation
|
||||
RCT2_GLOBAL(0x0138B580, uint16)++;
|
||||
aobj->type = type;
|
||||
aobj->x = x;
|
||||
aobj->y = y;
|
||||
aobj->baseZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -67,7 +74,7 @@ static bool map_animation_invalidate(rct_animated_object *obj);
|
|||
*/
|
||||
void map_animation_invalidate_all()
|
||||
{
|
||||
rct_animated_object *aobj = &gAnimatedObjects[0];
|
||||
rct_map_animation *aobj = &gAnimatedObjects[0];
|
||||
int numAnimatedObjects = RCT2_GLOBAL(0x0138B580, uint16);
|
||||
while (numAnimatedObjects > 0) {
|
||||
if (map_animation_invalidate(aobj)) {
|
||||
|
@ -86,16 +93,11 @@ void map_animation_invalidate_all()
|
|||
/**
|
||||
* @returns true if the animation should be removed.
|
||||
*/
|
||||
static bool map_animation_invalidate(rct_animated_object *obj)
|
||||
static bool map_animation_invalidate(rct_map_animation *obj)
|
||||
{
|
||||
uint32 address = _animatedObjectEventHandlers[obj->type];
|
||||
if (((address >> 20) & 0xFFF) == 0x006) {
|
||||
int result = RCT2_CALLPROC_X(address, obj->x, 0, obj->y, obj->baseZ, 0, 0, 0);
|
||||
return (result & 0x100) != 0;
|
||||
} else {
|
||||
map_animation_invalidate_event_handler handler = (map_animation_invalidate_event_handler)address;
|
||||
return handler(obj->x, obj->y, obj->baseZ);
|
||||
}
|
||||
assert(obj->type < MAP_ANIMATION_TYPE_COUNT);
|
||||
|
||||
return _animatedObjectEventHandlers[obj->type](obj->x, obj->y, obj->baseZ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +149,7 @@ static bool map_animation_invalidate_queue_banner(int x, int y, int baseZ)
|
|||
if (!(mapElement->properties.path.type & PATH_FLAG_QUEUE_BANNER))
|
||||
continue;
|
||||
|
||||
int direction = ((mapElement->type >> 6) & 3) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8);
|
||||
int direction = ((mapElement->type >> 6) + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)) & 3;
|
||||
if (direction == MAP_ELEMENT_DIRECTION_NORTH || direction == MAP_ELEMENT_DIRECTION_EAST) {
|
||||
baseZ = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, baseZ + 16, baseZ + 30);
|
||||
|
@ -184,14 +186,15 @@ static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (sceneryEntry->small_scenery.flags & 0x2000) {
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_IS_CLOCK) {
|
||||
// Peep, looking at scenery
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x3FF)) {
|
||||
int direction = mapElement->type & 3;
|
||||
int x2 = x - TileDirectionDelta[direction].x;
|
||||
int y2 = y - TileDirectionDelta[direction].y;
|
||||
|
||||
uint16 spriteIdx = RCT2_ADDRESS(0x00F1EF60, uint16)[((x2 & 0x1FE0) << 3) | (y2 >> 5)];
|
||||
for (; spriteIdx != 0xFFFF; spriteIdx = sprite->unknown.var_02) {
|
||||
for (; spriteIdx != 0xFFFF; spriteIdx = sprite->unknown.next_in_quadrant) {
|
||||
sprite = &g_sprite_list[spriteIdx];
|
||||
if (sprite->unknown.linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP)
|
||||
continue;
|
||||
|
@ -204,9 +207,9 @@ static bool map_animation_invalidate_small_scenery(int x, int y, int baseZ)
|
|||
if (peep->action < PEEP_ACTION_NONE_1)
|
||||
continue;
|
||||
|
||||
peep->action = 0;
|
||||
peep->action = PEEP_ACTION_CHECK_TIME;
|
||||
peep->action_frame = 0;
|
||||
peep->var_70 = 0;
|
||||
peep->action_sprite_image_offset = 0;
|
||||
sub_693B58(peep);
|
||||
RCT2_CALLPROC_X(0x006EC53F, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
break;
|
||||
|
@ -246,6 +249,137 @@ static bool map_animation_invalidate_park_entrance(int x, int y, int baseZ)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CE29E
|
||||
*/
|
||||
static bool map_animation_invalidate_track_waterfall(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (mapElement->base_height != baseZ)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.type == TRACK_ELEM_WATERFALL) {
|
||||
int z = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, z + 14, z + 46);
|
||||
return false;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CE2F3
|
||||
*/
|
||||
static bool map_animation_invalidate_track_rapids(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (mapElement->base_height != baseZ)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.type == TRACK_ELEM_RAPIDS) {
|
||||
int z = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, z + 14, z + 18);
|
||||
return false;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CE39D
|
||||
*/
|
||||
static bool map_animation_invalidate_track_onridephoto(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
bool wasInvalidated = false;
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (mapElement->base_height != baseZ)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.type == TRACK_ELEM_ON_RIDE_PHOTO) {
|
||||
int z = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||
if (mapElement->properties.track.sequence & 0xF0) {
|
||||
mapElement->properties.track.sequence -= 0x10;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CE348
|
||||
*/
|
||||
static bool map_animation_invalidate_track_whirlpool(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (mapElement->base_height != baseZ)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.type == TRACK_ELEM_WHIRLPOOL) {
|
||||
int z = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, z + 14, z + 18);
|
||||
return false;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006CE3FA
|
||||
*/
|
||||
static bool map_animation_invalidate_track_spinningtunnel(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (mapElement->base_height != baseZ)
|
||||
continue;
|
||||
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK)
|
||||
continue;
|
||||
|
||||
if (mapElement->properties.track.type == TRACK_ELEM_SPINNING_TUNNEL) {
|
||||
int z = mapElement->base_height * 8;
|
||||
map_invalidate_tile(x, y, z + 14, z + 32);
|
||||
return false;
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068DF8F
|
||||
|
@ -310,7 +444,7 @@ static bool map_animation_invalidate_large_scenery(int x, int y, int baseZ)
|
|||
*
|
||||
* rct2: 0x006E5B50
|
||||
*/
|
||||
static bool sub_6E5B50(int x, int y, int baseZ)
|
||||
static bool map_animation_invalidate_wall_unknown(int x, int y, int baseZ)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
|
@ -389,4 +523,22 @@ static bool map_animation_invalidate_wall(int x, int y, int baseZ)
|
|||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
|
||||
return !wasInvalidated;
|
||||
}
|
||||
}
|
||||
|
||||
/** rct2: 0x009819DC */
|
||||
static const map_animation_invalidate_event_handler _animatedObjectEventHandlers[MAP_ANIMATION_TYPE_COUNT] = {
|
||||
map_animation_invalidate_ride_entrance,
|
||||
map_animation_invalidate_queue_banner,
|
||||
map_animation_invalidate_small_scenery,
|
||||
map_animation_invalidate_park_entrance,
|
||||
map_animation_invalidate_track_waterfall,
|
||||
map_animation_invalidate_track_rapids,
|
||||
map_animation_invalidate_track_onridephoto,
|
||||
map_animation_invalidate_track_whirlpool,
|
||||
map_animation_invalidate_track_spinningtunnel,
|
||||
map_animation_invalidate_remove,
|
||||
map_animation_invalidate_banner,
|
||||
map_animation_invalidate_large_scenery,
|
||||
map_animation_invalidate_wall_unknown,
|
||||
map_animation_invalidate_wall
|
||||
};
|
|
@ -32,10 +32,29 @@ typedef struct {
|
|||
uint8 type;
|
||||
uint16 x;
|
||||
uint16 y;
|
||||
} rct_animated_object;
|
||||
} rct_map_animation;
|
||||
|
||||
extern rct_animated_object *gAnimatedObjects;
|
||||
enum {
|
||||
MAP_ANIMATION_TYPE_RIDE_ENTRANCE,
|
||||
MAP_ANIMATION_TYPE_QUEUE_BANNER,
|
||||
MAP_ANIMATION_TYPE_SMALL_SCENERY,
|
||||
MAP_ANIMATION_TYPE_PARK_ENTRANCE,
|
||||
MAP_ANIMATION_TYPE_TRACK_WATERFALL,
|
||||
MAP_ANIMATION_TYPE_TRACK_RAPIDS,
|
||||
MAP_ANIMATION_TYPE_TRACK_ONRIDEPHOTO,
|
||||
MAP_ANIMATION_TYPE_TRACK_WHIRLPOOL,
|
||||
MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL,
|
||||
MAP_ANIMATION_TYPE_REMOVE,
|
||||
MAP_ANIMATION_TYPE_BANNER,
|
||||
MAP_ANIMATION_TYPE_LARGE_SCENERY,
|
||||
MAP_ANIMATION_TYPE_WALL_UNKNOWN,
|
||||
MAP_ANIMATION_TYPE_WALL,
|
||||
MAP_ANIMATION_TYPE_COUNT
|
||||
};
|
||||
|
||||
extern rct_map_animation *gAnimatedObjects;
|
||||
|
||||
void map_animation_create(int type, int x, int y, int z);
|
||||
void map_animation_invalidate_all();
|
||||
|
||||
#endif
|
|
@ -203,15 +203,13 @@ int calculate_park_rating()
|
|||
// Rides
|
||||
{
|
||||
int i;
|
||||
short _ax, total_ride_intensity = 0, total_ride_excitement = 0, average_intensity, average_excitement;
|
||||
short total_ride_uptime = 0, total_ride_intensity = 0, total_ride_excitement = 0, average_intensity, average_excitement;
|
||||
int num_rides, num_exciting_rides = 0;
|
||||
rct_ride* ride;
|
||||
|
||||
//
|
||||
_ax = 0;
|
||||
num_rides = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
_ax += 100 - ride->var_199;
|
||||
total_ride_uptime += 100 - ride->downtime;
|
||||
|
||||
if (ride->excitement != -1){
|
||||
total_ride_excitement += ride->excitement / 8;
|
||||
|
@ -222,7 +220,7 @@ int calculate_park_rating()
|
|||
}
|
||||
result -= 200;
|
||||
if (num_rides > 0)
|
||||
result += (_ax / num_rides) * 2;
|
||||
result += (total_ride_uptime / num_rides) * 2;
|
||||
|
||||
result -= 100;
|
||||
|
||||
|
@ -276,11 +274,11 @@ money32 calculate_ride_value(rct_ride *ride)
|
|||
{
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
return 0;
|
||||
if (ride->reliability == 0xFFFF)
|
||||
if (ride->value == RIDE_VALUE_UNDEFINED)
|
||||
return 0;
|
||||
|
||||
// Reliability * (...)
|
||||
return (ride->reliability * 10) * (
|
||||
// Fair value * (...)
|
||||
return (ride->value * 10) * (
|
||||
ride->var_124 + ride->var_126 + ride->var_128 + ride->var_12A +
|
||||
ride->var_12C + ride->var_12E + ride->age + ride->running_cost +
|
||||
ride->var_134 + ride->var_136 +
|
||||
|
@ -369,8 +367,8 @@ static int park_calculate_guest_generation_probability()
|
|||
suggestedMaxGuests += RCT2_GLOBAL(0x0097D21E + (ride->type * 8), uint8);
|
||||
|
||||
// Add ride value
|
||||
if (ride->reliability != RIDE_RELIABILITY_UNDEFINED) {
|
||||
int rideValue = ride->reliability - ride->price;
|
||||
if (ride->value != RIDE_VALUE_UNDEFINED) {
|
||||
int rideValue = ride->value - ride->price;
|
||||
if (rideValue > 0)
|
||||
totalRideValue += rideValue * 2;
|
||||
}
|
||||
|
@ -802,4 +800,4 @@ void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
|
|||
}
|
||||
|
||||
*ebx = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,6 @@ void game_command_set_park_open(int *eax, int *ebx, int *ecx, int *edx, int *esi
|
|||
void game_command_remove_park_entrance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
void game_command_set_park_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp);
|
||||
|
||||
void sub_6EC847(int x, int y, int z0, int z1);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "../addresses.h"
|
||||
#include "../game.h"
|
||||
#include "../common.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../scenario.h"
|
||||
#include "climate.h"
|
||||
#include "fountain.h"
|
||||
#include "map.h"
|
||||
#include "park.h"
|
||||
#include "scenery.h"
|
||||
|
||||
void scenery_increase_age(int x, int y, rct_map_element *mapElement);
|
||||
|
||||
void scenery_update_tile(int x, int y)
|
||||
{
|
||||
rct_map_element *mapElement;
|
||||
|
||||
mapElement = map_get_first_element_at(x >> 5, y >> 5);
|
||||
do {
|
||||
if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY) {
|
||||
scenery_update_age(x, y, mapElement);
|
||||
} else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) {
|
||||
int additions = mapElement->properties.path.additions & 0x0F;
|
||||
if (additions != 0 && !(mapElement->properties.path.additions & 0x80)) {
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
sceneryEntry = g_pathBitSceneryEntries[additions - 1];
|
||||
if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER) {
|
||||
jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_WATER, x, y, mapElement);
|
||||
} else if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW) {
|
||||
jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_SNOW, x, y, mapElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!map_element_is_last_for_tile(mapElement++));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E33D9
|
||||
*/
|
||||
void scenery_update_age(int x, int y, rct_map_element *mapElement)
|
||||
{
|
||||
rct_map_element *mapElementAbove;
|
||||
rct_scenery_entry *sceneryEntry;
|
||||
|
||||
sceneryEntry = g_smallSceneryEntries[mapElement->properties.scenery.type];
|
||||
if (
|
||||
!(sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_CAN_BE_WATERED) ||
|
||||
(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, uint8) < WEATHER_RAIN) ||
|
||||
(mapElement->properties.scenery.age < 5)
|
||||
) {
|
||||
scenery_increase_age(x, y, mapElement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check map elements above, presumebly to see if map element is blocked from rain
|
||||
mapElementAbove = mapElement;
|
||||
while (!(mapElementAbove->flags & 7)) {
|
||||
mapElementAbove++;
|
||||
|
||||
switch (map_element_get_type(mapElementAbove)) {
|
||||
case MAP_ELEMENT_TYPE_SCENERY_MULTIPLE:
|
||||
case MAP_ELEMENT_TYPE_ENTRANCE:
|
||||
case MAP_ELEMENT_TYPE_PATH:
|
||||
map_invalidate_tile(x, y, mapElementAbove->base_height * 8, mapElementAbove->clearance_height * 8);
|
||||
scenery_increase_age(x, y, mapElement);
|
||||
return;
|
||||
case MAP_ELEMENT_TYPE_SCENERY:
|
||||
sceneryEntry = g_smallSceneryEntries[mapElementAbove->properties.scenery.type];
|
||||
if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) {
|
||||
scenery_increase_age(x, y, mapElement);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset age / water plant
|
||||
mapElement->properties.scenery.age = 0;
|
||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||
}
|
||||
|
||||
void scenery_increase_age(int x, int y, rct_map_element *mapElement)
|
||||
{
|
||||
if (mapElement->flags & SMALL_SCENERY_FLAG_ANIMATED)
|
||||
return;
|
||||
|
||||
if (mapElement->properties.scenery.age < 255) {
|
||||
mapElement->properties.scenery.age++;
|
||||
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
|
||||
}
|
||||
}
|
|
@ -36,26 +36,26 @@ typedef struct {
|
|||
} rct_small_scenery_entry;
|
||||
|
||||
typedef enum {
|
||||
SMALL_SCENERY_FLAG1 = (1 << 0), // 0x1
|
||||
SMALL_SCENERY_FLAG2 = (1 << 1), // 0x2
|
||||
SMALL_SCENERY_FLAG3 = (1 << 2), // 0x4
|
||||
SMALL_SCENERY_FLAG4 = (1 << 3), // 0x8
|
||||
SMALL_SCENERY_FLAG5 = (1 << 4), // 0x10
|
||||
SMALL_SCENERY_FLAG6 = (1 << 5), // 0x20
|
||||
SMALL_SCENERY_FLAG7 = (1 << 6), // 0x40
|
||||
SMALL_SCENERY_FLAG8 = (1 << 7), // 0x80
|
||||
SMALL_SCENERY_FLAG9 = (1 << 8), // 0x100
|
||||
SMALL_SCENERY_FLAG10 = (1 << 9), // 0x200
|
||||
SMALL_SCENERY_HAS_PRIMARY_COLOUR = (1 << 10), // 0x400
|
||||
SMALL_SCENERY_FLAG12 = (1 << 11), // 0x800
|
||||
SMALL_SCENERY_FLAG13 = (1 << 12), // 0x1000
|
||||
SMALL_SCENERY_FLAG14 = (1 << 13), // 0x2000
|
||||
SMALL_SCENERY_FLAG15 = (1 << 14), // 0x4000
|
||||
SMALL_SCENERY_FLAG16 = (1 << 15), // 0x8000
|
||||
SMALL_SCENERY_FLAG17 = (1 << 16), // 0x10000
|
||||
SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000
|
||||
SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000
|
||||
SMALL_SCENERY_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000
|
||||
SMALL_SCENERY_FLAG_FULL_TILE = (1 << 0), // 0x1
|
||||
SMALL_SCENERY_FLAG_VOFFSET_CENTRE = (1 << 1), // 0x2
|
||||
SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE = (1 << 2), // 0x4
|
||||
SMALL_SCENERY_FLAG4 = (1 << 3), // 0x8
|
||||
SMALL_SCENERY_FLAG_ANIMATED = (1 << 4), // 0x10
|
||||
SMALL_SCENERY_FLAG6 = (1 << 5), // 0x20
|
||||
SMALL_SCENERY_FLAG_CAN_BE_WATERED = (1 << 6), // 0x40
|
||||
SMALL_SCENERY_FLAG8 = (1 << 7), // 0x80
|
||||
SMALL_SCENERY_FLAG9 = (1 << 8), // 0x100
|
||||
SMALL_SCENERY_FLAG10 = (1 << 9), // 0x200
|
||||
SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR = (1 << 10), // 0x400
|
||||
SMALL_SCENERY_FLAG12 = (1 << 11), // 0x800
|
||||
SMALL_SCENERY_FLAG13 = (1 << 12), // 0x1000
|
||||
SMALL_SCENERY_FLAG_IS_CLOCK = (1 << 13), // 0x2000
|
||||
SMALL_SCENERY_FLAG15 = (1 << 14), // 0x4000
|
||||
SMALL_SCENERY_FLAG16 = (1 << 15), // 0x8000
|
||||
SMALL_SCENERY_FLAG17 = (1 << 16), // 0x10000
|
||||
SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000
|
||||
SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000
|
||||
SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000
|
||||
} SMALL_SCENERY_FLAGS;
|
||||
|
||||
typedef struct {
|
||||
|
@ -130,6 +130,11 @@ typedef struct {
|
|||
uint32 var_10A;
|
||||
} rct_scenery_set_entry;
|
||||
|
||||
enum {
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER = 1 << 4,
|
||||
PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW = 1 << 5
|
||||
};
|
||||
|
||||
#define g_smallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks)
|
||||
#define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks)
|
||||
#define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks)
|
||||
|
@ -138,5 +143,7 @@ typedef struct {
|
|||
#define g_scenerySetEntries ((rct_scenery_set_entry**)object_entry_groups[OBJECT_TYPE_SCENERY_SETS].chunks)
|
||||
|
||||
void init_scenery();
|
||||
void scenery_update_tile(int x, int y);
|
||||
void scenery_update_age(int x, int y, rct_map_element *mapElement);
|
||||
|
||||
#endif
|
|
@ -19,17 +19,34 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "../addresses.h"
|
||||
#include "../audio/audio.h"
|
||||
#include "../interface/viewport.h"
|
||||
#include "sprite.h"
|
||||
#include "../localisation/date.h"
|
||||
#include "../scenario.h"
|
||||
#include "fountain.h"
|
||||
#include "sprite.h"
|
||||
|
||||
enum {
|
||||
DUCK_STATE_FLY_TO_WATER,
|
||||
DUCK_STATE_SWIM,
|
||||
DUCK_STATE_DRINK,
|
||||
DUCK_STATE_DOUBLE_DRINK,
|
||||
DUCK_STATE_FLY_AWAY
|
||||
};
|
||||
|
||||
rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite);
|
||||
|
||||
static void duck_update_fly_to_water(rct_duck *duck);
|
||||
static void duck_update_swim(rct_duck *duck);
|
||||
static void duck_update_drink(rct_duck *duck);
|
||||
static void duck_update_double_drink(rct_duck *duck);
|
||||
static void duck_update_fly_away(rct_duck *duck);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006736C7
|
||||
*/
|
||||
void create_balloon(int x, int y, int z, int colour)
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl)
|
||||
{
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != NULL)
|
||||
|
@ -37,15 +54,94 @@ void create_balloon(int x, int y, int z, int colour)
|
|||
sprite->balloon.var_14 = 13;
|
||||
sprite->balloon.var_09 = 22;
|
||||
sprite->balloon.var_15 = 11;
|
||||
sprite->balloon.sprite_identifier = 2;
|
||||
sprite->balloon.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite_move(x, y, z, sprite);
|
||||
sprite->balloon.var_01 = 7;
|
||||
sprite->balloon.misc_identifier = SPRITE_MISC_BALLOON;
|
||||
sprite->balloon.var_26 = 0;
|
||||
sprite->balloon.colour = colour;
|
||||
sprite->balloon.var_24 = 0;
|
||||
sprite->balloon.popped = bl;
|
||||
}
|
||||
}
|
||||
|
||||
void balloon_pop(rct_balloon *balloon)
|
||||
{
|
||||
balloon->popped = 1;
|
||||
balloon->var_26 = 0;
|
||||
sound_play_panned(SOUND_BALLOON_POP, 0x8001, balloon->x, balloon->y, balloon->z);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067342C
|
||||
*/
|
||||
void balloon_update(rct_balloon *balloon)
|
||||
{
|
||||
invalidate_sprite((rct_sprite*)balloon);
|
||||
if (balloon->popped == 1) {
|
||||
balloon->var_26 += 256;
|
||||
if (balloon->var_26 >= 1280)
|
||||
sprite_remove((rct_sprite*)balloon);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int original_var26a = balloon->var_26a;
|
||||
balloon->var_26a += 85;
|
||||
if (original_var26a < 255 - 85)
|
||||
return;
|
||||
|
||||
balloon->var_26b++;
|
||||
sprite_move(balloon->x, balloon->y, balloon->z + 1, (rct_sprite*)balloon);
|
||||
|
||||
int maxZ = 1967 - ((balloon->x ^ balloon->y) & 31);
|
||||
if (balloon->z < maxZ)
|
||||
return;
|
||||
|
||||
balloon_pop(balloon);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E88ED
|
||||
*/
|
||||
void balloon_press(rct_balloon *balloon)
|
||||
{
|
||||
if (balloon->popped == 1)
|
||||
return;
|
||||
|
||||
uint32 random = scenario_rand();
|
||||
if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) {
|
||||
balloon_pop(balloon);
|
||||
return;
|
||||
}
|
||||
|
||||
sprite_move(
|
||||
balloon->x + ((random & 0x80000000) ? -6 : 6),
|
||||
balloon->y,
|
||||
balloon->z,
|
||||
(rct_sprite*)balloon
|
||||
);
|
||||
}
|
||||
|
||||
// rct2: 0x009A3B04
|
||||
static const rct_xy16 duck_move_offset[] = {
|
||||
{ -1, 0 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 0, -1 }
|
||||
};
|
||||
|
||||
// rct2: 0x0097F073
|
||||
static const uint8 duck_drink_animation[] = {
|
||||
1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 255
|
||||
};
|
||||
|
||||
// rct2: 0x0097F08C
|
||||
static const uint8 duck_double_drink_animation[] = {
|
||||
4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
|
||||
6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 0, 0, 0, 0, 255
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067440F
|
||||
|
@ -53,10 +149,9 @@ void create_balloon(int x, int y, int z, int colour)
|
|||
void create_duck(int targetX, int targetY)
|
||||
{
|
||||
rct_sprite* sprite = create_sprite(2);
|
||||
if (sprite != NULL)
|
||||
{
|
||||
sprite->duck.sprite_identifier = 2;
|
||||
sprite->duck.var_01 = 8;
|
||||
if (sprite != NULL) {
|
||||
sprite->duck.sprite_identifier = SPRITE_IDENTIFIER_MISC;
|
||||
sprite->duck.misc_identifier = SPRITE_MISC_DUCK;
|
||||
sprite->duck.var_14 = 9;
|
||||
sprite->duck.var_09 = 0xC;
|
||||
sprite->duck.var_15 = 9;
|
||||
|
@ -83,12 +178,264 @@ void create_duck(int targetX, int targetY)
|
|||
}
|
||||
sprite->duck.sprite_direction = direction << 3;
|
||||
sprite_move(targetX, targetY, 496, sprite);
|
||||
sprite->duck.var_48 = 0;
|
||||
sprite->duck.state = DUCK_STATE_FLY_TO_WATER;
|
||||
sprite->duck.var_26 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* rct2: 0x006EC473 */
|
||||
/**
|
||||
*
|
||||
* rct: 0x006740E8
|
||||
*/
|
||||
void duck_update(rct_duck *duck)
|
||||
{
|
||||
switch (duck->state) {
|
||||
case DUCK_STATE_FLY_TO_WATER:
|
||||
duck_update_fly_to_water(duck);
|
||||
break;
|
||||
case DUCK_STATE_SWIM:
|
||||
duck_update_swim(duck);
|
||||
break;
|
||||
case DUCK_STATE_DRINK:
|
||||
duck_update_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE_DOUBLE_DRINK:
|
||||
duck_update_double_drink(duck);
|
||||
break;
|
||||
case DUCK_STATE_FLY_AWAY:
|
||||
duck_update_fly_away(duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void duck_invalidate(rct_duck *duck)
|
||||
{
|
||||
sub_6EC60B((rct_sprite*)duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674108
|
||||
*/
|
||||
static void duck_update_fly_to_water(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int manhattanDistance = abs(duck->target_x - duck->x) + abs(duck->target_y - duck->y);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int y = duck->y + duck_move_offset[direction].y;
|
||||
int manhattanDistanceN = abs(duck->target_x - x) + abs(duck->target_y - y);
|
||||
|
||||
rct_map_element *mapElement = map_get_surface_element_at(duck->target_x >> 5, duck->target_y >> 5);
|
||||
int waterHeight = mapElement->properties.surface.terrain & 0x1F;
|
||||
if (waterHeight == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
waterHeight <<= 4;
|
||||
int z = abs(duck->z - waterHeight);
|
||||
|
||||
if (manhattanDistanceN <= manhattanDistance) {
|
||||
if (z > manhattanDistanceN) {
|
||||
z = duck->z - 2;
|
||||
if (waterHeight >= duck->z)
|
||||
z += 4;
|
||||
|
||||
duck->var_26 = 1;
|
||||
} else {
|
||||
z = duck->z;
|
||||
}
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
} else {
|
||||
if (z > 4) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674282
|
||||
*/
|
||||
static void duck_update_swim(rct_duck *duck)
|
||||
{
|
||||
if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3)
|
||||
return;
|
||||
|
||||
uint32 randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) < 0x666) {
|
||||
if (randomNumber & 0x80000000) {
|
||||
duck->state = DUCK_STATE_DOUBLE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_double_drink(duck);
|
||||
} else {
|
||||
duck->state = DUCK_STATE_DRINK;
|
||||
duck->var_26 = -1;
|
||||
duck_update_drink(duck);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int currentMonth = date_get_month(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16));
|
||||
if (currentMonth >= MONTH_SEPTEMBER && (randomNumber >> 16) < 218) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck_invalidate(duck);
|
||||
int landZ = map_element_height(duck->x, duck->y);
|
||||
int waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z < landZ || waterZ == 0) {
|
||||
duck->state = DUCK_STATE_FLY_AWAY;
|
||||
duck_update_fly_away(duck);
|
||||
return;
|
||||
}
|
||||
|
||||
duck->z = waterZ;
|
||||
randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) <= 0xAAA) {
|
||||
randomNumber >>= 16;
|
||||
duck->sprite_direction = randomNumber & 0x18;
|
||||
}
|
||||
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + duck_move_offset[direction].x;
|
||||
int y = duck->y + duck_move_offset[direction].y;
|
||||
landZ = map_element_height(x, y);
|
||||
waterZ = (landZ >> 16) & 0xFFFF;
|
||||
landZ &= 0xFFFF;
|
||||
|
||||
if (duck->z < landZ || duck->z != waterZ)
|
||||
return;
|
||||
|
||||
sprite_move(x, y, waterZ, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674357
|
||||
*/
|
||||
static void duck_update_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00674372
|
||||
*/
|
||||
static void duck_update_double_drink(rct_duck *duck)
|
||||
{
|
||||
duck->var_26++;
|
||||
if (duck_double_drink_animation[duck->var_26] == 255) {
|
||||
duck->state = DUCK_STATE_SWIM;
|
||||
duck->var_26 = 0;
|
||||
duck_update_swim(duck);
|
||||
} else {
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x0067438D
|
||||
*/
|
||||
static void duck_update_fly_away(rct_duck *duck)
|
||||
{
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3)
|
||||
return;
|
||||
|
||||
duck->var_26++;
|
||||
if (duck->var_26 >= 6)
|
||||
duck->var_26 = 0;
|
||||
|
||||
duck_invalidate(duck);
|
||||
int direction = duck->sprite_direction >> 3;
|
||||
int x = duck->x + (duck_move_offset[direction].x * 2);
|
||||
int y = duck->y + (duck_move_offset[direction].y * 2);
|
||||
if (x < 0 || y < 0 || x >= (32 * 256) || y >= (32 * 256)) {
|
||||
sprite_remove((rct_sprite*)duck);
|
||||
return;
|
||||
}
|
||||
|
||||
int z = z = min(duck->z + 2, 496);
|
||||
sprite_move(x, y, z, (rct_sprite*)duck);
|
||||
duck_invalidate(duck);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x006E895D
|
||||
*/
|
||||
void duck_press(rct_duck *duck)
|
||||
{
|
||||
sound_play_panned(SOUND_QUACK, 0x8001, duck->x, duck->y, duck->z);
|
||||
}
|
||||
|
||||
static const rct_xy16 _moneyEffectMoveOffset[] = {
|
||||
{ 1, -1 },
|
||||
{ 1, 1 },
|
||||
{ -1, 1 },
|
||||
{ -1, -1 }
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00673232
|
||||
*/
|
||||
void money_effect_update(rct_money_effect *moneyEffect)
|
||||
{
|
||||
invalidate_sprite((rct_sprite*)moneyEffect);
|
||||
moneyEffect->wiggle++;
|
||||
if (moneyEffect->wiggle >= 22)
|
||||
moneyEffect->wiggle = 0;
|
||||
|
||||
moneyEffect->move_delay++;
|
||||
if (moneyEffect->move_delay < 2)
|
||||
return;
|
||||
|
||||
moneyEffect->move_delay = 0;
|
||||
int x = moneyEffect->x + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].x;
|
||||
int y = moneyEffect->y + _moneyEffectMoveOffset[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)].y;
|
||||
int z = moneyEffect->z;
|
||||
sprite_move(x, y, z, (rct_sprite*)moneyEffect);
|
||||
|
||||
moneyEffect->num_movements++;
|
||||
if (moneyEffect->num_movements < 55)
|
||||
return;
|
||||
|
||||
sprite_remove((rct_sprite*)moneyEffect);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* rct2: 0x006EC473
|
||||
*/
|
||||
void invalidate_sprite(rct_sprite* sprite){
|
||||
if (sprite->unknown.sprite_left == (sint16)0x8000) return;
|
||||
|
||||
|
@ -130,6 +477,15 @@ void invalidate_sprite(rct_sprite* sprite){
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to invalidate sprite...
|
||||
* rct2: 0x006EC60B
|
||||
*/
|
||||
void sub_6EC60B(rct_sprite* sprite)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006EC60B, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* rct2: 0x0069EB13
|
||||
|
@ -198,14 +554,14 @@ void reset_0x69EBE4(){
|
|||
}
|
||||
uint16 ax = RCT2_ADDRESS(0xF1EF60,uint16)[edi];
|
||||
RCT2_ADDRESS(0xF1EF60,uint16)[edi] = spr->unknown.sprite_index;
|
||||
spr->unknown.var_02 = ax;
|
||||
spr->unknown.next_in_quadrant = ax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rct2: 0x0069EC6B
|
||||
* bl: if bl & 2 > 0, the sprite ends up in the FLOATING_TEXT linked list.
|
||||
* bl: if bl & 2 > 0, the sprite ends up in the MISC linked list.
|
||||
*/
|
||||
rct_sprite *create_sprite(uint8 bl)
|
||||
{
|
||||
|
@ -220,7 +576,7 @@ rct_sprite *create_sprite(uint8 bl)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
linkedListTypeOffset = SPRITE_LINKEDLIST_OFFSET_FLOATING_TEXT;
|
||||
linkedListTypeOffset = SPRITE_LINKEDLIST_OFFSET_MISC;
|
||||
}
|
||||
else if (RCT2_GLOBAL(0x13573C8, uint16) <= 0)
|
||||
{
|
||||
|
@ -235,14 +591,14 @@ rct_sprite *create_sprite(uint8 bl)
|
|||
sprite->y = SPRITE_LOCATION_NULL;
|
||||
sprite->z = 0;
|
||||
sprite->name_string_idx = 0;
|
||||
sprite->var_14 = 0x10;
|
||||
sprite->var_09 = 0x14;
|
||||
sprite->var_15 = 0x8;
|
||||
sprite->pad_0C[0] = 0x0;
|
||||
sprite->sprite_width = 0x10;
|
||||
sprite->sprite_height_negative = 0x14;
|
||||
sprite->sprite_height_positive = 0x8;
|
||||
sprite->var_0C = 0;
|
||||
sprite->sprite_left = SPRITE_LOCATION_NULL;
|
||||
|
||||
sprite->var_02 = RCT2_GLOBAL(0xF3EF60, uint16);
|
||||
RCT2_GLOBAL(0xF3EF60, uint16) = sprite->sprite_index;
|
||||
sprite->next_in_quadrant = RCT2_ADDRESS(0xF1EF60, uint16)[0x10000];
|
||||
RCT2_ADDRESS(0xF1EF60, uint16)[0x10000] = sprite->sprite_index;
|
||||
|
||||
return (rct_sprite*)sprite;
|
||||
}
|
||||
|
@ -299,13 +655,59 @@ void move_sprite_to_list(rct_sprite *sprite, uint8 cl)
|
|||
++(RCT2_GLOBAL(0x13573C8 + cl, uint16));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x006731CD
|
||||
*/
|
||||
void sprite_misc_update(rct_sprite *sprite)
|
||||
{
|
||||
switch (sprite->unknown.misc_identifier) {
|
||||
case SPRITE_MISC_0:
|
||||
RCT2_CALLPROC_X(0x00673200, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
break;
|
||||
case SPRITE_MISC_MONEY_EFFECT:
|
||||
money_effect_update(&sprite->money_effect);
|
||||
break;
|
||||
case SPRITE_MISC_2:
|
||||
RCT2_CALLPROC_X(0x00673298, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
break;
|
||||
case SPRITE_MISC_3:
|
||||
RCT2_CALLPROC_X(0x00673385, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
break;
|
||||
case SPRITE_MISC_4:
|
||||
RCT2_CALLPROC_X(0x0067339D, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
break;
|
||||
case SPRITE_MISC_5:
|
||||
RCT2_CALLPROC_X(0x006733B4, 0, 0, 0, 0, (int)sprite, 0, 0);
|
||||
break;
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_WATER:
|
||||
case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW:
|
||||
jumping_fountain_update(&sprite->jumping_fountain);
|
||||
break;
|
||||
case SPRITE_MISC_BALLOON:
|
||||
balloon_update(&sprite->balloon);
|
||||
break;
|
||||
case SPRITE_MISC_DUCK:
|
||||
duck_update(&sprite->duck);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct: 0x00672AA4
|
||||
*/
|
||||
void texteffect_update_all()
|
||||
void sprite_misc_update_all()
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x00672AA4);
|
||||
rct_sprite *sprite;
|
||||
uint16 spriteIndex;
|
||||
|
||||
spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_MISC, uint16);
|
||||
while (spriteIndex != SPRITE_INDEX_NULL) {
|
||||
sprite = &g_sprite_list[spriteIndex];
|
||||
spriteIndex = sprite->unknown.next;
|
||||
sprite_misc_update(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,14 +736,14 @@ void sprite_move(int x, int y, int z, rct_sprite* sprite){
|
|||
uint16* sprite_idx = &RCT2_ADDRESS(0xF1EF60, uint16)[current_position];
|
||||
rct_sprite* sprite2 = &g_sprite_list[*sprite_idx];
|
||||
while (sprite != sprite2){
|
||||
sprite_idx = &sprite2->unknown.var_02;
|
||||
sprite_idx = &sprite2->unknown.next_in_quadrant;
|
||||
sprite2 = &g_sprite_list[*sprite_idx];
|
||||
}
|
||||
*sprite_idx = sprite->unknown.var_02;
|
||||
*sprite_idx = sprite->unknown.next_in_quadrant;
|
||||
|
||||
int temp_sprite_idx = RCT2_ADDRESS(0xF1EF60, uint16)[new_position];
|
||||
RCT2_ADDRESS(0xF1EF60, uint16)[new_position] = sprite->unknown.sprite_index;
|
||||
sprite->unknown.var_02 = temp_sprite_idx;
|
||||
sprite->unknown.next_in_quadrant = temp_sprite_idx;
|
||||
}
|
||||
|
||||
if (x == 0x8000){
|
||||
|
@ -371,24 +773,15 @@ void sprite_move(int x, int y, int z, rct_sprite* sprite){
|
|||
break;
|
||||
}
|
||||
|
||||
sprite->unknown.sprite_left = new_x - sprite->unknown.var_14;
|
||||
sprite->unknown.sprite_right = new_x + sprite->unknown.var_14;
|
||||
sprite->unknown.sprite_top = new_y - sprite->unknown.var_09;
|
||||
sprite->unknown.sprite_bottom = new_y + sprite->unknown.var_15;
|
||||
sprite->unknown.sprite_left = new_x - sprite->unknown.sprite_width;
|
||||
sprite->unknown.sprite_right = new_x + sprite->unknown.sprite_width;
|
||||
sprite->unknown.sprite_top = new_y - sprite->unknown.sprite_height_negative;
|
||||
sprite->unknown.sprite_bottom = new_y + sprite->unknown.sprite_height_positive;
|
||||
sprite->unknown.x = x;
|
||||
sprite->unknown.y = y;
|
||||
sprite->unknown.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E88D7
|
||||
*/
|
||||
void balloon_pop(rct_sprite *sprite)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006E88D7, 0, 0, 0, (int)sprite, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069EDB6
|
||||
|
|
|
@ -32,33 +32,36 @@
|
|||
enum SPRITE_IDENTIFIER{
|
||||
SPRITE_IDENTIFIER_VEHICLE = 0,
|
||||
SPRITE_IDENTIFIER_PEEP = 1,
|
||||
SPRITE_IDENTIFIER_FLOATING_TEXT = 2,
|
||||
SPRITE_IDENTIFIER_MISC = 2,
|
||||
SPRITE_IDENTIFIER_LITTER = 3,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SPRITE_LINKEDLIST_OFFSET_VEHICLE = 2,
|
||||
SPRITE_LINKEDLIST_OFFSET_PEEP = 4,
|
||||
SPRITE_LINKEDLIST_OFFSET_FLOATING_TEXT = 6,
|
||||
SPRITE_LINKEDLIST_OFFSET_FLOATING_LITTER = 8,
|
||||
SPRITE_LINKEDLIST_OFFSET_MISC = 6,
|
||||
SPRITE_LINKEDLIST_OFFSET_LITTER = 8,
|
||||
SPRITE_LINKEDLIST_OFFSET_UNKNOWN = 10
|
||||
} SPRITE_LINKEDLIST_OFFSET;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 pad_01;
|
||||
uint16 var_02;
|
||||
uint8 misc_identifier; // 0x01
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09;
|
||||
// Height from center of sprite to bottom
|
||||
uint8 sprite_height_negative; // 0x09
|
||||
uint16 sprite_index; // 0x0A
|
||||
uint8 pad_0C[2];
|
||||
uint16 var_0C;
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 var_14; // 0x14
|
||||
uint8 var_15; // 0x15
|
||||
// Width from center of sprite to edge
|
||||
uint8 sprite_width; // 0x14
|
||||
// Height from center of sprite to top
|
||||
uint8 sprite_height_positive; // 0x15
|
||||
sint16 sprite_left; // 0x16
|
||||
sint16 sprite_top; // 0x18
|
||||
sint16 sprite_right; // 0x1A
|
||||
|
@ -73,46 +76,63 @@ typedef struct {
|
|||
} rct_unk_sprite;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 var_01; // 0x01
|
||||
uint16 var_02; // 0x02
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 pad_09;
|
||||
uint16 sprite_index; // 0x0A
|
||||
uint8 pad_0B[0x19];
|
||||
uint16 pad_0C;
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 pad_14[0x10];
|
||||
uint32 var_24;
|
||||
} rct_litter;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 var_01; // 0x01
|
||||
uint16 var_02; // 0x02
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 misc_identifier; // 0x01
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09; // 0x09
|
||||
uint8 pad_0A[0xA];
|
||||
uint16 var_0A;
|
||||
uint8 pad_0C[0x2];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 var_14; // 0x14
|
||||
uint8 var_15; // 0x15
|
||||
uint8 pad_16[0xE];
|
||||
uint8 var_24; // 0x24
|
||||
uint8 pad_25;
|
||||
uint16 var_26; // 0x26
|
||||
uint16 popped; // 0x24
|
||||
union {
|
||||
uint16 var_26;
|
||||
struct {
|
||||
uint8 var_26a;
|
||||
uint8 var_26b;
|
||||
};
|
||||
};
|
||||
uint8 pad_28[4];
|
||||
uint8 colour; // 0x2C
|
||||
} rct_balloon;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 var_01; // 0x01
|
||||
uint16 var_02; // 0x02
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 misc_identifier; // 0x01
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09; // 0x09
|
||||
uint8 pad_0A[0xA];
|
||||
uint16 var_0A;
|
||||
uint8 pad_0C[0x2];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 var_14; // 0x14
|
||||
uint8 var_15; // 0x15
|
||||
uint8 pad_16[0x8];
|
||||
|
@ -123,9 +143,61 @@ typedef struct {
|
|||
sint16 target_x; // 0x30
|
||||
sint16 target_y; // 0x32
|
||||
uint8 pad_34[0x14];
|
||||
uint8 var_48; // 0x48
|
||||
uint8 state; // 0x48
|
||||
} rct_duck;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 misc_identifier; // 0x01
|
||||
uint16 next_in_quadrant; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09;
|
||||
uint8 pad_0A[0x4];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 var_14;
|
||||
uint8 var_15;
|
||||
uint8 pad_16[0x8];
|
||||
uint8 sprite_direction; // 0x1E
|
||||
uint8 pad_1F[0x7];
|
||||
union {
|
||||
uint16 var_26;
|
||||
struct {
|
||||
uint8 var_26a;
|
||||
uint8 var_26b;
|
||||
};
|
||||
};
|
||||
uint8 pad_28[0x6];
|
||||
uint8 var_2E;
|
||||
uint8 flags;
|
||||
sint16 target_x; // 0x30
|
||||
sint16 target_y; // 0x32
|
||||
uint8 pad_34[0x12];
|
||||
uint16 iteration; // 0x46
|
||||
} rct_jumping_fountain;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 misc_identifier; // 0x01
|
||||
uint16 var_02; // 0x02
|
||||
uint16 next; // 0x04
|
||||
uint16 previous; // 0x06
|
||||
uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_...
|
||||
uint8 var_09;
|
||||
uint8 pad_0A[0x4];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 pad_14[0x10];
|
||||
uint16 move_delay; // 0x24
|
||||
uint16 num_movements; // 0x26
|
||||
uint8 pad_28[0x1E];
|
||||
uint16 wiggle; // 0x46
|
||||
} rct_money_effect;
|
||||
|
||||
/**
|
||||
* Sprite structure.
|
||||
* size: 0x0100
|
||||
|
@ -138,21 +210,38 @@ typedef union {
|
|||
rct_vehicle vehicle;
|
||||
rct_balloon balloon;
|
||||
rct_duck duck;
|
||||
rct_jumping_fountain jumping_fountain;
|
||||
rct_money_effect money_effect;
|
||||
} rct_sprite;
|
||||
|
||||
enum {
|
||||
SPRITE_MISC_0,
|
||||
SPRITE_MISC_MONEY_EFFECT,
|
||||
SPRITE_MISC_2, // (related to vehicle crash, probably crash particles)
|
||||
SPRITE_MISC_3, // (related to vehicle crash, probably crash particles)
|
||||
SPRITE_MISC_4, // (related to vehicle crash, probably crash particles)
|
||||
SPRITE_MISC_5, // (related to vehicle crash, probably crash particles)
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_WATER,
|
||||
SPRITE_MISC_BALLOON,
|
||||
SPRITE_MISC_DUCK,
|
||||
SPRITE_MISC_JUMPING_FOUNTAIN_SNOW
|
||||
};
|
||||
|
||||
// rct2: 0x010E63BC
|
||||
extern rct_sprite* g_sprite_list;
|
||||
|
||||
void create_balloon(int x, int y, int z, int colour);
|
||||
void create_balloon(int x, int y, int z, int colour, uint8 bl);
|
||||
void balloon_press(rct_balloon *balloon);
|
||||
void create_duck(int targetX, int targetY);
|
||||
void duck_press(rct_duck *duck);
|
||||
rct_sprite *create_sprite(uint8 bl);
|
||||
void reset_sprite_list();
|
||||
void reset_0x69EBE4();
|
||||
void move_sprite_to_list(rct_sprite *sprite, uint8 cl);
|
||||
void texteffect_update_all();
|
||||
void sprite_misc_update_all();
|
||||
void sprite_move(int x, int y, int z, rct_sprite* sprite);
|
||||
void balloon_pop(rct_sprite *sprite);
|
||||
void invalidate_sprite(rct_sprite *sprite);
|
||||
void sub_6EC60B(rct_sprite* sprite);
|
||||
void sprite_remove(rct_sprite *sprite);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue