/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 * * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ #include "../../config/Config.h" #include "../../interface/Viewport.h" #include "../../paint/Paint.h" #include "../../paint/Supports.h" #include "../../peep/Peep.h" #include "../../world/Entity.h" #include "../../world/Map.h" #include "../../world/Surface.h" #include "../RideData.h" #include "../TrackData.h" #include "../TrackPaint.h" #include "../Vehicle.h" #include "../VehiclePaint.h" #include enum { SPR_MINI_GOLF_FLAT_SW_NE = 14404, SPR_MINI_GOLF_FLAT_NW_SE = 14405, SPR_MINI_GOLF_FLAT_FENCE_BACK_SW_NE = 14406, SPR_MINI_GOLF_FLAT_FENCE_BACK_NW_SE = 14407, SPR_MINI_GOLF_FLAT_FENCE_FRONT_SW_NE = 14408, SPR_MINI_GOLF_FLAT_FENCE_FRONT_NW_SE = 14409, SPR_MINI_GOLF_STATION_FLOOR = 14410, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_SW_NW = 14411, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_NW_NE = 14412, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_NE_SE = 14413, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_SE_SW = 14414, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_SW_NW = 14415, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_NW_NE = 14416, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_NE_SE = 14417, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_SE_SW = 14418, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_SW_NW = 14419, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_NW_NE = 14420, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_NE_SE = 14421, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_SE_SW = 14422, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_INSIDE_SW_NW = 14423, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_INSIDE_NE_SE = 14424, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_SW_NE = 14425, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_NW_SE = 14426, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_NE_SW = 14427, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_SE_NW = 14428, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_SW_NE = 14429, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_NW_SE = 14430, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_NE_SW = 14431, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_SE_NW = 14432, SPR_MINI_GOLF_25_DEG_UP_SW_NE = 14433, SPR_MINI_GOLF_25_DEG_UP_NW_SE = 14434, SPR_MINI_GOLF_25_DEG_UP_NE_SW = 14435, SPR_MINI_GOLF_25_DEG_UP_SE_NW = 14436, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_SW_NE = 14437, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_NW_SE = 14438, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_NE_SW = 14439, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_SE_NW = 14440, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_SW_NE = 14441, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_NW_SE = 14442, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_NE_SW = 14443, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_SE_NW = 14444, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_SW_NE = 14445, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_NW_SE = 14446, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_NE_SW = 14447, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_SE_NW = 14448, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_SW_NE = 14449, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_NW_SE = 14450, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_NE_SW = 14451, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_SE_NW = 14452, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_SW_NE = 14453, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_NW_SE = 14454, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_NE_SW = 14455, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_SE_NW = 14456, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_SW_NE = 14457, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_NW_SE = 14458, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_NE_SW = 14459, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_SE_NW = 14460, SPR_MINI_GOLF_HOLE_A_BASE_PART_1_SW_NE = 14461, SPR_MINI_GOLF_HOLE_A_BASE_PART_2_SW_NE = 14462, SPR_MINI_GOLF_HOLE_A_BASE_PART_1_NW_SE = 14463, SPR_MINI_GOLF_HOLE_A_BASE_PART_2_NW_SE = 14464, SPR_MINI_GOLF_HOLE_A_BASE_PART_1_NE_SW = 14465, SPR_MINI_GOLF_HOLE_A_BASE_PART_2_NE_SW = 14466, SPR_MINI_GOLF_HOLE_A_BASE_PART_1_SE_NW = 14467, SPR_MINI_GOLF_HOLE_A_BASE_PART_2_SE_NW = 14468, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_SW_NE = 14469, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_SW_NE = 14470, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_NW_SE = 14471, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_NW_SE = 14472, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_NE_SW = 14473, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_NE_SW = 14474, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_SE_NW = 14475, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_SE_NW = 14476, SPR_MINI_GOLF_HOLE_B_BASE_PART_1_SW_NE = 14477, SPR_MINI_GOLF_HOLE_B_BASE_PART_2_SW_NE = 14478, SPR_MINI_GOLF_HOLE_B_BASE_PART_1_NW_SE = 14479, SPR_MINI_GOLF_HOLE_B_BASE_PART_2_NW_SE = 14480, SPR_MINI_GOLF_HOLE_B_BASE_PART_1_NE_SW = 14481, SPR_MINI_GOLF_HOLE_B_BASE_PART_2_NE_SW = 14482, SPR_MINI_GOLF_HOLE_B_BASE_PART_1_SE_NW = 14483, SPR_MINI_GOLF_HOLE_B_BASE_PART_2_SE_NW = 14484, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_SW_NE = 14485, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_SW_NE = 14486, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_NW_SE = 14487, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_NW_SE = 14488, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_NE_SW = 14489, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_NE_SW = 14490, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_SE_NW = 14491, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_SE_NW = 14492, SPR_MINI_GOLF_HOLE_C_BASE_PART_1_SW_NE = 14493, SPR_MINI_GOLF_HOLE_C_BASE_PART_2_SW_NE = 14494, SPR_MINI_GOLF_HOLE_C_BASE_PART_1_NW_SE = 14495, SPR_MINI_GOLF_HOLE_C_BASE_PART_2_NW_SE = 14496, SPR_MINI_GOLF_HOLE_C_BASE_PART_1_NE_SW = 14497, SPR_MINI_GOLF_HOLE_C_BASE_PART_2_NE_SW = 14498, SPR_MINI_GOLF_HOLE_C_BASE_PART_1_SE_NW = 14499, SPR_MINI_GOLF_HOLE_C_BASE_PART_2_SE_NW = 14500, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_SW_NE = 14501, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_SW_NE = 14502, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_NW_SE = 14503, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_NW_SE = 14504, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_NE_SW = 14505, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_NE_SW = 14506, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_SE_NW = 14507, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_SE_NW = 14508, SPR_MINI_GOLF_HOLE_D_BASE_PART_1_SW_SE = 14509, SPR_MINI_GOLF_HOLE_D_BASE_PART_2_SW_SE = 14510, SPR_MINI_GOLF_HOLE_D_BASE_PART_3_SW_SE = 14511, SPR_MINI_GOLF_HOLE_D_BASE_PART_1_NW_SW = 14512, SPR_MINI_GOLF_HOLE_D_BASE_PART_2_NW_SW = 14513, SPR_MINI_GOLF_HOLE_D_BASE_PART_3_NW_SW = 14514, SPR_MINI_GOLF_HOLE_D_BASE_PART_1_NE_NW = 14515, SPR_MINI_GOLF_HOLE_D_BASE_PART_2_NE_NW = 14516, SPR_MINI_GOLF_HOLE_D_BASE_PART_3_NE_NW = 14517, SPR_MINI_GOLF_HOLE_D_BASE_PART_1_SE_NE = 14518, SPR_MINI_GOLF_HOLE_D_BASE_PART_2_SE_NE = 14519, SPR_MINI_GOLF_HOLE_D_BASE_PART_3_SE_NE = 14520, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_SW_SE = 14521, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_SW_SE = 14522, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_SW_SE = 14523, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_NW_SW = 14524, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_NW_SW = 14525, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_NW_SW = 14526, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_NE_NW = 14527, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_NE_NW = 14528, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_NE_NW = 14529, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_SE_NE = 14530, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_SE_NE = 14531, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_SE_NE = 14532, SPR_MINI_GOLF_HOLE_E_BASE_PART_1_SE_SW = 14533, SPR_MINI_GOLF_HOLE_E_BASE_PART_2_SE_SW = 14534, SPR_MINI_GOLF_HOLE_E_BASE_PART_3_SE_SW = 14535, SPR_MINI_GOLF_HOLE_E_BASE_PART_1_NE_SE = 14536, SPR_MINI_GOLF_HOLE_E_BASE_PART_2_NE_SE = 14537, SPR_MINI_GOLF_HOLE_E_BASE_PART_3_NE_SE = 14538, SPR_MINI_GOLF_HOLE_E_BASE_PART_1_NW_NE = 14539, SPR_MINI_GOLF_HOLE_E_BASE_PART_2_NW_NE = 14540, SPR_MINI_GOLF_HOLE_E_BASE_PART_3_NW_NE = 14541, SPR_MINI_GOLF_HOLE_E_BASE_PART_1_SW_NW = 14542, SPR_MINI_GOLF_HOLE_E_BASE_PART_2_SW_NW = 14543, SPR_MINI_GOLF_HOLE_E_BASE_PART_3_SW_NW = 14544, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_SE_SW = 14545, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_SE_SW = 14546, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_SE_SW = 14547, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_NE_SE = 14548, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_NE_SE = 14549, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_NE_SE = 14550, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_NW_NE = 14551, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_NW_NE = 14552, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_NW_NE = 14553, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_SW_NW = 14554, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_SW_NW = 14555, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_SW_NW = 14556, }; static constexpr const uint32_t mini_golf_track_sprites_25_deg_up[][3] = { { SPR_MINI_GOLF_25_DEG_UP_SW_NE, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_SW_NE, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_SW_NE, }, { SPR_MINI_GOLF_25_DEG_UP_NW_SE, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_NW_SE, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_NW_SE, }, { SPR_MINI_GOLF_25_DEG_UP_NE_SW, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_NE_SW, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_NE_SW, }, { SPR_MINI_GOLF_25_DEG_UP_SE_NW, SPR_MINI_GOLF_25_DEG_UP_FENCE_BACK_SE_NW, SPR_MINI_GOLF_25_DEG_UP_FENCE_FRONT_SE_NW, }, }; static constexpr const uint32_t mini_golf_track_sprites_flat_to_25_deg_up[][3] = { { SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_SW_NE, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_SW_NE, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_SW_NE, }, { SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_NW_SE, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_NW_SE, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_NW_SE, }, { SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_NE_SW, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_NE_SW, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_NE_SW, }, { SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_SE_NW, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_BACK_SE_NW, SPR_MINI_GOLF_FLAT_TO_25_DEG_UP_FENCE_FRONT_SE_NW, }, }; static constexpr const uint32_t mini_golf_track_sprites_25_deg_up_to_flat[][3] = { { SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_SW_NE, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_SW_NE, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_SW_NE, }, { SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_NW_SE, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_NW_SE, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_NW_SE, }, { SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_NE_SW, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_NE_SW, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_NE_SW, }, { SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_SE_NW, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_BACK_SE_NW, SPR_MINI_GOLF_25_DEG_UP_TO_FLAT_FENCE_FRONT_SE_NW, }, }; static constexpr const uint32_t mini_golf_track_sprites_quarter_turn_1_tile[] = { SPR_MINI_GOLF_QUARTER_TURN_1_TILE_SW_NW, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_NW_NE, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_NE_SE, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_SE_SW, }; static constexpr const uint32_t mini_golf_track_sprites_quarter_turn_1_tile_fence_front[] = { SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_SW_NW, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_NW_NE, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_NE_SE, SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_FRONT_SE_SW, }; static constexpr const uint32_t mini_golf_track_sprites_hole_a[4][2][2] = { { { SPR_MINI_GOLF_HOLE_A_BASE_PART_1_SW_NE, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_SW_NE }, { SPR_MINI_GOLF_HOLE_A_BASE_PART_2_SW_NE, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_SW_NE }, }, { { SPR_MINI_GOLF_HOLE_A_BASE_PART_1_NW_SE, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_NW_SE }, { SPR_MINI_GOLF_HOLE_A_BASE_PART_2_NW_SE, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_NW_SE }, }, { { SPR_MINI_GOLF_HOLE_A_BASE_PART_1_NE_SW, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_NE_SW }, { SPR_MINI_GOLF_HOLE_A_BASE_PART_2_NE_SW, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_NE_SW }, }, { { SPR_MINI_GOLF_HOLE_A_BASE_PART_1_SE_NW, SPR_MINI_GOLF_HOLE_A_TRIM_PART_1_SE_NW }, { SPR_MINI_GOLF_HOLE_A_BASE_PART_2_SE_NW, SPR_MINI_GOLF_HOLE_A_TRIM_PART_2_SE_NW }, }, }; static constexpr const uint32_t mini_golf_track_sprites_hole_b[4][2][2] = { { { SPR_MINI_GOLF_HOLE_B_BASE_PART_1_SW_NE, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_SW_NE }, { SPR_MINI_GOLF_HOLE_B_BASE_PART_2_SW_NE, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_SW_NE }, }, { { SPR_MINI_GOLF_HOLE_B_BASE_PART_1_NW_SE, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_NW_SE }, { SPR_MINI_GOLF_HOLE_B_BASE_PART_2_NW_SE, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_NW_SE }, }, { { SPR_MINI_GOLF_HOLE_B_BASE_PART_1_NE_SW, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_NE_SW }, { SPR_MINI_GOLF_HOLE_B_BASE_PART_2_NE_SW, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_NE_SW }, }, { { SPR_MINI_GOLF_HOLE_B_BASE_PART_1_SE_NW, SPR_MINI_GOLF_HOLE_B_TRIM_PART_1_SE_NW }, { SPR_MINI_GOLF_HOLE_B_BASE_PART_2_SE_NW, SPR_MINI_GOLF_HOLE_B_TRIM_PART_2_SE_NW }, }, }; static constexpr const uint32_t mini_golf_track_sprites_hole_c[][2][2] = { { { SPR_MINI_GOLF_HOLE_C_BASE_PART_1_SW_NE, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_SW_NE }, { SPR_MINI_GOLF_HOLE_C_BASE_PART_2_SW_NE, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_SW_NE }, }, { { SPR_MINI_GOLF_HOLE_C_BASE_PART_1_NW_SE, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_NW_SE }, { SPR_MINI_GOLF_HOLE_C_BASE_PART_2_NW_SE, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_NW_SE }, }, { { SPR_MINI_GOLF_HOLE_C_BASE_PART_1_NE_SW, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_NE_SW }, { SPR_MINI_GOLF_HOLE_C_BASE_PART_2_NE_SW, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_NE_SW }, }, { { SPR_MINI_GOLF_HOLE_C_BASE_PART_1_SE_NW, SPR_MINI_GOLF_HOLE_C_TRIM_PART_1_SE_NW }, { SPR_MINI_GOLF_HOLE_C_BASE_PART_2_SE_NW, SPR_MINI_GOLF_HOLE_C_TRIM_PART_2_SE_NW }, }, }; static constexpr const uint32_t mini_golf_track_sprites_hole_d[][3][2] = { { { SPR_MINI_GOLF_HOLE_D_BASE_PART_1_SW_SE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_SW_SE }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_2_SW_SE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_SW_SE }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_3_SW_SE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_SW_SE }, }, { { SPR_MINI_GOLF_HOLE_D_BASE_PART_1_NW_SW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_NW_SW }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_2_NW_SW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_NW_SW }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_3_NW_SW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_NW_SW }, }, { { SPR_MINI_GOLF_HOLE_D_BASE_PART_1_NE_NW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_NE_NW }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_2_NE_NW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_NE_NW }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_3_NE_NW, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_NE_NW }, }, { { SPR_MINI_GOLF_HOLE_D_BASE_PART_1_SE_NE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_1_SE_NE }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_2_SE_NE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_2_SE_NE }, { SPR_MINI_GOLF_HOLE_D_BASE_PART_3_SE_NE, SPR_MINI_GOLF_HOLE_D_TRIM_PART_3_SE_NE }, }, }; static constexpr const uint32_t mini_golf_track_sprites_hole_e[][3][2] = { { { SPR_MINI_GOLF_HOLE_E_BASE_PART_1_SW_NW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_SW_NW }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_2_SW_NW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_SW_NW }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_3_SW_NW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_SW_NW }, }, { { SPR_MINI_GOLF_HOLE_E_BASE_PART_1_NW_NE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_NW_NE }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_2_NW_NE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_NW_NE }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_3_NW_NE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_NW_NE }, }, { { SPR_MINI_GOLF_HOLE_E_BASE_PART_1_NE_SE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_NE_SE }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_2_NE_SE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_NE_SE }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_3_NE_SE, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_NE_SE }, }, { { SPR_MINI_GOLF_HOLE_E_BASE_PART_1_SE_SW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_1_SE_SW }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_2_SE_SW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_2_SE_SW }, { SPR_MINI_GOLF_HOLE_E_BASE_PART_3_SE_SW, SPR_MINI_GOLF_HOLE_E_TRIM_PART_3_SE_SW }, }, }; /** rct2: 0x00933471 */ // clang-format off static constexpr const uint8_t mini_golf_peep_animation_frames_walk[] = { 0, 1, 2, 3, 4, 5, }; /** rct2: 0x00933478 */ static constexpr const uint8_t mini_golf_peep_animation_frames_place_ball_downwards[] = { 12, 13, 14, 15, }; /** rct2: 0x009334B5 */ static constexpr const uint8_t mini_golf_peep_animation_frames_swing[] = { 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33, 33, 33, 34, }; /** rct2: 0x0093347D */ static constexpr const uint8_t mini_golf_peep_animation_frames_swing_left[] = { 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 9, }; /** rct2: 0x0093348D */ static constexpr const uint8_t mini_golf_peep_animation_frames_pickup_ball[] = { 12, 13, 14, 15, 14, 13, 12, }; /** rct2: 0x00933495 */ static constexpr const uint8_t mini_golf_peep_animation_frames_jump[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, }; /** rct2: 0x009334A5 */ static constexpr const uint8_t mini_golf_peep_animation_frames_place_ball_upwards[] = { 15, 14, 13, 12, }; /** rct2: 0x009334C5 */ static constexpr const uint8_t mini_golf_peep_animation_frames_putt[] = { 35, 36, 36, 36, 36, 36, 35, 35, 35, 35, }; /** rct2: 0x009334AA */ static constexpr const uint8_t mini_golf_peep_animation_frames_putt_left[] = { 10, 11, 11, 11, 11, 11, 10, 10, 10, 10, }; /** rct2: 0x008B8F74 */ static constexpr const uint8_t* mini_golf_peep_animation_frames[] = { mini_golf_peep_animation_frames_walk, mini_golf_peep_animation_frames_place_ball_downwards, mini_golf_peep_animation_frames_swing_left, mini_golf_peep_animation_frames_pickup_ball, mini_golf_peep_animation_frames_jump, mini_golf_peep_animation_frames_place_ball_upwards, mini_golf_peep_animation_frames_putt_left, mini_golf_peep_animation_frames_swing, mini_golf_peep_animation_frames_putt, }; const size_t mini_golf_peep_animation_lengths[] = { std::size(mini_golf_peep_animation_frames_walk), std::size(mini_golf_peep_animation_frames_place_ball_downwards), std::size(mini_golf_peep_animation_frames_swing_left), std::size(mini_golf_peep_animation_frames_pickup_ball), std::size(mini_golf_peep_animation_frames_jump), std::size(mini_golf_peep_animation_frames_place_ball_upwards), std::size(mini_golf_peep_animation_frames_putt_left), std::size(mini_golf_peep_animation_frames_swing), std::size(mini_golf_peep_animation_frames_putt), }; // clang-format on static paint_struct* mini_golf_paint_util_7c( paint_session* session, uint8_t direction, uint32_t image_id, int8_t x_offset, int8_t y_offset, int16_t bound_box_length_x, int16_t bound_box_length_y, int8_t bound_box_length_z, int16_t z_offset, int16_t bound_box_offset_x, int16_t bound_box_offset_y, int16_t bound_box_offset_z, uint32_t rotation) { if (direction & 1) { return PaintAddImageAsParent( session, image_id, { y_offset, x_offset, z_offset }, { bound_box_length_y, bound_box_length_x, bound_box_length_z }, { bound_box_offset_y, bound_box_offset_x, bound_box_offset_z }); } return PaintAddImageAsParent( session, image_id, { x_offset, y_offset, z_offset }, { bound_box_length_x, bound_box_length_y, bound_box_length_z }, { bound_box_offset_x, bound_box_offset_y, bound_box_offset_z }); } static bool mini_golf_paint_util_should_draw_fence(paint_session* session, const TrackElement& trackElement) { if (!session->DidPassSurface) { // Should be above ground (have passed surface rendering) return false; } const TileElement* surfaceElement = session->SurfaceElement; if (surfaceElement->base_height != trackElement.base_height) { return true; } if (surfaceElement->AsSurface()->GetSlope() != TILE_ELEMENT_SLOPE_FLAT) { return true; } return false; } /** rct2: 0x0087F10C */ static void paint_mini_golf_track_flat( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; if (direction & 1) { imageId = SPR_MINI_GOLF_FLAT_NW_SE | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 20, 32, 1 }, { 6, 0, height }); paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); } else { imageId = SPR_MINI_GOLF_FLAT_SW_NE | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 32, 20, 1 }, { 0, 6, height }); paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); } metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_D0 | SEGMENT_C4 | SEGMENT_CC, direction), 0xFFFF, 0); if (mini_golf_paint_util_should_draw_fence(session, trackElement)) { if (direction & 1) { imageId = SPR_MINI_GOLF_FLAT_FENCE_BACK_NW_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 1, 32, 7 }, { 10, 0, height + 2 }); imageId = SPR_MINI_GOLF_FLAT_FENCE_FRONT_NW_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 1, 32, 7 }, { 22, 0, height + 2 }); } else { imageId = SPR_MINI_GOLF_FLAT_FENCE_BACK_SW_NE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 32, 1, 7 }, { 0, 10, height + 2 }); imageId = SPR_MINI_GOLF_FLAT_FENCE_FRONT_SW_NE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 32, 1, 7 }, { 0, 22, height + 2 }); } } paint_util_set_general_support_height(session, height + 32, 0x20); } /** rct2: 0x0087F11C */ static void paint_mini_golf_track_25_deg_up( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; imageId = mini_golf_track_sprites_25_deg_up[direction][0] | session->TrackColours[SCHEME_TRACK]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 20, 1, height, 0, 6, height, session->CurrentRotation); metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 8, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_D0 | SEGMENT_C4 | SEGMENT_CC, direction), 0xFFFF, 0); imageId = mini_golf_track_sprites_25_deg_up[direction][1] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 15, height, 0, 10, height + 2, session->CurrentRotation); imageId = mini_golf_track_sprites_25_deg_up[direction][2] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 15, height, 0, 22, height + 2, session->CurrentRotation); switch (direction) { case 0: paint_util_push_tunnel_left(session, height - 8, TUNNEL_1); break; case 1: paint_util_push_tunnel_right(session, height + 8, TUNNEL_2); break; case 2: paint_util_push_tunnel_left(session, height + 8, TUNNEL_2); break; case 3: paint_util_push_tunnel_right(session, height - 8, TUNNEL_1); break; } paint_util_set_general_support_height(session, height + 56, 0x20); } /** rct2: 0x0087F12C */ static void paint_mini_golf_track_flat_to_25_deg_up( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; imageId = mini_golf_track_sprites_flat_to_25_deg_up[direction][0] | session->TrackColours[SCHEME_TRACK]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 20, 1, height, 0, 6, height, session->CurrentRotation); metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_D0 | SEGMENT_C4 | SEGMENT_CC, direction), 0xFFFF, 0); imageId = mini_golf_track_sprites_flat_to_25_deg_up[direction][1] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 11, height, 0, 10, height + 2, session->CurrentRotation); imageId = mini_golf_track_sprites_flat_to_25_deg_up[direction][2] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 11, height, 0, 22, height + 2, session->CurrentRotation); switch (direction) { case 0: paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; case 1: paint_util_push_tunnel_right(session, height, TUNNEL_2); break; case 2: paint_util_push_tunnel_left(session, height, TUNNEL_2); break; case 3: paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; } paint_util_set_general_support_height(session, height + 48, 0x20); } /** rct2: 0x0087F13C */ static void paint_mini_golf_track_25_deg_up_to_flat( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; imageId = mini_golf_track_sprites_25_deg_up_to_flat[direction][0] | session->TrackColours[SCHEME_TRACK]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 20, 1, height, 0, 6, height, session->CurrentRotation); metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 8, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_D0 | SEGMENT_C4 | SEGMENT_CC, direction), 0xFFFF, 0); imageId = mini_golf_track_sprites_25_deg_up_to_flat[direction][1] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 11, height, 0, 10, height + 2, session->CurrentRotation); imageId = mini_golf_track_sprites_25_deg_up_to_flat[direction][2] | session->TrackColours[SCHEME_MISC]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 1, 11, height, 0, 22, height + 2, session->CurrentRotation); switch (direction) { case 0: paint_util_push_tunnel_left(session, height - 8, TUNNEL_0); break; case 1: paint_util_push_tunnel_right(session, height + 8, TUNNEL_PATH_AND_MINI_GOLF); break; case 2: paint_util_push_tunnel_left(session, height + 8, TUNNEL_PATH_AND_MINI_GOLF); break; case 3: paint_util_push_tunnel_right(session, height - 8, TUNNEL_0); break; } paint_util_set_general_support_height(session, height + 40, 0x20); } /** rct2: 0x0087F14C */ static void paint_mini_golf_track_25_deg_down( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_track_25_deg_up(session, ride, trackSequence, (direction + 2) % 4, height, trackElement); } /** rct2: 0x0087F15C */ static void paint_mini_golf_track_flat_to_25_deg_down( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_track_25_deg_up_to_flat(session, ride, trackSequence, (direction + 2) % 4, height, trackElement); } /** rct2: 0x0087F16C */ static void paint_mini_golf_track_25_deg_down_to_flat( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_track_flat_to_25_deg_up(session, ride, trackSequence, (direction + 2) % 4, height, trackElement); } /** rct2: 0x0087F17C, 0x0087F18C, 0x0087F19C */ static void paint_mini_golf_station( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { if (ride == nullptr) return; auto stationObj = ride_get_station_object(ride); uint32_t imageId; bool hasFence; imageId = SPR_MINI_GOLF_STATION_FLOOR | session->TrackColours[SCHEME_TRACK]; mini_golf_paint_util_7c(session, direction, imageId, 0, 0, 32, 28, 1, height, 0, 0, height, session->CurrentRotation); if (direction & 1) { hasFence = track_paint_util_has_fence(EDGE_NE, session->MapPosition, trackElement, ride, session->CurrentRotation); if (hasFence) { imageId = SPR_MINI_GOLF_FLAT_FENCE_BACK_NW_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { -10, 0, height }, { 1, 32, 7 }, { 0, 0, height + 2 }); } bool hasSWFence = track_paint_util_has_fence( EDGE_SW, session->MapPosition, trackElement, ride, session->CurrentRotation); if (hasFence) { imageId = SPR_MINI_GOLF_FLAT_FENCE_FRONT_NW_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 10, 0, height }, { 1, 32, 7 }, { 31, 0, height + 2 }); } track_paint_util_draw_station_covers(session, EDGE_NE, hasFence, stationObj, height); track_paint_util_draw_station_covers(session, EDGE_SW, hasSWFence, stationObj, height); // Was leftwards tunnel in game, seems odd paint_util_push_tunnel_right(session, height, TUNNEL_SQUARE_FLAT); } else { hasFence = track_paint_util_has_fence(EDGE_NW, session->MapPosition, trackElement, ride, session->CurrentRotation); if (hasFence) { imageId = SPR_MINI_GOLF_FLAT_FENCE_BACK_SW_NE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, -10, height }, { 32, 1, 7 }, { 0, 0, height + 2 }); } bool hasSEFence = track_paint_util_has_fence( EDGE_SE, session->MapPosition, trackElement, ride, session->CurrentRotation); if (hasFence) { imageId = SPR_MINI_GOLF_FLAT_FENCE_FRONT_SW_NE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 10, height }, { 32, 1, 7 }, { 0, 31, height + 2 }); } track_paint_util_draw_station_covers(session, EDGE_NW, hasFence, stationObj, height); track_paint_util_draw_station_covers(session, EDGE_SE, hasSEFence, stationObj, height); paint_util_push_tunnel_left(session, height, TUNNEL_SQUARE_FLAT); } wooden_a_supports_paint_setup(session, (direction & 1), 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); paint_util_set_general_support_height(session, height + 32, 0x20); } /** rct2: 0x0087F1AC */ static void paint_mini_golf_track_left_quarter_turn_1_tile( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; track_paint_util_left_quarter_turn_1_tile_paint( session, 1, height, 0, direction, session->TrackColours[SCHEME_TRACK], mini_golf_track_sprites_quarter_turn_1_tile); metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height( session, paint_util_rotate_segments(SEGMENT_B8 | SEGMENT_C8 | SEGMENT_C4 | SEGMENT_D0, direction), 0xFFFF, 0); const bool shouldDrawFence = mini_golf_paint_util_should_draw_fence(session, trackElement); switch (direction) { case 0: paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); if (!shouldDrawFence) break; imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_SW_NW | session->TrackColours[SCHEME_MISC]; PaintAddImageAsChild(session, imageId, 0, 0, 26, 24, 1, height, 6, 2, height); break; case 1: if (!shouldDrawFence) break; imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_NW_NE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsChild(session, imageId, 0, 0, 26, 26, 1, height, 0, 0, height); break; case 2: paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); if (!shouldDrawFence) break; imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_NE_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsChild(session, imageId, 0, 0, 24, 26, 1, height, 2, 6, height); break; case 3: paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); if (!shouldDrawFence) break; imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_BACK_SE_SW | session->TrackColours[SCHEME_MISC]; PaintAddImageAsChild(session, imageId, 0, 0, 24, 24, 1, height, 6, 6, height); break; } if (shouldDrawFence) { // TODO: The back fence uses the same x/y offsets, but uses another paint function. See if this occurs more often. track_paint_util_left_quarter_turn_1_tile_paint( session, 0, height, 24, direction, session->TrackColours[SCHEME_MISC], mini_golf_track_sprites_quarter_turn_1_tile_fence_front); switch (direction) { case 0: imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_INSIDE_SW_NW | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 5, 5, 5 }, { 24, 0, height + 2 }); break; case 2: imageId = SPR_MINI_GOLF_QUARTER_TURN_1_TILE_FENCE_INSIDE_NE_SE | session->TrackColours[SCHEME_MISC]; PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 5, 5, 5 }, { 0, 24, height + 2 }); break; } } paint_util_set_general_support_height(session, height + 32, 0x20); } /** rct2: 0x0087F1BC */ static void paint_mini_golf_track_right_quarter_turn_1_tile( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_track_left_quarter_turn_1_tile(session, ride, trackSequence, (direction + 3) % 4, height, trackElement); } static void paint_mini_golf_hole_ab( paint_session* session, uint8_t trackSequence, uint8_t direction, int32_t height, const uint32_t sprites[4][2][2]) { uint32_t imageId; CoordsXY boundBox, boundBoxOffset; bool drewSupports = wooden_a_supports_paint_setup( session, (direction & 1), 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); paint_util_set_general_support_height(session, height + 32, 0x20); if ((direction == 0 && trackSequence == 0) || (direction == 2 && trackSequence == 1)) { paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); } else if ((direction == 3 && trackSequence == 0) || (direction == 1 && trackSequence == 1)) { paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); } if (direction & 1) { boundBox = { 26, 32 }; boundBoxOffset = { 3, 0 }; } else { boundBox = { 32, 26 }; boundBoxOffset = { 0, 3 }; } imageId = sprites[direction][trackSequence][1] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 0 }, { boundBoxOffset.x, boundBoxOffset.y, height + 24 }); if (drewSupports) { imageId = ((direction & 1) ? SPR_FLOOR_PLANKS_90_DEG : SPR_FLOOR_PLANKS) | session->TrackColours[SCHEME_SUPPORTS]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); imageId = sprites[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsChild( session, imageId, 0, 0, boundBox.x, boundBox.y, 1, height, boundBoxOffset.x, boundBoxOffset.y, height); } else { imageId = sprites[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); } } /** rct2: 0x0087F1CC */ static void paint_mini_golf_hole_a( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_hole_ab(session, trackSequence, direction, height, mini_golf_track_sprites_hole_a); } /** rct2: 0x0087F1DC */ static void paint_mini_golf_hole_b( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { paint_mini_golf_hole_ab(session, trackSequence, direction, height, mini_golf_track_sprites_hole_b); } /** rct2: 0x0087F1EC */ static void paint_mini_golf_hole_c( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; CoordsXY boundBox, boundBoxOffset; bool drewSupports = wooden_a_supports_paint_setup( session, (direction & 1), 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); paint_util_set_general_support_height(session, height + 32, 0x20); if ((direction == 0 && trackSequence == 0) || (direction == 2 && trackSequence == 1)) { paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); } else if ((direction == 3 && trackSequence == 0) || (direction == 1 && trackSequence == 1)) { paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); } if (direction & 1) { boundBox = { 26, 32 }; boundBoxOffset = { 3, 0 }; } else { boundBox = { 32, 26 }; boundBoxOffset = { 0, 3 }; } imageId = mini_golf_track_sprites_hole_c[direction][trackSequence][1] | session->TrackColours[SCHEME_TRACK]; switch ((direction << 4) | trackSequence) { case 0x01: case 0x20: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 26, 3 }, { 30, 3, height + 4 }); break; case 0x10: case 0x31: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 26, 2, 3 }, { 3, 30, height + 4 }); break; default: PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 0 }, { boundBoxOffset.x, boundBoxOffset.y, height + 24 }); break; } if (drewSupports) { imageId = ((direction & 1) ? SPR_FLOOR_PLANKS_90_DEG : SPR_FLOOR_PLANKS) | session->TrackColours[SCHEME_SUPPORTS]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); imageId = mini_golf_track_sprites_hole_c[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsChild( session, imageId, 0, 0, boundBox.x, boundBox.y, 1, height, boundBoxOffset.x, boundBoxOffset.y, height); } else { imageId = mini_golf_track_sprites_hole_c[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); } } /** rct2: 0x0087F1FC */ static void paint_mini_golf_hole_d( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; CoordsXY boundBox, boundBoxOffset; int32_t supportType = (direction & 1); if (trackSequence == 2) supportType = 1 - supportType; bool drewSupports = wooden_a_supports_paint_setup(session, supportType, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); paint_util_set_general_support_height(session, height + 32, 0x20); switch ((direction << 4) | trackSequence) { case 0x00: case 0x12: paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; case 0x02: case 0x30: paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; } if (supportType & 1) { boundBox = { 26, 32 }; boundBoxOffset = { 3, 0 }; } else { boundBox = { 32, 26 }; boundBoxOffset = { 0, 3 }; } imageId = mini_golf_track_sprites_hole_d[direction][trackSequence][1] | session->TrackColours[SCHEME_TRACK]; switch ((direction << 4) | trackSequence) { case 0x01: case 0x32: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 26, 3 }, { 30, 3, height + 4 }); break; case 0x02: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 23, 2, 3 }, { 3, 30, height + 4 }); break; case 0x10: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 24, 3 }, { 30, 3, height + 4 }); break; case 0x20: case 0x31: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 26, 2, 3 }, { 3, 30, height + 4 }); break; default: PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 0 }, { boundBoxOffset.x, boundBoxOffset.y, height + 24 }); break; } switch ((direction << 4) | trackSequence) { case 0x02: boundBox = { 23, 32 }; break; case 0x10: boundBox = { 24, 32 }; break; } if (drewSupports) { imageId = ((supportType & 1) ? SPR_FLOOR_PLANKS_90_DEG : SPR_FLOOR_PLANKS) | session->TrackColours[SCHEME_SUPPORTS]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); imageId = mini_golf_track_sprites_hole_d[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsChild( session, imageId, 0, 0, boundBox.x, boundBox.y, 1, height, boundBoxOffset.x, boundBoxOffset.y, height); } else { imageId = mini_golf_track_sprites_hole_d[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); } } /** rct2: 0x0087F1FC */ static void paint_mini_golf_hole_e( paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height, const TrackElement& trackElement) { uint32_t imageId; CoordsXY boundBox, boundBoxOffset; int32_t supportType = (direction & 1); if (trackSequence == 2) supportType = 1 - supportType; bool drewSupports = wooden_a_supports_paint_setup(session, supportType, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); paint_util_set_general_support_height(session, height + 32, 0x20); switch ((direction << 4) | trackSequence) { case 0x00: case 0x12: paint_util_push_tunnel_left(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; case 0x02: case 0x30: paint_util_push_tunnel_right(session, height, TUNNEL_PATH_AND_MINI_GOLF); break; } if (supportType & 1) { boundBox = { 26, 32 }; boundBoxOffset = { 3, 0 }; } else { boundBox = { 32, 26 }; boundBoxOffset = { 0, 3 }; } imageId = mini_golf_track_sprites_hole_e[direction][trackSequence][1] | session->TrackColours[SCHEME_TRACK]; switch ((direction << 4) | trackSequence) { case 0x01: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 26, 3 }, { 30, 3, height + 4 }); break; case 0x02: case 0x20: case 0x31: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 26, 2, 3 }, { 3, 30, height + 4 }); break; case 0x10: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 24, 3 }, { 30, 3, height + 4 }); break; case 0x32: PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 23, 3 }, { 30, 3, height + 4 }); break; default: PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 0 }, { boundBoxOffset.x, boundBoxOffset.y, height + 24 }); break; } switch ((direction << 4) | trackSequence) { case 0x10: boundBox = { 24, 32 }; break; case 0x32: boundBox = { 32, 23 }; break; } if (drewSupports) { imageId = ((supportType & 1) ? SPR_FLOOR_PLANKS_90_DEG : SPR_FLOOR_PLANKS) | session->TrackColours[SCHEME_SUPPORTS]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); imageId = mini_golf_track_sprites_hole_e[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsChild( session, imageId, 0, 0, boundBox.x, boundBox.y, 1, height, boundBoxOffset.x, boundBoxOffset.y, height); } else { imageId = mini_golf_track_sprites_hole_e[direction][trackSequence][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParent( session, imageId, { 0, 0, height }, { boundBox.x, boundBox.y, 1 }, { boundBoxOffset.x, boundBoxOffset.y, height }); } } /** * rct2: 0x0087EDC4 */ TRACK_PAINT_FUNCTION get_track_paint_function_mini_golf(int32_t trackType) { switch (trackType) { case TrackElemType::Flat: return paint_mini_golf_track_flat; case TrackElemType::BeginStation: case TrackElemType::MiddleStation: case TrackElemType::EndStation: return paint_mini_golf_station; case TrackElemType::Up25: return paint_mini_golf_track_25_deg_up; case TrackElemType::FlatToUp25: return paint_mini_golf_track_flat_to_25_deg_up; case TrackElemType::Up25ToFlat: return paint_mini_golf_track_25_deg_up_to_flat; case TrackElemType::Down25: return paint_mini_golf_track_25_deg_down; case TrackElemType::FlatToDown25: return paint_mini_golf_track_flat_to_25_deg_down; case TrackElemType::Down25ToFlat: return paint_mini_golf_track_25_deg_down_to_flat; case TrackElemType::LeftQuarterTurn1Tile: return paint_mini_golf_track_left_quarter_turn_1_tile; case TrackElemType::RightQuarterTurn1Tile: return paint_mini_golf_track_right_quarter_turn_1_tile; case TrackElemType::MinigolfHoleA: return paint_mini_golf_hole_a; case TrackElemType::MinigolfHoleB: return paint_mini_golf_hole_b; case TrackElemType::MinigolfHoleC: return paint_mini_golf_hole_c; case TrackElemType::MinigolfHoleD: return paint_mini_golf_hole_d; case TrackElemType::MinigolfHoleE: return paint_mini_golf_hole_e; } return nullptr; } /** * rct2: 0x006D42F0 */ void vehicle_visual_mini_golf_player( paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const Vehicle* vehicle) { if (vehicle->num_peeps == 0) { return; } rct_drawpixelinfo* edi = &session->DPI; if (edi->zoom_level >= 2) { return; } if (session->ViewFlags & VIEWPORT_FLAG_INVISIBLE_PEEPS) { return; } auto ride = vehicle->GetRide(); if (ride == nullptr) return; auto rideEntry = ride->GetRideEntry(); if (rideEntry == nullptr) return; auto* peep = GetEntity(vehicle->peep[0]); if (peep == nullptr) return; uint8_t frame = mini_golf_peep_animation_frames[EnumValue(vehicle->mini_golf_current_animation)][vehicle->animation_frame]; uint32_t ebx = (frame << 2) + (imageDirection >> 3); uint32_t image_id = rideEntry->vehicles[0].base_image_id + 1 + ebx; uint32_t peep_palette = peep->TshirtColour << 19 | peep->TrousersColour << 24 | 0x0A0000000; PaintAddImageAsParent(session, image_id | peep_palette, { 0, 0, z }, { 1, 1, 11 }, { 0, 0, z + 5 }); } /** * rct2: 0x006D43C6 */ void vehicle_visual_mini_golf_ball( paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const Vehicle* vehicle) { if (vehicle->mini_golf_current_animation != MiniGolfAnimation::PlaceBallDown) { return; } rct_drawpixelinfo* edi = &session->DPI; if (edi->zoom_level >= 1) { return; } if (session->ViewFlags & VIEWPORT_FLAG_INVISIBLE_PEEPS) { return; } auto ride = vehicle->GetRide(); if (ride == nullptr) return; auto rideEntry = ride->GetRideEntry(); if (rideEntry == nullptr) return; uint32_t image_id = rideEntry->vehicles[0].base_image_id; PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 1, 1, 0 }, { 0, 0, z + 3 }); }