Initial implementation of ride reachability checks

This commit is contained in:
lnz 2014-05-21 14:04:08 +02:00
parent 0687758e0a
commit 64bece0246
3 changed files with 209 additions and 3 deletions

View File

@ -20,6 +20,9 @@
#include <windows.h>
#include "addresses.h"
#include "map.h"
#include "news_item.h"
#include "sprite.h"
#include "ride.h"
#include "sprite.h"
#include "peep.h"
@ -191,3 +194,204 @@ void ride_update_favourited_stat()
window_invalidate_by_id(WC_RIDE_LIST, 0);
}
int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction)
{
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[coordinate / 4];
do {
rct_map_element_path_properties props = tile->properties.path;
uint8 path_type = props.type >> 2, path_dir = props.type & 3;
uint8 element_type = tile->type & 0x3C;
if (!(element_type & PATH_ROAD))
continue;
if (path_type & 1) {
if (path_dir == face_direction) {
if (height == tile->base_height + 2)
return 1;
}
else if (path_dir ^ 2 == face_direction && height == tile->base_height) {
return 1;
}
} else {
if (height == tile->base_height)
return 1;
}
} while (!(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) && tile++);
return 0;
}
/**
* rct2: 0x006B7C59
* @return 1 if the coordinate is reachable or has no entrance, 0 otw
*/
int ride_is_reachable(uint16 coordinate, rct_ride* ride, int index) {
int x = ((coordinate >> 8) & 0xFF) << 5, // cx
y = (coordinate & 0xFF) << 5; // ax
uint8 station_height = ride->pad_05A[index]; // pad_05a is uint8 station_base_height[4]
int tile_idx = ((x << 8) | y) >> 3;
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx / 4];
while(1) {
uint8 element_type = tile->type & 0x3C;
if (element_type == MAP_ELEMENT_TYPE_ENTRANCE && station_height == tile->base_height) {
break;
} else if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) {
return 1;
}
tile++;
}
uint8 face_direction = tile->type & 3;
y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
tile_idx = ((x << 8) | y) >> 3;
return map_coord_is_connected(tile_idx, station_height, face_direction);
/* while (1) { */
/* rct_map_element_path_properties props; */
/* element_type = tile->type & 0x3C; */
/* if (!(element_type & MAP_ELEMENT_TYPE_PATH)) */
/* goto end; */
/* props = tile->properties.path; */
/* if ( props.type & PATH_ROAD) { // with roads slopes count as connected sometimes */
/* if ((props.type & 3) == face_direction) { */
/* if (station_height == tile->base_height + 2) */
/* return 1; */
/* } */
/* else { */
/* uint8 madness = (props.type & 3) ^ 2; */
/* if (madness == face_direction && station_height == tile->base_height) */
/* return 1; */
/* } */
/* } else { // off-road only same height counts as connected */
/* if (station_height == tile->base_height) */
/* return 1; */
/* } */
/* end: */
/* if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) */
/* return 0; */
/* tile++; */
/* } */
}
void ride_entrance_exit_connected(rct_ride* ride, int ride_idx)
{
for (int i = 0; i < 4; ++i) {
uint16 station_start = ride->station_starts[i],
entrance = ride->entrances[i],
exit = ride->exits[i];
if (station_start == -1 )
continue;
if (entrance != -1 && !ride_is_reachable(entrance, ride, i)) {
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
news_item_add_to_queue(1, 0xb26, ride_idx);
ride->var_1AF = 3;
}
if (exit != -1 && !ride_is_reachable(exit, ride, i)) {
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
news_item_add_to_queue(1, 0xb27, ride_idx);
ride->var_1AF = 3;
}
}
}
void blue_reachable(rct_ride* ride, int ride_idx)
{
uint16 coordinate = ride->station_starts[ride_idx];
int x = ((coordinate >> 8) & 0xFF) << 5, // cx
y = (coordinate & 0xFF) << 5; // ax
uint16 magic = 0;
int tile_idx = ((x << 8) | y) >> 3, count = 0;
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx / 4];
while (1) {
// First find the appropriate track element for our ride
uint8 element_type = tile->type & 0x3C;
if(element_type == MAP_ELEMENT_TYPE_TRACK && tile->properties.track.ride_index == ride_idx)
break;
if(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE)
return;
tile++;
}
uint8 track_type = tile->properties.track.type;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) {
magic = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16];
} else {
magic = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16];
}
magic = magic << (tile->type & 3);
magic = ((magic >> 12) | magic) & 0xF;
for (int count = 0; magic != 0; ++count) {
if (!(magic & 1)) {
magic >>= 1;
continue;
}
uint8 face_direction = count ^ 2;
y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
tile_idx = ((x << 8) | y) >> 3;
if (map_coord_is_connected(tile, tile->base_height, face_direction))
return;
}
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
news_item_add_to_queue(1, 0xb26, ride_idx);
ride->var_1AF = 3;
}
/**
* rct2: 0x006B7A5E
**/
void ride_check_all_reachable()
{
/* XXX: coordinates gleich um 5 shiften und / 4 ueberall weg */
rct_ride *ride;
for (int i = 0; i < MAX_RIDES; i++) {
ride = GET_RIDE(i);
if (ride->type == RIDE_TYPE_NULL)
continue;
if (ride->var_1AF != 0)
ride->var_1AF--;
if (ride->status != RIDE_STATUS_OPEN || ride->var_1AF != 0)
continue;
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000) {
//lightblue
blue_reachable(ride, i);
return;
}
else {
//pink
ride_entrance_exit_connected(ride, i);
}
}
}

View File

@ -111,8 +111,9 @@ typedef struct {
uint8 var_199;
uint8 pad_19A[0x14];
uint8 var_1AE;
uint8 pad_1AF[0x05];
money32 profit; // 0x1B4
uint8 var_1AF;
uint32 pad_1B0;
sint32 profit; // 0x1B4
uint8 queue_time[4]; // 0x1B8
uint8 var_1BC;
uint8 pad_1BD[0x10];
@ -343,5 +344,6 @@ int ride_get_max_queue_time(rct_ride *ride);
void ride_init_all();
void reset_all_ride_build_dates();
void ride_update_favourited_stat();
void ride_check_all_reachable();
#endif

View File

@ -592,7 +592,7 @@ void scenario_update()
finance_pay_interest();
marketing_update();
peep_problem_warnings_update();
RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability
ride_check_all_reachable();
ride_update_favourited_stat();
if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) {