Merge branch 'ride-update'

Conflicts:
	src/world/map.c
This commit is contained in:
IntelOrca 2014-11-04 19:01:59 +00:00
commit 0104042640
27 changed files with 1780 additions and 436 deletions

View File

@ -89,6 +89,7 @@
<ClCompile Include="..\src\ride\ride.c" />
<ClCompile Include="..\src\ride\ride_data.c" />
<ClCompile Include="..\src\ride\ride_ratings.c" />
<ClCompile Include="..\src\ride\station.c" />
<ClCompile Include="..\src\ride\track.c" />
<ClCompile Include="..\src\ride\vehicle.c" />
<ClCompile Include="..\src\scenario.c" />
@ -190,6 +191,7 @@
<ClInclude Include="..\src\ride\ride.h" />
<ClInclude Include="..\src\ride\ride_data.h" />
<ClInclude Include="..\src\ride\ride_ratings.h" />
<ClInclude Include="..\src\ride\station.h" />
<ClInclude Include="..\src\ride\track.h" />
<ClInclude Include="..\src\ride\vehicle.h" />
<ClInclude Include="..\src\scenario.h" />

View File

@ -381,7 +381,6 @@
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\src\drawing\rain.c">
<Filter>Source\Drawing</Filter>
</ClCompile>
@ -434,6 +433,10 @@
<ClCompile Include="..\src\windows\sign.c">
<Filter>Source\Windows</Filter>
</ClCompile>
<ClCompile Include="..\lib\libspeex\resample.c;..\lib\lodepng\lodepng.c" />
<ClCompile Include="..\src\ride\station.c">
<Filter>Source\Ride</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\management\award.h">
@ -631,5 +634,8 @@
<ClInclude Include="..\src\world\banner.h">
<Filter>Source\World</Filter>
</ClInclude>
<ClInclude Include="..\src\ride\station.h">
<Filter>Source\Ride</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -493,7 +493,7 @@ static void RCT2_CALLPROC_EBPSAFE(int address)
/* Returns the flags register
*
*Flags register is as follows:
*0bSZ0A_0P0C_0000_00000
*0bSZ0A_0P0C_0000_0000
*S = Signed flag
*Z = Zero flag
*C = Carry flag

View File

@ -1836,35 +1836,6 @@ void stop_vehicle_sounds()
}
}
/**
* Update zoom based volume attenuation for ride music and clear music list
* rct2: 0x006BC348
*/
void sub_6BC348()
{
RCT2_GLOBAL(0x009AF42C, rct_music_info*) = &RCT2_GLOBAL(0x009AF430, rct_music_info);
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = (rct_viewport*)-1;
rct_window* window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*);
while (1) {
window--;
if (window < RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) {
break;
}
if (window->viewport && window->viewport->flags & VIEWPORT_FLAG_SOUND_ON) {
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = window->viewport;
RCT2_GLOBAL(0x00F438A8, rct_window*) = window;
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 0;
if (window->viewport->zoom) {
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 30;
if (window->viewport->zoom != 1) {
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 60;
}
}
return;
}
}
}
/**
*
* rct2: 0x006BC3AC
@ -1874,17 +1845,32 @@ void sub_6BC348()
* @param x (ax)
* @param y (cx)
* @param z (dx)
* @param bx
* @param ebp
* @param di
* @returns ebp register
* @param sampleRate (di)
* @param rideIndex (bl)
* @param position (ebp)
* @param tuneId (bh)
* @returns new position (ebp)
*/
int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint16 bx, uint32 ebp, uint16 di)
int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint16 sampleRate, uint32 position, uint8 *tuneId)
{
uint8 bl = LOBYTE(bx);
uint8 bh = HIBYTE(bx);
{
int a_eax, a_ebx, a_ecx, a_edx, a_esi, a_edi, a_ebp;
a_eax = x;
a_ebx = (*tuneId << 8) | rideIndex;
a_ecx = y;
a_edx = z;
a_edi = sampleRate;
a_ebp = position;
RCT2_CALLFUNC_X(0x006BC3AC, &a_eax, &a_ebx, &a_ecx, &a_edx, &a_esi, &a_edi, &a_ebp);
*tuneId = (a_ebx >> 8) & 0xFF;
return a_ebp;
}
// TODO fix / bh needs returning too!
if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !RCT2_GLOBAL(0x009AF59C, uint8) && RCT2_GLOBAL(0x00F438A4, rct_viewport*) != (rct_viewport*)-1) {
RCT2_GLOBAL(0x009AF47C, uint16) = di;
RCT2_GLOBAL(0x009AF47C, uint16) = sampleRate;
sint16 v11;
sint16 v12;
switch (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint32)) {
@ -1988,12 +1974,12 @@ int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint16 bx, uint32 ebp, uint16 di)
rct_music_info2* music_info2 = &RCT2_GLOBAL(0x009AF46C, rct_music_info2);
int channel = 0;
uint32 a1;
while (music_info2->id != bl && music_info2->var_1 != bh) {
while (music_info2->id != rideIndex && music_info2->var_1 != *tuneId) {
music_info2++;
channel++;
if (channel >= 2) {
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[bh];
a1 = ebp + music_info3->var_4;
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[*tuneId];
a1 = position + music_info3->var_4;
goto label51;
}
}
@ -2007,11 +1993,11 @@ int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint16 bx, uint32 ebp, uint16 di)
a1 = sub_401B46(channel);
RCT2_GLOBAL(0x014241BC, uint32) = 0;
label51:
if (a1 < RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[bh].var_0) {
if (a1 < RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[*tuneId].var_0) {
rct_music_info* music_info = RCT2_GLOBAL(0x009AF42C, rct_music_info*);
if (music_info < (rct_music_info*)0x009AF46C/*music_info list end*/) {
music_info->id = bl;
music_info->var_1 = bh;
music_info->id = rideIndex;
music_info->var_1 = *tuneId;
music_info->offset = a1;
music_info->volume = v32;
music_info->pan = panx;
@ -2022,16 +2008,16 @@ int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint16 bx, uint32 ebp, uint16 di)
} else {
uint32 eax;
label58:
eax = ebp;
ebp = bh;
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[bh];
eax = position;
position = *tuneId;
rct_music_info3* music_info3 = &RCT2_GLOBAL(0x009AF1C8, rct_music_info3*)[*tuneId];
eax += music_info3->var_4;
if (eax < music_info3->var_0) {
ebp = eax;
position = eax;
}
}
}
return ebp;
return position;
}
/**

View File

@ -213,8 +213,8 @@ void audio_close();
void pause_sounds();
void unpause_sounds();
void stop_vehicle_sounds();
void sub_6BC348();
void sub_6BC6D8();
int sub_6BC3AC(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint16 sampleRate, uint32 position, uint8 *tuneId);
// 0x009AF59C probably does the same job
// once it's confirmed and calls in pause_sounds() are reversed, it can be used instead of this

View File

@ -1792,4 +1792,39 @@ void sub_6EA73F()
window_invalidate_pressed_image_buttons(w);
RCT2_CALLPROC_X(w->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)w, 0, 0);
}
}
/**
* Update zoom based volume attenuation for ride music and clear music list.
* rct2: 0x006BC348
*/
void window_update_viewport_ride_music()
{
rct_viewport *viewport;
rct_window *w;
RCT2_GLOBAL(0x009AF42C, rct_music_info*) = (rct_music_info*)0x009AF430;
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = (rct_viewport*)-1;
for (w = RCT2_LAST_WINDOW; w >= g_window_list; w--) {
viewport = w->viewport;
if (viewport == NULL || !(viewport->flags & VIEWPORT_FLAG_SOUND_ON))
continue;
RCT2_GLOBAL(0x00F438A4, rct_viewport*) = viewport;
RCT2_GLOBAL(0x00F438A8, rct_window*) = w;
switch (viewport->zoom) {
case 0:
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 0;
break;
case 1:
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 30;
break;
default:
RCT2_GLOBAL(RCT2_ADDRESS_VOLUME_ADJUST_ZOOM, uint8) = 60;
break;
}
break;
}
}

