2017-06-01 21:55:10 +02:00
|
|
|
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
2016-08-24 13:19:25 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
|
|
*
|
|
|
|
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
|
|
|
* For more information, visit https://github.com/OpenRCT2/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.
|
|
|
|
*
|
|
|
|
* A full copy of the GNU General Public License can be found in licence.txt
|
|
|
|
*****************************************************************************/
|
|
|
|
#pragma endregion
|
|
|
|
|
2017-02-20 21:05:59 +01:00
|
|
|
#include <openrct2/config/Config.h>
|
2016-12-28 14:16:15 +01:00
|
|
|
#include <openrct2/object.h>
|
|
|
|
#include <openrct2/interface/colour.h>
|
|
|
|
#include <openrct2/interface/viewport.h>
|
|
|
|
#include <openrct2/ride/ride.h>
|
|
|
|
#include <openrct2/ride/track.h>
|
|
|
|
#include <openrct2/world/sprite.h>
|
|
|
|
#include <openrct2/paint/map_element/map_element.h>
|
2017-10-13 22:23:07 +02:00
|
|
|
#include <openrct2/ride/ride.h>
|
2016-08-24 13:19:25 +02:00
|
|
|
|
2017-06-06 23:24:18 +02:00
|
|
|
#define RCT2_ADDRESS_SPRITE_LIST 0x010E63BC
|
2016-09-12 17:37:57 +02:00
|
|
|
|
2016-08-24 13:19:25 +02:00
|
|
|
#define gRideEntries RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*)
|
|
|
|
#define gCurrentRotation RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint8)
|
|
|
|
|
|
|
|
rct_map_element *gMapElements = (rct_map_element *) RCT2_ADDRESS_MAP_ELEMENTS;
|
|
|
|
rct_map_element **gMapElementTilePointers = (rct_map_element **) RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS;
|
2017-09-12 11:29:43 +02:00
|
|
|
Ride *gRideList = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, Ride);
|
2016-08-24 13:19:25 +02:00
|
|
|
rct_sprite *sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite);
|
2016-09-05 17:26:08 +02:00
|
|
|
sint16 gMapSizeUnits;
|
2016-09-12 17:37:57 +02:00
|
|
|
sint16 gMapBaseZ;
|
|
|
|
bool gTrackDesignSaveMode = false;
|
|
|
|
uint8 gTrackDesignSaveRideIndex = 255;
|
2017-01-08 21:31:34 +01:00
|
|
|
uint8 gClipHeight = 255;
|
2016-08-24 13:19:25 +02:00
|
|
|
|
2017-10-13 22:23:07 +02:00
|
|
|
const LocationXY16 TileDirectionDelta[] = {
|
2017-06-06 23:24:18 +02:00
|
|
|
{-32, 0},
|
|
|
|
{0, +32},
|
|
|
|
{+32, 0},
|
|
|
|
{0, -32},
|
|
|
|
{-32, +32},
|
|
|
|
{+32, +32},
|
|
|
|
{+32, -32},
|
|
|
|
{-32, -32}
|
2016-08-24 13:19:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
uint8 get_current_rotation() {
|
2017-06-06 23:24:18 +02:00
|
|
|
return gCurrentRotation & 3;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const uint32 construction_markers[] = {
|
2017-06-06 23:24:18 +02:00
|
|
|
COLOUR_DARK_GREEN << 19 | COLOUR_GREY << 24 | IMAGE_TYPE_REMAP, // White
|
|
|
|
2 << 19 | 0b110000 << 19 | IMAGE_TYPE_TRANSPARENT, // Translucent
|
2016-08-24 13:19:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
int object_entry_group_counts[] = {
|
2017-06-06 23:24:18 +02:00
|
|
|
128, // rides
|
|
|
|
252, // small scenery
|
|
|
|
128, // large scenery
|
|
|
|
128, // walls
|
|
|
|
32, // banners
|
|
|
|
16, // paths
|
|
|
|
15, // path bits
|
|
|
|
19, // scenery sets
|
|
|
|
1, // park entrance
|
|
|
|
1, // water
|
|
|
|
1 // scenario text
|
2016-08-24 13:19:25 +02:00
|
|
|
};
|
|
|
|
|
2017-02-21 07:29:06 +01:00
|
|
|
GeneralConfiguration gConfigGeneral;
|
2016-08-24 13:19:25 +02:00
|
|
|
uint16 gMapSelectFlags;
|
|
|
|
uint16 gMapSelectType;
|
2017-10-13 22:23:07 +02:00
|
|
|
LocationXY16 gMapSelectPositionA;
|
|
|
|
LocationXY16 gMapSelectPositionB;
|
|
|
|
LocationXYZ16 gMapSelectArrowPosition;
|
2016-08-24 13:19:25 +02:00
|
|
|
uint8 gMapSelectArrowDirection;
|
|
|
|
|
2017-09-02 23:43:45 +02:00
|
|
|
void entrance_paint(paint_session * session, uint8 direction, int height, rct_map_element *map_element) { }
|
2017-09-02 23:38:26 +02:00
|
|
|
void banner_paint(paint_session * session, uint8 direction, int height, rct_map_element *map_element) { }
|
2017-09-02 23:25:45 +02:00
|
|
|
void surface_paint(paint_session * session, uint8 direction, uint16 height, rct_map_element *mapElement) { }
|
2017-09-02 23:31:39 +02:00
|
|
|
void path_paint(paint_session * session, uint8 direction, uint16 height, rct_map_element *mapElement) { }
|
2017-09-02 23:44:39 +02:00
|
|
|
void scenery_paint(paint_session * session, uint8 direction, int height, rct_map_element *mapElement) { }
|
2017-09-02 23:41:36 +02:00
|
|
|
void fence_paint(paint_session * session, uint8 direction, int height, rct_map_element *mapElement) { }
|
2017-09-02 23:40:19 +02:00
|
|
|
void scenery_multiple_paint(paint_session * session, uint8 direction, uint16 height, rct_map_element *mapElement) { }
|
2016-08-24 13:19:25 +02:00
|
|
|
|
2017-09-12 11:29:43 +02:00
|
|
|
Ride *get_ride(int index) {
|
2017-06-06 23:24:18 +02:00
|
|
|
if (index < 0 || index >= MAX_RIDES) {
|
|
|
|
log_error("invalid index %d for ride", index);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return &gRideList[index];
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rct_ride_entry *get_ride_entry(int index) {
|
2017-06-06 23:24:18 +02:00
|
|
|
if (index < 0 || index >= object_entry_group_counts[OBJECT_TYPE_RIDE]) {
|
|
|
|
log_error("invalid index %d for ride type", index);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-10-12 21:07:35 +02:00
|
|
|
|
2017-10-15 15:53:16 +02:00
|
|
|
return gRideEntries[index];
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
2017-09-12 11:29:43 +02:00
|
|
|
rct_ride_entry *get_ride_entry_by_ride(Ride *ride) {
|
2017-10-12 21:07:35 +02:00
|
|
|
rct_ride_entry * type = get_ride_entry(ride->subtype);
|
2017-06-06 23:24:18 +02:00
|
|
|
if (type == NULL) {
|
|
|
|
log_error("Invalid ride subtype for ride");
|
|
|
|
}
|
|
|
|
return type;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
rct_sprite *get_sprite(size_t sprite_idx) {
|
2017-06-06 23:24:18 +02:00
|
|
|
assert(sprite_idx < MAX_SPRITES);
|
|
|
|
return &sprite_list[sprite_idx];
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int map_element_is_last_for_tile(const rct_map_element *element) {
|
2017-06-06 23:24:18 +02:00
|
|
|
return element->flags & MAP_ELEMENT_FLAG_LAST_TILE;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int map_element_get_type(const rct_map_element *element) {
|
2017-06-06 23:24:18 +02:00
|
|
|
return element->type & MAP_ELEMENT_TYPE_MASK;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int map_element_get_direction(const rct_map_element *element) {
|
2017-06-06 23:24:18 +02:00
|
|
|
return element->type & MAP_ELEMENT_DIRECTION_MASK;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 11:59:41 +02:00
|
|
|
int map_element_get_direction_with_offset(const rct_map_element *element, uint8 offset) {
|
2017-08-06 01:18:32 +02:00
|
|
|
return ((element->type & MAP_ELEMENT_DIRECTION_MASK) + offset) & MAP_ELEMENT_DIRECTION_MASK;
|
2017-07-27 11:59:41 +02:00
|
|
|
}
|
|
|
|
|
2016-08-24 13:19:25 +02:00
|
|
|
rct_map_element *map_get_first_element_at(int x, int y) {
|
2017-06-06 23:24:18 +02:00
|
|
|
if (x < 0 || y < 0 || x > 255 || y > 255) {
|
|
|
|
log_error("Trying to access element outside of range");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return gMapElementTilePointers[x + y * 256];
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 13:48:01 +02:00
|
|
|
int map_element_get_station(const rct_map_element * mapElement) {
|
|
|
|
return (mapElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK) >> 4;
|
|
|
|
}
|
|
|
|
|
2017-07-27 16:19:01 +02:00
|
|
|
void map_element_set_station(rct_map_element * mapElement, uint32 stationIndex)
|
2017-07-27 13:48:01 +02:00
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_STATION_INDEX_MASK;
|
|
|
|
mapElement->properties.track.sequence |= (stationIndex << 4);
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 16:19:01 +02:00
|
|
|
sint32 map_element_get_track_sequence(const rct_map_element * mapElement)
|
|
|
|
{
|
|
|
|
return mapElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void map_element_set_track_sequence(rct_map_element * mapElement, int trackSequence)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
|
|
|
|
mapElement->properties.track.sequence |= (trackSequence & MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool map_element_get_green_light(const rct_map_element * mapElement)
|
|
|
|
{
|
2017-08-01 13:42:50 +02:00
|
|
|
return (mapElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT) != 0;
|
2017-07-27 16:19:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void map_element_set_green_light(rct_map_element * mapElement, bool greenLight)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence &= ~MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT;
|
|
|
|
if (greenLight)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence |= MAP_ELEM_TRACK_SEQUENCE_GREEN_LIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int map_element_get_brake_booster_speed(const rct_map_element *mapElement)
|
|
|
|
{
|
|
|
|
return (mapElement->properties.track.sequence >> 4) << 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void map_element_set_brake_booster_speed(rct_map_element *mapElement, int speed)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence = map_element_get_track_sequence(mapElement) | ((speed >> 1) << 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool map_element_is_taking_photo(const rct_map_element * mapElement)
|
|
|
|
{
|
2017-08-01 13:42:50 +02:00
|
|
|
return (mapElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK) != 0;
|
2017-07-27 16:19:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void map_element_set_onride_photo_timeout(rct_map_element * mapElement)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence &= MAP_ELEM_TRACK_SEQUENCE_SEQUENCE_MASK;
|
|
|
|
mapElement->properties.track.sequence |= (3 << 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void map_element_decrement_onride_photo_timout(rct_map_element * mapElement)
|
|
|
|
{
|
|
|
|
// We should only touch the upper 4 bits, avoid underflow into the lower 4.
|
|
|
|
if (mapElement->properties.track.sequence & MAP_ELEM_TRACK_SEQUENCE_TAKING_PHOTO_MASK)
|
|
|
|
{
|
|
|
|
mapElement->properties.track.sequence -= (1 << 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 17:15:56 +02:00
|
|
|
sint32 map_get_water_height(const rct_map_element * mapElement)
|
|
|
|
{
|
|
|
|
return mapElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK;
|
|
|
|
}
|
|
|
|
|
2016-08-24 13:19:25 +02:00
|
|
|
bool ride_type_has_flag(int rideType, int flag)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return (RideProperties[rideType].flags & flag) != 0;
|
2016-08-24 13:19:25 +02:00
|
|
|
}
|
2016-09-12 22:56:52 +02:00
|
|
|
|
|
|
|
sint16 get_height_marker_offset()
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return 0;
|
2016-09-12 22:56:52 +02:00
|
|
|
}
|
2016-10-01 19:03:31 +02:00
|
|
|
|
|
|
|
bool track_element_is_lift_hill(rct_map_element *trackElement)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return trackElement->type & 0x80;
|
2016-10-01 19:03:31 +02:00
|
|
|
}
|
2016-10-09 00:20:29 +02:00
|
|
|
|
|
|
|
bool track_element_is_cable_lift(rct_map_element *trackElement)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT;
|
2016-10-09 00:20:29 +02:00
|
|
|
}
|
2016-10-09 04:35:39 +02:00
|
|
|
|
|
|
|
bool track_element_is_inverted(rct_map_element *trackElement)
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_INVERTED;
|
2016-10-09 04:35:39 +02:00
|
|
|
}
|
2017-04-11 19:53:52 +02:00
|
|
|
|
|
|
|
bool is_csg_loaded()
|
|
|
|
{
|
2017-06-06 23:24:18 +02:00
|
|
|
return false;
|
2017-04-11 19:53:52 +02:00
|
|
|
}
|
2017-10-04 17:14:53 +02:00
|
|
|
|
|
|
|
uint8 track_element_get_colour_scheme(const rct_map_element * mapElement)
|
|
|
|
{
|
|
|
|
return mapElement->properties.track.colour & 0x3;
|
|
|
|
}
|