View File

@ -463,6 +463,8 @@ void tool_cancel();
void window_close_construction_windows();
void window_update_viewport_ride_music();
// Open window functions
void window_main_open();
void window_resize_gui(int width, int height);

View File

@ -558,11 +558,11 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum
*argument_2 = 0;
break;
case PEEP_STATE_ANSWERING:
if (peep->pad_2C == 0){
if (peep->var_2C == 0){
*argument_1 = STR_WALKING;
*argument_2 = 0;
}
else if (peep->pad_2C == 1){
else if (peep->var_2C == 1){
*argument_1 = STR_ANSWERING_RADIO_CALL;
*argument_2 = 0;
}

View File

@ -304,7 +304,7 @@ typedef struct {
typedef struct {
uint8 sprite_identifier; // 0x00
uint8 pad_01;
uint8 var_01;
uint16 var_02; // 0x02
uint16 next; // 0x04
uint16 previous; // 0x06
@ -329,7 +329,7 @@ typedef struct {
uint16 next_z; // 0x28
uint8 var_2A;
uint8 state; // 0x2B
uint8 pad_2C;
uint8 var_2C;
uint8 sprite_type; // 0x2D
uint8 type; // 0x2E
union{
@ -363,7 +363,7 @@ typedef struct {
uint8 photo4_ride_ref; // 0x5E
uint8 pad_5F[0x09]; // 0x5C
uint8 current_ride; // 0x68
uint8 pad_69;
uint8 current_ride_station; // 0x69
uint8 current_train; // 0x6A
uint8 current_car; // 0x6B
uint8 current_seat; // 0x6C

View File

@ -290,3 +290,34 @@ void sub_6C0C3F()
}
}
}
int staff_is_location_in_patrol_area(rct_peep *peep, int x, int y)
{
// Patrol quads are stored in a bit map (8 patrol quads per byte)
// Each patrol quad is 4x4
// Therefore there are in total 64 x 64 patrol quads in the 256 x 256 map
int patrolOffset = peep->staff_id * (64 * 64 / 8);
int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1);
int mask = 1 << (patrolIndex & 0x1F);
int base = patrolIndex >> 5;
uint32 *patrolBits = (uint32*)(0x013B0E72 + patrolOffset + (base * 4));
return (*patrolBits & mask) != 0;
}
/**
*
* rct2: 0x006C0905
*/
int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y)
{
// Check if location is in the park
if (!sub_664F72(x, y, mechanic->z))
return 0;
// Check if mechanic has patrol area
if (!(RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[mechanic->staff_id] & 2))
return 1;
return staff_is_location_in_patrol_area(mechanic, x, y);
}

View File

@ -22,6 +22,7 @@
#define _STAFF_H_
#include "../common.h"
#include "peep.h"
#define STAFF_MAX_COUNT 0xC8
#define STAFF_TYPE_COUNT 0x04
@ -45,5 +46,6 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
void update_staff_colour(uint8 staff_type, uint16 color);
uint16 hire_new_staff_member(uint8 staff_type);
void sub_6C0C3F();
int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -97,7 +97,7 @@ typedef struct {
uint16 station_starts[4]; // 0x052
uint8 station_heights[4]; // 0x05A
uint8 pad_05E[0x4];
uint8 var_062[4];
uint8 station_depart[4]; // 0x062
uint8 pad_066[0x4];
uint16 entrances[4]; // 0x06A
uint16 exits[4]; // 0x072
@ -114,7 +114,11 @@ typedef struct {
uint8 var_0CD;
uint8 min_waiting_time; // 0x0CE
uint8 max_waiting_time; // 0x0CF
uint8 var_0D0;
union {
uint8 var_0D0;
uint8 time_limit; // 0x0D0
uint8 num_laps; // 0x0D0
};
uint8 pad_0D1[0x3];
uint8 measurement_index; // 0x0D4
uint8 var_0D5;
@ -178,20 +182,26 @@ typedef struct {
uint16 var_158;
uint8 pad_15A;
uint8 num_riders; // 0x15B
uint8 var_15C;
uint8 music_tune_id; // 0x15C
uint8 var_15D;
uint16 maze_tiles; // 0x15E
union {
uint16 slide_peep; // 0x15E
uint16 maze_tiles; // 0x15E
};
uint8 pad_160[0x16];
uint8 var_176;
uint8 pad_177[0x9];
sint16 build_date; // 0x180
money16 upkeep_cost; // 0x182
uint16 race_winner; // 0x184
uint8 pad_186[0x06];
uint8 var_18C;
uint8 pad_186[0x02];
uint32 music_position; // 0x188
uint8 breakdown_reason_pending; // 0x18C
uint8 mechanic_status; // 0x18D
uint16 mechanic; // 0x18E
uint8 pad_190[0x03];
uint8 inspection_station; // 0x190
uint8 broken_vehicle; // 0x191
uint8 broken_car; // 0x192
uint8 breakdown_reason; // 0x193
money16 price_secondary; // 0x194
uint16 var_196;
@ -200,9 +210,18 @@ typedef struct {
uint8 var_199;
uint8 inspection_interval; // 0x19A
uint8 last_inspection; // 0x19B
uint8 pad_19C[0x8];
uint8 var_19C;
uint8 var_19D;
uint8 var_19E;
uint8 var_19F;
uint8 var_1A0;
uint8 var_1A1;
uint8 var_1A2;
uint8 var_1A3;
uint32 var_1A4;
uint8 pad_1A8[6];
uint8 pad_1A8[4];
uint8 var_1AC;
uint8 var_1AD;
uint8 var_1AE;
uint8 connected_message_throttle; // 0x1AF
money32 income_per_hour; // 0x1B0
@ -261,8 +280,9 @@ enum {
RIDE_LIFECYCLE_NO_RAW_STATS = 1 << 3,
RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING = 1 << 4,
RIDE_LIFECYCLE_ON_RIDE_PHOTO = 1 << 5,
RIDE_LIFECYCLE_BREAKDOWN_PENDING = 1 << 6,
RIDE_LIFECYCLE_BROKEN_DOWN = 1 << 7,
RIDE_LIFECYCLE_DUE_INSPECTION = 1 << 8,
RIDE_LIFECYCLE_CRASHED = 1 << 10,
RIDE_LIFECYCLE_11 = 1 << 11,
@ -480,9 +500,11 @@ enum {
};
enum {
RIDE_MECHANIC_STATUS_CALLING = 1,
RIDE_MECHANIC_STATUS_HEADING = 2,
RIDE_MECHANIC_STATUS_FIXING = 3,
RIDE_MECHANIC_STATUS_UNDEFINED,
RIDE_MECHANIC_STATUS_CALLING,
RIDE_MECHANIC_STATUS_HEADING,
RIDE_MECHANIC_STATUS_FIXING,
RIDE_MECHANIC_STATUS_4
};
enum {
@ -522,6 +544,16 @@ enum {
RIDE_ENTRANCE_STYLE_SPACE
};
enum {
RIDE_INSPECTION_EVERY_10_MINUTES,
RIDE_INSPECTION_EVERY_20_MINUTES,
RIDE_INSPECTION_EVERY_30_MINUTES,
RIDE_INSPECTION_EVERY_45_MINUTES,
RIDE_INSPECTION_EVERY_HOUR,
RIDE_INSPECTION_EVERY_2_HOURS,
RIDE_INSPECTION_NEVER
};
typedef struct {
uint8 main;
uint8 additional;
@ -545,6 +577,9 @@ enum {
#define MAX_RIDE_MEASUREMENTS 8
#define RIDE_RELIABILITY_UNDEFINED 0xFFFF
#define STATION_DEPART_FLAG (1 << 7)
#define STATION_DEPART_MASK (~STATION_DEPART_FLAG)
// rct2: 0x009ACFA4
rct_ride_type **gRideTypeList;
@ -587,5 +622,6 @@ rct_ride_type *ride_get_entry(rct_ride *ride);
uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType);
void ride_measurements_update();
rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message);
void ride_breakdown_add_news_item(int rideIndex);
#endif

View File

@ -771,4 +771,98 @@ const uint8 RideAvailableModes[] = {
RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 58 Mine Ride
RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 59 LIM Launched Roller Coaster
RIDE_MODE_POWERED_LAUNCH_35, RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED, 0xFF // 60 (none)
};
const uint8 RideAvailableBreakdowns[] = {
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 00 Spiral Roller coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 01 Stand Up Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 02 Suspended Swinging
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 03 Inverted
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 04 Steel Mini Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 05 Mini Railroad
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_DOORS_STUCK_CLOSED) | (1 << BREAKDOWN_DOORS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 06 Monorail
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 07 Mini Suspended Coaster
(1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 08 Bumper Boats
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 09 Wooden Wild Mine/Mouse
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 0A Steeplechase/Motorbike/Soap Box Derby
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 0B Car Ride
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 0C Launched Freefall
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 0D Bobsleigh Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 0E Observation Tower
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 0F Looping Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 10 Dinghy Slide
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 11 Mine Train Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 12 Chairlift
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 13 Corkscrew Roller Coaster
0, // 14 Maze
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 15 Spiral Slide
(1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 16 Go Karts
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_CONTROL_FAILURE), // 17 Log Flume
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_CONTROL_FAILURE), // 18 River Rapids
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 19 Bumper Cars
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 1A Pirate Ship
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 1B Swinging Inverter Ship
0, // 1C Food Stall
0, // 1D (none)
0, // 1E Drink Stall
0, // 1F (none)
0, // 20 Shop (all types)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_CONTROL_FAILURE), // 21 Merry Go Round
0, // 22 Balloon Stall (maybe)
0, // 23 Information Kiosk
0, // 24 Bathroom
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 25 Ferris Wheel
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 26 Motion Simulator
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 27 3D Cinema
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 28 Gravitron
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 29 Space Rings
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 2A Reverse Freefall Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_DOORS_STUCK_CLOSED) | (1 << BREAKDOWN_DOORS_STUCK_OPEN), // 2B Elevator
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 2C Vertical Drop Roller Coaster
0, // 2D ATM
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 2E Twist
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 2F Haunted House
0, // 30 First Aid
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 31 Circus Show
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 32 Ghost Train
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 33 Twister Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 34 Wooden Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 35 Side-Friction Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 36 Wild Mouse
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 37 Multi Dimension Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 38 (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 39 Flying Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 3A (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 3B Virginia Reel
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_CONTROL_FAILURE), // 3C Splash Boats
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 3D Mini Helicopters
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 3E Lay-down Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_DOORS_STUCK_CLOSED) | (1 << BREAKDOWN_DOORS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 3F Suspended Monorail
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 40 (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 41 Reverser Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 42 Heartline Twister Roller Coaster
0, // 43 Mini Golf
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 44 Giga Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 45 Roto-Drop
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 46 Flying Saucers
0, // 47 Crooked House
(1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 48 Monorail Cycles
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 49 Compact Inverted Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 4A Water Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 4B Air Powered Vertical Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 4C Inverted Hairpin Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 4D Magic Carpet
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 4E Submarine Ride
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 4F River Rafts
0, // 50 (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT), // 51 Enterprise
0, // 52 (none)
0, // 53 (none)
0, // 54 (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 55 (none)
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 56 Inverted Impulse Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 57 Mini Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION), // 58 Mine Ride
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE), // 59 LIM Launched Roller Coaster
(1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE) // 60 (none)
};

View File

@ -41,5 +41,6 @@ extern const uint8 rideUnknownData3[0x60];
extern const rct_ride_name_convention RideNameConvention[96];
extern const uint8 RideAvailableModes[];
extern const uint8 RideAvailableBreakdowns[];
#endif

309
src/ride/station.c Normal file
View File

@ -0,0 +1,309 @@
/*****************************************************************************
* 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 "../scenario.h"
#include "../world/sprite.h"
#include "station.h"
static void ride_update_station_blocksection(rct_ride *ride, int stationIndex);
static void ride_update_station_bumpercar(rct_ride *ride, int stationIndex);
static void ride_update_station_normal(rct_ride *ride, int stationIndex);
static void ride_update_station_race(rct_ride *ride, int stationIndex);
static void ride_race_init_vehicle_speeds(rct_ride *ride);
static void ride_invalidate_station_start(rct_ride *ride, int stationIndex, int dl);
/**
*
* rct2: 0x006ABFFB
*/
void ride_update_station(rct_ride *ride, int stationIndex)
{
if (ride->station_starts[stationIndex] == 0xFFFF)
return;
switch (ride->mode) {
case RIDE_MODE_RACE:
ride_update_station_race(ride, stationIndex);
break;
case RIDE_MODE_BUMPERCAR:
ride_update_station_bumpercar(ride, stationIndex);
break;
case RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED:
case RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED:
ride_update_station_blocksection(ride, stationIndex);
break;
default:
ride_update_station_normal(ride, stationIndex);
break;
}
}
/**
*
* rct2: 0x006AC0A1
*/
static void ride_update_station_blocksection(rct_ride *ride, int stationIndex)
{
rct_map_element *mapElement;
mapElement = ride_get_station_start_track_element(ride, stationIndex);
if ((ride->status == RIDE_STATUS_CLOSED && ride->num_riders == 0) || mapElement->flags & 0x20) {
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
if ((ride->station_depart[stationIndex] & STATION_DEPART_FLAG) || (mapElement->properties.track.sequence & 0x80))
ride_invalidate_station_start(ride, stationIndex, 0);
} else {
if (!(ride->station_depart[stationIndex] & STATION_DEPART_FLAG)) {
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
ride_invalidate_station_start(ride, stationIndex, 1);
} else if (mapElement->properties.track.sequence & 0x80) {
ride_invalidate_station_start(ride, stationIndex, 1);
}
}
}
/**
*
* rct2: 0x006AC12B
*/
static void ride_update_station_bumpercar(rct_ride *ride, int stationIndex)
{
int i, dx, dl, dh;
rct_vehicle *vehicle;
if (
ride->status == RIDE_STATUS_CLOSED ||
(ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))
) {
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) {
dx = ride->time_limit * 32;
dl = dx & 0xFF;
dh = (dx >> 8) & 0xFF;
for (i = 0; i < ride->num_vehicles; i++) {
vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle);
if (vehicle->var_CE < dh || (vehicle->var_CE < dh && vehicle->var_51 > dl))
continue;
// End match
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
// Continue match
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
} else {
// Check if all vehicles are ready to go
for (i = 0; i < ride->num_vehicles; i++) {
vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART) {
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
}
// Begin the match
ride->lifecycle_flags |= RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
ride->var_14D |= 12;
}
}
/**
*
* rct2: 0x006AC02C
*/
static void ride_update_station_normal(rct_ride *ride, int stationIndex)
{
int time;
time = ride->station_depart[stationIndex] & STATION_DEPART_MASK;
if (
(ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) &&
(ride->status == RIDE_STATUS_CLOSED && ride->num_riders == 0)
) {
if (time != 0 && time != 127 && !(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 7))
time--;
ride->station_depart[stationIndex] = time;
} else {
if (time == 0) {
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
} else {
if (time != 127 && !(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 31))
time--;
ride->station_depart[stationIndex] = time;
}
}
}
/**
*
* rct2: 0x006AC1DF
*/
static void ride_update_station_race(rct_ride *ride, int stationIndex)
{
int i, numLaps;
rct_vehicle *vehicle;
rct_peep *peep;
if (
ride->status == RIDE_STATUS_CLOSED ||
(ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))
) {
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) {
numLaps = ride->num_laps;
for (i = 0; i < ride->num_vehicles; i++) {
vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART && vehicle->num_laps >= numLaps) {
// Found a winner
if (vehicle->var_B3 != 0) {
peep = &(g_sprite_list[vehicle->peep].peep);
ride->race_winner = peep->sprite_index;
ride->var_14D |= 12;
}
// Race is over
ride->lifecycle_flags &= ~RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING;
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
}
// Continue racing
ride->station_depart[stationIndex] |= STATION_DEPART_FLAG;
} else {
// Check if all vehicles are ready to go
for (i = 0; i < ride->num_vehicles; i++) {
vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle);
if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART && vehicle->status != VEHICLE_STATUS_DEPARTING) {
ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG;
return;
}
}
// Begin the race
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;
}
}
/**
*
* rct2: 0x006AC988
* set the speed of the go kart type vehicle at the start to a random value or alter if peep name is an easter egg
* @param ride (esi)
*/
static void ride_race_init_vehicle_speeds(rct_ride *ride)
{
rct_ride_type *rideEntry;
rct_vehicle *vehicle;
uint8 *unk;
int i;
for (i = 0; i < ride->num_vehicles; i++) {
vehicle = &g_sprite_list[ride->vehicles[i]].vehicle;
vehicle->var_48 &= ~(1 << 6);
rideEntry = GET_RIDE_ENTRY(vehicle->var_D6);
unk = (uint8*)((int)rideEntry + (vehicle->var_31 * 0x65));
vehicle->speed = (scenario_rand() & 16) - 8 + RCT2_GLOBAL(unk + 0x76, uint8);
if (vehicle->var_B3) {
rct_peep *peep = &g_sprite_list[vehicle->peep].peep;
switch (peep_get_easteregg_name_id(peep)) {
case EASTEREGG_PEEP_NAME_MICHAEL_SCHUMACHER:
vehicle->speed += 35;
break;
case EASTEREGG_PEEP_NAME_JACQUES_VILLENEUVE:
vehicle->speed += 25;
break;
case EASTEREGG_PEEP_NAME_DAMON_HILL:
vehicle->speed += 55;
break;
case EASTEREGG_PEEP_NAME_CHRIS_SAWYER:
vehicle->speed += 14;
break;
case EASTEREGG_PEEP_NAME_MR_BEAN:
vehicle->speed = 9;
break;
}
}
}
}
/**
*
* rct2: 0x006AC2C7
*/
static void ride_invalidate_station_start(rct_ride *ride, int stationIndex, int dl)
{
int x, y;
rct_map_element *mapElement;
x = (ride->station_starts[stationIndex] & 0xFF) * 32;
y = (ride->station_starts[stationIndex] >> 8) * 32;
mapElement = ride_get_station_start_track_element(ride, stationIndex);
mapElement->properties.track.sequence &= 0x7F;
if (dl != 0)
mapElement->properties.track.sequence |= 0x80;
// Invalidate map tile
map_invalidate_tile(x, y, mapElement->base_height * 8, mapElement->clearance_height * 8);
}
rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex)
{
int x, y, z;
rct_map_element *mapElement;
x = ride->station_starts[stationIndex] & 0xFF;
y = ride->station_starts[stationIndex] >> 8;
z = ride->station_heights[stationIndex];
// Get first element of the tile
mapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x);
// Find the station track element
do {
if ((mapElement->type & MAP_ELEMENT_TYPE_MASK) == MAP_ELEMENT_TYPE_TRACK && z == mapElement->base_height)
return mapElement;
mapElement++;
} while (!((mapElement - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE));
return NULL;
}

31
src/ride/station.h Normal file
View File

@ -0,0 +1,31 @@
/*****************************************************************************
* 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 _RIDE_STATION_H_
#define _RIDE_STATION_H_
#include "../common.h"
#include "../world/map.h"
#include "ride.h"
void ride_update_station(rct_ride *ride, int stationIndex);
rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex);
#endif

View File

@ -76,7 +76,10 @@ typedef struct {
uint8 pad_C3[0x09];
uint8 var_CC;
uint8 var_CD;
uint8 var_CE;
union {
uint8 var_CE;
uint8 num_laps; // 0xCE
};
uint8 pad_CF[0x07];
uint8 var_D6;
} rct_vehicle;

View File

@ -642,7 +642,7 @@ void scenario_update()
*
* rct2: 0x006E37D2
*/
int scenario_rand()
unsigned int scenario_rand()
{
int eax = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32);
RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32) += ror32(RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_1, uint32) ^ 0x1234567F, 7);

View File

@ -407,6 +407,6 @@ int scenario_load(const char *path);
int scenario_load_and_play(const rct_scenario_basic *scenario);
int scenario_load_and_play_from_path(const char *path);
void scenario_update();
int scenario_rand();
unsigned int scenario_rand();
#endif

View File

@ -51,4 +51,15 @@ long fsize(FILE *fp)
fseek(fp, originalPosition, SEEK_SET);
return size;
}
int bitscanforward(int source)
{
int i;
for (i = 0; i < 32; i++)
if (source & (1 << i))
return i;
return -1;
}

View File

@ -29,4 +29,6 @@ int mph_to_kmph(int mph);
long fsize(FILE *fp);
int bitscanforward(int source);
#endif

View File

@ -627,7 +627,7 @@ void window_guest_overview_mouse_up(){
RCT2_CALLPROC_X(0x0069E9D3, 0x8000, 0, peep->y, peep->z, (int)peep, 0, 0);
RCT2_CALLPROC_X(0x0069A409, 0, 0, 0, 0, (int)peep, 0, 0);
peep->state = 9;
peep->pad_2C = 0;
peep->var_2C = 0;
RCT2_CALLPROC_X(0x0069A42F, 0, 0, 0, 0, (int)peep, 0, 0);
break;
case WIDX_RENAME:
@ -1204,7 +1204,7 @@ void window_guest_overview_tool_down(){
int dest_z = ((uint8*)edx)[2] * 8 + 16;
if (sub_664F72(tile_x, tile_y, dest_z)){
if (!sub_664F72(tile_x, tile_y, dest_z)){
window_error_open(0x785,-1);
return;
}

View File

@ -1124,7 +1124,7 @@ void window_staff_overview_tool_down(){
int dest_z = ((uint8*)edx)[2] * 8 + 16;
if (sub_664F72(tile_x, tile_y, dest_z)){
if (!sub_664F72(tile_x, tile_y, dest_z)){
window_error_open(0x785, -1);
return;
}

View File

@ -437,27 +437,56 @@ static void sub_6A87BB(int x, int y)
RCT2_CALLPROC_X(0x006A87BB, x, 0, y, 0, 0, 0, 0);
}
/* rct2: 0x664F72 */
int sub_664F72(int x, int y, int z){
if (x > 0x1FFF || y > 0x1FFF){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0x6C1;
/**
*
* rct2: 0x00664F72
*/
int sub_664F72(int x, int y, int z)
{
rct_map_element *mapElement;
if (x < (256 * 32) && y < (256 * 32)) {
mapElement = map_get_surface_element_at(x / 32, y / 32);
if (mapElement->properties.surface.ownership & 0x20)
return 1;
if (mapElement->properties.surface.ownership & 0x10) {
z /= 8;
if (z < mapElement->base_height || z - 2 > mapElement->base_height)
return 1;
}
}
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 1729;
return 0;
}
/**
*
* rct2: 0x00664F2C
*/
int map_is_location_in_park(int x, int y)
{
rct_map_element *mapElement;
if (x < (256 * 32) && y < (256 * 32)) {
mapElement = map_get_surface_element_at(x / 32, y / 32);
if (mapElement->properties.surface.ownership & 0x20)
return 1;
}
rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32);
if (map_element->properties.surface.ownership & 0x20) return 0;
if (!(map_element->properties.surface.ownership & 0x10)){
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0x6C1;
return 1;
}
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 1729;
return 0;
}
z >>= 3;
if ((z & 0xFF) < map_element->base_height)return 0;
z = (z & 0xFF) - 2;
if (z > map_element->base_height)return 0;
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0x6C1;
return 1;
/**
*
* rct2: 0x006ECB60
* NOTE: x, y and z are in pixels, not tile units
*/
void map_invalidate_tile(int x, int y, int zLow, int zHigh)
{
RCT2_CALLPROC_X(0x006ECB60, x, 0, y, 0, zHigh, zLow, 0);
}
/**

View File

@ -206,6 +206,8 @@ int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction
void map_invalidate_animations();
void sub_6A876D();
int sub_664F72(int x, int y, int z);
int map_is_location_in_park(int x, int y);
void map_invalidate_tile(int x, int y, int zLow, int zHigh);
void fountain_update_all();

View File

@ -508,7 +508,7 @@ static rct_peep *park_generate_new_guest_due_to_campaign(int campaign)
static void park_generate_new_guests()
{
// Generate a new guest for some probability
if ((scenario_rand() & 0xFFFF) < _guestGenerationProbability) {
if ((int)(scenario_rand() & 0xFFFF) < _guestGenerationProbability) {
int difficultGeneration = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) != 0;
if (!difficultGeneration || _suggestedGuestMaximum + 150 >= RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))
park_generate_new_guest();
@ -519,7 +519,7 @@ static void park_generate_new_guests()
for (campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) {
if (RCT2_ADDRESS(0x01358102, uint8)[campaign] != 0) {
// Random chance of guest generation
if ((scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign))
if ((int)(scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign))
park_generate_new_guest_due_to_campaign(campaign);
}
}