From 79730e50fd7250dee4e2b0776897a3b0f93833fe Mon Sep 17 00:00:00 2001 From: spacek531 Date: Fri, 28 Jan 2022 00:46:35 -0800 Subject: [PATCH] Diagonal Brakes and Block Brakes --- resources/g2/sprites.json | 300 ++++++++++++++++++ .../g2/track/bm_invert/brake_horizontal.png | Bin 0 -> 987 bytes .../g2/track/bm_invert/brake_vertical.png | Bin 0 -> 1194 bytes .../blockbrake_horizontal_closed.png | Bin 0 -> 1027 bytes .../corkscrew/blockbrake_horizontal_open.png | Bin 0 -> 1016 bytes .../corkscrew/blockbrake_vertical_closed.png | Bin 0 -> 1104 bytes .../corkscrew/blockbrake_vertical_open.png | Bin 0 -> 1100 bytes .../g2/track/corkscrew/brake_horizontal.png | Bin 0 -> 1037 bytes .../g2/track/corkscrew/brake_vertical.png | Bin 0 -> 1120 bytes .../junior/blockbrake_horizontal_closed.png | Bin 0 -> 1026 bytes .../junior/blockbrake_horizontal_open.png | Bin 0 -> 1014 bytes .../junior/blockbrake_vertical_closed.png | Bin 0 -> 1059 bytes .../track/junior/blockbrake_vertical_open.png | Bin 0 -> 1055 bytes .../g2/track/junior/brake_horizontal.png | Bin 0 -> 1037 bytes resources/g2/track/junior/brake_vertical.png | Bin 0 -> 1069 bytes .../lim/blockbrake_horizontal_closed.png | Bin 0 -> 1002 bytes .../track/lim/blockbrake_horizontal_open.png | Bin 0 -> 999 bytes .../track/lim/blockbrake_vertical_closed.png | Bin 0 -> 1021 bytes .../g2/track/lim/blockbrake_vertical_open.png | Bin 0 -> 1026 bytes resources/g2/track/lim/brake_horizontal.png | Bin 0 -> 1011 bytes resources/g2/track/lim/brake_vertical.png | Bin 0 -> 1063 bytes .../g2/track/looping/brake_horizontal.png | Bin 0 -> 1060 bytes resources/g2/track/looping/brake_vertical.png | Bin 0 -> 1055 bytes .../blockbrake_horizontal_closed.png | Bin 0 -> 1104 bytes .../minetrain/blockbrake_horizontal_open.png | Bin 0 -> 1096 bytes .../minetrain/blockbrake_vertical_closed.png | Bin 0 -> 1183 bytes .../minetrain/blockbrake_vertical_open.png | Bin 0 -> 1196 bytes .../g2/track/minetrain/brake_horizontal.png | Bin 0 -> 1136 bytes .../g2/track/minetrain/brake_vertical.png | Bin 0 -> 1206 bytes .../inverted_blockbrake_horizontal.png | Bin 0 -> 1145 bytes .../inverted_blockbrake_vertical_closed.png | Bin 0 -> 1202 bytes .../inverted_blockbrake_vertical_open.png | Bin 0 -> 1205 bytes .../multidim/inverted_brake_horizontal.png | Bin 0 -> 1162 bytes .../multidim/inverted_brake_vertical.png | Bin 0 -> 1205 bytes .../upright_blockbrake_horizontal_closed.png | Bin 0 -> 1190 bytes .../upright_blockbrake_horizontal_open.png | Bin 0 -> 1182 bytes .../upright_blockbrake_vertical_closed.png | Bin 0 -> 1158 bytes .../upright_blockbrake_vertical_open.png | Bin 0 -> 1174 bytes .../multidim/upright_brake_horizontal.png | Bin 0 -> 1189 bytes .../track/multidim/upright_brake_vertical.png | Bin 0 -> 1175 bytes .../g2/track/slc/blockbrake_vertical_open.png | Bin 0 -> 1144 bytes resources/g2/track/slc/brake_horizontal.png | Bin 0 -> 1052 bytes resources/g2/track/slc/brake_vertical.png | Bin 0 -> 1142 bytes .../standup/blockbrake_horizontal_closed.png | Bin 0 -> 1046 bytes .../standup/blockbrake_horizontal_open.png | Bin 0 -> 1049 bytes .../standup/blockbrake_vertical_closed.png | Bin 0 -> 1105 bytes .../standup/blockbrake_vertical_open.png | Bin 0 -> 1101 bytes .../g2/track/standup/brake_horizontal.png | Bin 0 -> 1049 bytes resources/g2/track/standup/brake_vertical.png | Bin 0 -> 1149 bytes .../track/steeplechase/brake_horizontal.png | Bin 0 -> 1014 bytes .../g2/track/steeplechase/brake_vertical.png | Bin 0 -> 964 bytes src/openrct2-ui/ride/Construction.h | 24 ++ src/openrct2-ui/windows/Ride.cpp | 3 +- src/openrct2-ui/windows/RideConstruction.cpp | 1 + src/openrct2/actions/TrackPlaceAction.cpp | 2 + src/openrct2/actions/TrackRemoveAction.cpp | 1 + .../actions/TrackSetBrakeSpeedAction.cpp | 4 +- src/openrct2/ride/Ride.cpp | 70 ++-- src/openrct2/ride/Ride.h | 4 +- src/openrct2/ride/RideConstruction.cpp | 8 + src/openrct2/ride/RideConstruction.h | 3 - src/openrct2/ride/Track.cpp | 31 +- src/openrct2/ride/Track.h | 13 +- src/openrct2/ride/TrackData.cpp | 37 ++- src/openrct2/ride/TrackPaint.cpp | 14 + src/openrct2/ride/TrackPaint.h | 3 + src/openrct2/ride/Vehicle.cpp | 31 +- src/openrct2/ride/VehicleSubpositionData.cpp | 2 + .../ride/coaster/CompactInvertedCoaster.cpp | 67 ++++ .../ride/coaster/CorkscrewRollerCoaster.cpp | 65 ++++ .../ride/coaster/InvertedRollerCoaster.cpp | 31 ++ .../ride/coaster/JuniorRollerCoaster.cpp | 212 ++++++++----- .../ride/coaster/LayDownRollerCoaster.cpp | 129 ++++++++ .../ride/coaster/LimLaunchedRollerCoaster.cpp | 65 ++++ .../ride/coaster/LoopingRollerCoaster.cpp | 31 ++ .../ride/coaster/MineTrainCoaster.cpp | 72 +++++ .../coaster/MultiDimensionRollerCoaster.cpp | 131 ++++++++ .../ride/coaster/StandUpRollerCoaster.cpp | 64 ++++ src/openrct2/ride/coaster/Steeplechase.cpp | 29 ++ .../coaster/meta/CompactInvertedCoaster.h | 2 +- .../coaster/meta/CorkscrewRollerCoaster.h | 2 +- .../ride/coaster/meta/InvertedRollerCoaster.h | 2 +- .../coaster/meta/LIMLaunchedRollerCoaster.h | 2 +- .../ride/coaster/meta/LayDownRollerCoaster.h | 2 +- .../ride/coaster/meta/LoopingRollerCoaster.h | 2 +- .../meta/MultiDimensionRollerCoaster.h | 2 +- .../ride/coaster/meta/StandUpRollerCoaster.h | 2 +- src/openrct2/sprites.h | 17 +- src/openrct2/world/TileElement.h | 2 + 89 files changed, 1335 insertions(+), 147 deletions(-) create mode 100644 resources/g2/track/bm_invert/brake_horizontal.png create mode 100644 resources/g2/track/bm_invert/brake_vertical.png create mode 100644 resources/g2/track/corkscrew/blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/corkscrew/blockbrake_horizontal_open.png create mode 100644 resources/g2/track/corkscrew/blockbrake_vertical_closed.png create mode 100644 resources/g2/track/corkscrew/blockbrake_vertical_open.png create mode 100644 resources/g2/track/corkscrew/brake_horizontal.png create mode 100644 resources/g2/track/corkscrew/brake_vertical.png create mode 100644 resources/g2/track/junior/blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/junior/blockbrake_horizontal_open.png create mode 100644 resources/g2/track/junior/blockbrake_vertical_closed.png create mode 100644 resources/g2/track/junior/blockbrake_vertical_open.png create mode 100644 resources/g2/track/junior/brake_horizontal.png create mode 100644 resources/g2/track/junior/brake_vertical.png create mode 100644 resources/g2/track/lim/blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/lim/blockbrake_horizontal_open.png create mode 100644 resources/g2/track/lim/blockbrake_vertical_closed.png create mode 100644 resources/g2/track/lim/blockbrake_vertical_open.png create mode 100644 resources/g2/track/lim/brake_horizontal.png create mode 100644 resources/g2/track/lim/brake_vertical.png create mode 100644 resources/g2/track/looping/brake_horizontal.png create mode 100644 resources/g2/track/looping/brake_vertical.png create mode 100644 resources/g2/track/minetrain/blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/minetrain/blockbrake_horizontal_open.png create mode 100644 resources/g2/track/minetrain/blockbrake_vertical_closed.png create mode 100644 resources/g2/track/minetrain/blockbrake_vertical_open.png create mode 100644 resources/g2/track/minetrain/brake_horizontal.png create mode 100644 resources/g2/track/minetrain/brake_vertical.png create mode 100644 resources/g2/track/multidim/inverted_blockbrake_horizontal.png create mode 100644 resources/g2/track/multidim/inverted_blockbrake_vertical_closed.png create mode 100644 resources/g2/track/multidim/inverted_blockbrake_vertical_open.png create mode 100644 resources/g2/track/multidim/inverted_brake_horizontal.png create mode 100644 resources/g2/track/multidim/inverted_brake_vertical.png create mode 100644 resources/g2/track/multidim/upright_blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/multidim/upright_blockbrake_horizontal_open.png create mode 100644 resources/g2/track/multidim/upright_blockbrake_vertical_closed.png create mode 100644 resources/g2/track/multidim/upright_blockbrake_vertical_open.png create mode 100644 resources/g2/track/multidim/upright_brake_horizontal.png create mode 100644 resources/g2/track/multidim/upright_brake_vertical.png create mode 100644 resources/g2/track/slc/blockbrake_vertical_open.png create mode 100644 resources/g2/track/slc/brake_horizontal.png create mode 100644 resources/g2/track/slc/brake_vertical.png create mode 100644 resources/g2/track/standup/blockbrake_horizontal_closed.png create mode 100644 resources/g2/track/standup/blockbrake_horizontal_open.png create mode 100644 resources/g2/track/standup/blockbrake_vertical_closed.png create mode 100644 resources/g2/track/standup/blockbrake_vertical_open.png create mode 100644 resources/g2/track/standup/brake_horizontal.png create mode 100644 resources/g2/track/standup/brake_vertical.png create mode 100644 resources/g2/track/steeplechase/brake_horizontal.png create mode 100644 resources/g2/track/steeplechase/brake_vertical.png diff --git a/resources/g2/sprites.json b/resources/g2/sprites.json index 40d397ca9c..6ad0d77b57 100644 --- a/resources/g2/sprites.json +++ b/resources/g2/sprites.json @@ -24488,5 +24488,305 @@ "x_offset": -5, "y_offset": -20, "palette": "keep" + }, + { + "path": "track/junior/brake_horizontal.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/junior/brake_vertical.png", + "x_offset": -9, + "y_offset": -4, + "palette": "keep" + }, + { + "path": "track/junior/blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/junior/blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/junior/blockbrake_vertical_closed.png", + "x_offset": -9, + "y_offset": -4, + "palette": "keep" + }, + { + "path": "track/junior/blockbrake_vertical_open.png", + "x_offset": -9, + "y_offset": -4, + "palette": "keep" + }, + { + "path": "track/corkscrew/brake_horizontal.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/corkscrew/brake_vertical.png", + "x_offset": -13, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/corkscrew/blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/corkscrew/blockbrake_vertical_closed.png", + "x_offset": -13, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/corkscrew/blockbrake_vertical_open.png", + "x_offset": -13, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/slc/brake_horizontal.png", + "x_offset": -32, + "y_offset": 4, + "palette": "keep" + }, + { + "path": "track/slc/brake_vertical.png", + "x_offset": -13, + "y_offset": -9, + "palette": "keep" + }, + { + "path": "track/slc/blockbrake_vertical_open.png", + "x_offset": -13, + "y_offset": -9, + "palette": "keep" + }, + { + "path": "track/multidim/upright_brake_horizontal.png", + "x_offset": -32, + "y_offset": 3, + "palette": "keep" + }, + { + "path": "track/multidim/upright_brake_vertical.png", + "x_offset": -11, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/multidim/upright_blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 3, + "palette": "keep" + }, + { + "path": "track/multidim/upright_blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 3, + "palette": "keep" + }, + { + "path": "track/multidim/upright_blockbrake_vertical_closed.png", + "x_offset": -11, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/multidim/upright_blockbrake_vertical_open.png", + "x_offset": -11, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/multidim/inverted_brake_horizontal.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/multidim/inverted_brake_vertical.png", + "x_offset": -11, + "y_offset": -12, + "palette": "keep" + }, + { + "path": "track/multidim/inverted_blockbrake_horizontal.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/multidim/inverted_blockbrake_vertical_open.png", + "x_offset": -11, + "y_offset": -12, + "palette": "keep" + }, + { + "path": "track/multidim/inverted_blockbrake_vertical_closed.png", + "x_offset": -11, + "y_offset": -12, + "palette": "keep" + }, + { + "path": "track/steeplechase/brake_horizontal.png", + "x_offset": -32, + "y_offset": 9, + "palette": "keep" + }, + { + "path": "track/steeplechase/brake_vertical.png", + "x_offset": -4, + "y_offset": -6, + "palette": "keep" + }, + { + "path": "track/standup/brake_horizontal.png", + "x_offset": -32, + "y_offset": 1, + "palette": "keep" + }, + { + "path": "track/standup/brake_vertical.png", + "x_offset": -13, + "y_offset": -9, + "palette": "keep" + }, + { + "path": "track/standup/blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 1, + "palette": "keep" + }, + { + "path": "track/standup/blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 1, + "palette": "keep" + }, + { + "path": "track/standup/blockbrake_vertical_closed.png", + "x_offset": -13, + "y_offset": -9, + "palette": "keep" + }, + { + "path": "track/standup/blockbrake_vertical_open.png", + "x_offset": -13, + "y_offset": -9, + "palette": "keep" + }, + { + "path": "track/minetrain/brake_horizontal.png", + "x_offset": -32, + "y_offset": 6, + "palette": "keep" + }, + { + "path": "track/minetrain/brake_vertical.png", + "x_offset": -17, + "y_offset": -3, + "palette": "keep" + }, + { + "path": "track/minetrain/blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 6, + "palette": "keep" + }, + { + "path": "track/minetrain/blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 6, + "palette": "keep" + }, + { + "path": "track/minetrain/blockbrake_vertical_closed.png", + "x_offset": -17, + "y_offset": -3, + "palette": "keep" + }, + { + "path": "track/minetrain/blockbrake_vertical_open.png", + "x_offset": -17, + "y_offset": -3, + "palette": "keep" + }, + { + "path": "track/looping/brake_horizontal.png", + "x_offset": -32, + "y_offset": 0, + "palette": "keep" + }, + { + "path": "track/looping/brake_vertical.png", + "x_offset": -15, + "y_offset": -8, + "palette": "keep" + }, + { + "path": "track/lim/brake_horizontal.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/lim/brake_vertical.png", + "x_offset": -10, + "y_offset": -5, + "palette": "keep" + }, + { + "path": "track/lim/blockbrake_horizontal_closed.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/lim/blockbrake_horizontal_open.png", + "x_offset": -32, + "y_offset": 7, + "palette": "keep" + }, + { + "path": "track/lim/blockbrake_vertical_closed.png", + "x_offset": -10, + "y_offset": -5, + "palette": "keep" + }, + { + "path": "track/lim/blockbrake_vertical_open.png", + "x_offset": -10, + "y_offset": -5, + "palette": "keep" + }, + { + "path": "track/bm_invert/brake_horizontal.png", + "x_offset": -32, + "y_offset": 2, + "palette": "keep" + }, + { + "path": "track/bm_invert/brake_vertical.png", + "x_offset": -13, + "y_offset": -13, + "palette": "keep" } ] diff --git a/resources/g2/track/bm_invert/brake_horizontal.png b/resources/g2/track/bm_invert/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..bbabcd6d7e446af9aad58b3a97f86e17d916e822 GIT binary patch literal 987 zcmWlYZ;0D;7{{Mmub2Dd=!+tm3tD%55ivrAya*B@J99@pBA0m?bR#daGuP!s7*TUl zUBwJLD3U?Y4ypvKkQWu=))$9Fu0oJ9j#(iu4y+iVLWg}ZAz)wBc`tru@O+;y4}5t( zFCL!HF71@huAW~7fV10gZtkXjF;#v!lXm>x>G!EUcd&KkKr*f$)b`%5!p6SwPW8p@ z8+%%Hx4O6g(R&Z8uLES@(p#6e((uB2wd1YkRhGr9yE3!<Cqi%jSB+#^k zW(qoW5E>K#L;wZDj9ktl2!|v+mOT{3V@(@b*5ghGg&{%biyU4O3#>wx4XR?%s>7Nt z-|&T2U-E`Z5Nid7D3yz>L`iO^#5tMurl+GhTBC9~ z2FJ^VqC}NcmNf;jsie#5J-c<>?Zty=Hs(MPFjLA|O2N@7x6b)ZsqbpXzBLNn>1Z&U zJw_Zr1;7Mw0DORBfC&aDEs;lc6ZsyBMfHY#(No0Rk>(AT6(_oB7 z37H3`fR#%*nJefLUDpK1(!G||_gm4xpT+|;8#97{0zfe!1St#C_erNoH0qdMW!yI7 ze(6po=5WZkU-7am>AG648+56`l-eBa^K>YbPDE;2DI%qSEE2gi3OE!A2%*o-y!P}5 z4t94WxcJv^*VAEtdvoLRhrj>*g|K?-)n~HW^NIB`bMxGdKepv>|J}%l?@qpZLHcj` z!Yk_^D}S#4vTpr!|Ju<_>+Y?q|Lp(z?2iu~eL@Y%m$F}fP_-{S*;#mU{|BY*({tx|~qyhi{ literal 0 HcmV?d00001 diff --git a/resources/g2/track/bm_invert/brake_vertical.png b/resources/g2/track/bm_invert/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..4f0c0ed6133cf22b79ee10a6da64e5f65c8b710a GIT binary patch literal 1194 zcmWktacmQH6n@Z++Zd#1#cp(=EDbhrk`hk6Xh{w{W*s-UWrr4M+=)jiq?s4Fg@RR^ zSfD^PC)8MHks@a->=hJ{qDWQj}oS(5j?@B8EBeaZLo z4)(40%$>bpHUP}+d38;HgBLXLY>TPUd$o4`#V+6q`Nn$h_O(xUXtfuP|hEc262^UaqV3{_b&k_vULt$4e?oOuIOqS2(r9v@Y zt|&B)dEIRyV~u$2vfxZh#MvmFPkIYk(HM(W4P~mPdu+ht5TZclu#AZ1$ z2B(aXX{#se^yMkB=#7^pr6%j>EQ?zN(iZaIaj!cg&^d`KMuk#Rs;JRgJ~>rXQAIaf zNGI+k$N)u$I4&*-sZb~zkLT0rqNbH6CTg`B0-FfVBt~S+bk4>V@IaZ4ReVY{l&i@T z^=x&zG=WtN00}?_PyxmODj1+fu`~)xNL7$gVx1rokf1>GfWZRd0Et!< zCy>G-Er<#+WGL|X@FXxacv&ncSR)}kA$u~4kjq7jMYUQjqK20(07STrlC7*_=QXEj zxaFEpt%q_`$-=Z&Mx~n50;C=DxXeDv9^{B{fRQ6XB@xM~iK4Dn4IS0XB*P#LkO2rm z!wU;;b;>bYG>irPWGYFfK2KFDQlUVmhH0OV3kHR7SR`Cg(v_qLl_v6xYl6kAUI*gs zDB?sZ0%;T~G6D|o(jyrSn~F-L+tE@=7VpH{CsO5^W-H*&nag5 z*!6uS*B`A*zUjKV^V4Sr*WFmMY02Hq?|v0~0+w+|K6DsH#6$Wan-w~ilZtf~JVu=rDm#v!9lX!`@W9La zJn-^fKf9bfGX3H-032CboL?F8=^>6!hK7Cb$ty>P^up%Cg-ubpw3%D`U<2mXm5Upv zmM*VlHdZ#))<1mzr;XPELU8tta|^@ak&%(n(a}&SG&VLiK0ZD%F@a&&?NLyTMLI(yyUK~IGkT6UMhxJ&@AP9?Lb_8KJlWFPtex-t3H%3L`Y&0R@j6@_AGNn_p z!Kh^}Z}X+PXf-4!$l!D=k&H7U$;)(F;go_*6+cyMt5(nO(2hVxWIC2hlEoBLmASeq`gyr!svSGubIpNoqmCDj&;*&H z=nTu{M6oE#Oydv)Ah(h$%pr7*!2(^_bWoGi|QWNn71qy=OH0weCS{ zfM&>Wn2tu1cw8hCGQ+66P>_bpv|6#WTdf72-*2-Z@t7)xbqP1JWLabFf>!YDpECZA_!x~Y+!X<}L0>8?|~w1ZW&fCcqd}K%a_O{~&B~glP>DR9Fj>mxD3?z(1+trpBMC=3fyxweSmg5v zp-ex2`=dU3mMrmi}&b z>Ad<){_s7tJuc!S>UmvxoD+;ve+w_Ub?B&)SQ>U%63ye&^A< zdtbeJb+0*l=hlN??mqhWa iVaR=YU4QfMW2-=Ya_qkI)_rrB3zim^=f6F(y7fPhM#TyM literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/blockbrake_horizontal_open.png b/resources/g2/track/corkscrew/blockbrake_horizontal_open.png new file mode 100644 index 0000000000000000000000000000000000000000..b984b13158cb3f6b64c6fc5c6a0021b8e527479e GIT binary patch literal 1016 zcmWktZ;0D;7=G_>?vJyF{SaKxPOFO&uu6n{$Rs;+w|Zn;#%0h!k$B5>72*h*lTHgp zFG!UNLHeP0%b6L|*A)g%Lk*Tp^|NY-*=7#j>`r^5DNxQIKSbZx8^K07q+_9yL ztNGkYZguUQH-E^T02qTar_U}9het+6Mn^}-#>U3S$0sHxCMPE`44ayonx3A+lqoVP`b~H!=xJA!|ClZSsCK(`snZPN^3;2mK&TfJ{Mw153i{8s?W{?RtFBB2X`d z1~NLd5DJn2B7lrxS}bM|ghi4L%WjL}PCnl@jQv^-`949%lN_EB6Rb?8H7aA!ipAt9sWp`+oHxbWt~m#Tk;y&`h4= z3zAe;6uVGpl*@jt7J6Q1cemf~BOo*&s~BC6@l8T%QTYyE>Smo@q1m@~2aVog`vA>S zu^5Bn=|obZQVPrJf>@G=%ZiP1WvAYVf^g8`Ko&4viWzdkQYpL0xh1J-=XYGA?c2R} zFc|D34j==d16Tkqzz#qc12im=M@1dE4vN|$2^tL*4!kr(A|MHnhNCi#91(dcYL!sr zz=OjxAn=e8F;&5h0#&inbw_D7%`kL(y$}t(h&<56SmCn0;J7O_@8>kbOdgKF#0 z>!5a@j02Ov(y3UMOQ;fE%nO#GIu)boR>HvTMFARg7(qZDpa>9xp%?&h#+TE_+YBBZ}pUq0DsuYVFoidqJm7`sr_J!20NcA#FBqxwTBAZ4Yhe81%^r;@t zKlp+5m1PM|{rN!liFJ69a83S4rC_ zSDL!eMLaNtbYz+jQS#x?6bjyl2pLOlE%|WF!qWA?AYn!s5^Na7miaTn`@9eDm*?T( zec$EL5zp~s{l@^{`0$0Hu@?8YaIUAL)lbiFqZU0g;~t+8r0JQ+#I+y{PDzu&=Y~I; z2nEN26H{|nw}Wp2binAvOKyZvTU%RudwWMmM`veeS65eecQ=M%Jv}|Wy}dT4(@Byp zmSqHi6GfjaOR-oimCEGvda1NynvG_YbOA#H&-M9y)^OMniMrwmI+f;g`9Ps4myJZV zmSqXdOZQ2fP4PNZ5zolvdW|nKbIT>Os-MfK>on2pmzs zRgB8mJbBz#WF*6zsLI)fT0-kQVHGKR#6u*!bWUUovS7r-N=mM2u|_dP|CX zKdKy{KEh(5Y&MU>DG)A^re%(g2U=p$d?LA(%bO*mS!E!=VX|OR0uD7yq@#=$7Ygan zmZnsS>3XHqY(7K`fEPdpPysZ6Er1#Zs8u|RqB7F5$gJ==vn$2h_Q84Yo&63!--f|fK&THP$6W|iVNqysVmA!vDF z;VE2=+hb8I9Hi1ID!rPn)#P%SO5bFCJ|P?yqfv=;#VA*bAvKmPa;_bosC%6#;6MtF z(j?LuWN@wHKX+yHMC)PNX2wPYcDF+6cxdp_?B0*b*Po0HJmG#1zx`N!@LSKV z!Ni|uwz)NNZ1#nJx<31L_g~8ZEIoU;a`&k_&!7MFRojx;yuG;k_u>h+Z}3j%MRw!H z($40>7i+hI+T^bB!PSkg*F5fxANKa&p1*!_y7!wKAKsh$IP{wT{SumA-rf8zb>`Im z{_La4mmVY>UpkfExuM$ip>_X~?!Pt?y?NQa_gCFtJ{-Tdsrj+X8;{-?pL^_o<)_m> zC#jW_XFbc|`xo9ly!*+@sfoz9EB%M7x&EgY=(7iZlwa(3zWmF|Z0`VkRj!h@cNRWx Pg@j@E$k6xauPput%L?TL literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/blockbrake_vertical_open.png b/resources/g2/track/corkscrew/blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..56ace7ff31c9306ef696f3862fe4a9211d164c8f GIT binary patch literal 1100 zcmWkte`p(Z6n|~nUVj>Fz_3LcM;ymEX2e6!F0!+|maMzctG$iXMR#`BHo7Rc?Fv~N z#tm6wKyYqKu_*kIzw(b48`OG`^@Ypcy>Yinz3Z*TAD=)f?nv$M0StIO%}cu3OA zFf`Azq8OBANmbQEB9+bNip6!ysy7;>7ib@FY)>%g2#4K~s5hqh5=kzd74ikSWNMYF z!4O!$*CVk`CE(UYJSCIMDpN=VN?FNTjnyn;yI%CWKp-GOgU(}V2`gy!a@x@-xlqlE z8UotU5h{8BH~;~|B)eU4xpW*ie74+n{s*m9v@GzA{CSvDaOT8LMkWaOr>bW&04y$U9i*O;K3OJcNB0P zqf$k#a@+gck6nMJ6xvrYe>bay6sY3yEzrgQ`WlgTjdb zNrh-8!tT74FZeFyj>C8dYDK?=}e5zCqt_l zrCdnX%Ed-w3()`p02x3B$N;PYR53u!;usW_QN}=4nZrRMAx=Zi4;BZA2P8R>Mk0el zxiBilkY&K5!&AUA5a6(|=u{#^T=%C9F`rjWGgGUXsOjYj0U7O~bth-Ig&ZzfKD{2y zG$Q%!L}@2iLFGE`0LqQ|z4jpO4)bI*#Og}eh%5O_+$?5lRuMHS6w9IKZ13o?AUabaaR`P|~gue6EO?e_g1Jvemx+-G-w?LTz&!WY`qm4ANx zZs^VQ+2g{ij-~x?-MPGUf91yTgU9ytc3rpq{^h@?HjhQW?L%98Piol{mq&gsiT7_! z{obG^j-RN@$t>YwXLrcr#?B9f4C98h7H{K{=Wk^Rik=fYT@CD1%2>C{E5Sd z`(OF<_zROO==8zvk-M+$`~1Cw_XaBMr(=H&oF5!Le|_|sy_>DQ@O)rnx$o_7x|#uD NY;=6&=I|Tu{twIw+MWOa literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/brake_horizontal.png b/resources/g2/track/corkscrew/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..d66a9170c7569fefa50733a1be8c8fd6100f645b GIT binary patch literal 1037 zcmWktZ;0D;7=G_>?$2iD6;@`Ds%1nLFhV{=79l%xM?E5!aT#9?12gF)vIuolh;l;32%S{c4|focekk*VpB=o<`|!Za`#kXS zespm)d2;TlIRH4h^6Jvsh%bz=Ff%dge;z%5YD8x?moINh`qj_u+|b`lKeO`A zdM3S=Uf;NJ?SA@YfC;$x+NI^u@YvYc`1tt5#Kh#}ls8ni=hU0nrK@biGGzA*91Y!Nn*s&MHJwCsTP^HCdy| z7i^*2l&rSm1erL4Q^^D?k%G#|I{V$uFp#iqW$Rp<5aHHtKniC_|7bn#pi{ zR+37pTFqt~rIK5#`Hs`w-w(qO0j>j4!RUH~Z{kv$%yju;PqzBmW@zpY8vWzW5Y3a3 z2osAX;|YnRRF*Xav8are@ zJU%=F0uLz>)6`f#OP0-K-BO#)g74e?zK=#;cn0X)JZHv4E3P<%9NkwEXu1Rz*Bba&3D(9Pa+4t;z;Gsd65d`D_3IHJ(d12ZHVHWX14%5<1 zwZc?CtM+&v@IYRiUS zd*e@jI);C-BTwC;j`%Z|@Ba4H?pkR#`tQ!UZ|_|@RsE~e`6O{^dy+p`Tx&gBexH2q l?YF*H?i?(jm;O0@1%5UoXPb{GVU!S7mRFa)e&xys{{#KSz@`8I literal 0 HcmV?d00001 diff --git a/resources/g2/track/corkscrew/brake_vertical.png b/resources/g2/track/corkscrew/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..f039044a5e93fe472fb7c308c3d60876190d6474 GIT binary patch literal 1120 zcmWktaflRk6n@^`Ij5&iwAG?x%;gf34Kdmf6O1wHcx>l{b2-L_TQ}OcZn?#%bFp^w z$CeAOvdDDqA8RbR;8=@nxx{6It-94B$GOC0M{YLCLK|&iw!(r3o$_mi_q~q~9`EDh z@s5pc3oT!|YAFCLAANbt_8zb5VeO!=*H=%@q8_cB7sIRZj=kxXV_YVvVEMB}A!?3}@!6i$U1cJdJ z%QB)UD2k+M5yQ|^sZ=gkD3_gDZO-#L-7d?3z=JFeMI!!qoJ^QZI>YDka@$>N#i2AsHf$0K`l7C<0flf)@>J?^Hp2`zXE|6kS0(T z#uWmgG8L%`x*N_k4ZCC2(6mhZHI7Jx=uDU|YGTDu+?3YH8Ld*PQ_ao0CDf|nevYEU zEEf~Rgra0LEuTn~Gns0k;5troZm!emARu(0au{30#R{R+=~z=tw<2~sQR!H7-Ew=O zF^`659OnXo5E)cxM&o%ylGAE$nOV+cXNqO7=60I`s1jx6{> zqnd9wYTfQ_Bmjf~3;+wD1TX{8!T|M37LjS7l8wBEOo7fqRsbgio(xCpQoHS=tQnK6WZcdsE2XSkE495E>NYt^LJlAg5Q3f;7T-fz zX(DA}@hF$iaru+^R?Dc@x%?+$B%;LQnrZ4Rlj4}1z?MX|Dlv01-3|wlN}?o%@+@)$ zpz#%9lL z{OA6@@V?g`A9-_KA3L_@s{fY#`Q^=TT)TU>Jp7G1<@?NcY(IYX!~Rd7{rKwjlP^Bf za4znfo%{As|B0g;o;xx;e&@ijDSkh4_^Y6M>*DWUPI=?vR>PxLZheWl|AX`kp(s|H=cO^-p}VJubiG7fBVpd>;FclA6&V8 zkQwt&;rjf}d*<<@&n$l-c6{)$ou{7v`oXoEb!Yv%!spqaed?M&F_mR0TQrsW^H*gJT)~nJw2UBBxYu2W@l&T=H@UAo1dRwSXjU_nGD0w zg22nNsHz3S(5uyIqtR@){V?2*4N=e5ZddW+Qko^`Y=)C5QDqCdpx2~YQ)&9TADLlXkA|)OL6GDjB?Df9bOlHoW1D!k zO%?)PkMdUEa7T8Cb|fmLvP3ycS$VFd3LQg^s%o!c47}(P)H#(1C1VOe-mL2)Rp@`a*3`aEIm2$lf2fhljlbv`8hB zERJW>8JVJ0jx$85rc9Pq+E#tH)sDkx+~+|NF+)z8O4`;ar^0(Rx#N^}J+l`$!(KQZ z-$Xn>9>4&w0X%?RfB^<*Qj&lw2J&1K_aqW@2I@TcS%@V-G9VpC7K2;~`5NlhQ0&5; z!?Pd?ke4t`#mzERx3eu*?R2V9`}oRmpccI?xEjD zy%CuLHjQQJWPwj>GE*suwyC*wv*XpH&>O}f8uwXIL_VMx5Q2#prfraRji^>It;jkJ z*7?*K42*7*puJ$}OE literal 0 HcmV?d00001 diff --git a/resources/g2/track/junior/blockbrake_horizontal_open.png b/resources/g2/track/junior/blockbrake_horizontal_open.png new file mode 100644 index 0000000000000000000000000000000000000000..3c1ddb977c8ddf9bb9bce972cf8b3a2460e7d849 GIT binary patch literal 1014 zcmWktU5Mjk6utAC`L$xvsztNVhqy$^LvXVaAv0#iIz%SJWTCqh%#4{%l&pj`162zX zuq$<`8nj4V3s%iTmBL@3&afCa1Op`&HD$gK3C$~+YO?7}_waNu&!fy=$N zwV7OAcz6K-mN%YT+aB}E7)x_g<9_Q2VKkcfG{6*WJ%3?+JUlTmF*!LoH8nLoJv}osGdnwrVc6W<-2D7}ERjgiG{y6r zBngU=HVi$V&zH;9dfoN?b{GzZLz)7P1yNW`r=yyNXLD4c$d)T&tu8k_qZJgpJ)0-7 z6uYPkF*Ai*3Q;xaqdf1GQ?0rlHVggGJ{|bUILIVqIj|(Grej_)(y2vX4xZAY^rL0`{J<-p1`g`^ktjouDVk9^J}XH@ zMX6-7^glr z96$=d0I&cYfF?i>12is?M>zvIHVQi;0XhvO4%{S!A|MHn9z#VM*&=c^)GDCRhP#Jn zK;R)IVww^&vt-Fi)@-HG$OnPb?+0k?6<2}IEpk>&v~k%b^pLd%X=j*ioR(W7w~IOh zA_@$SC82S}mq>olmDFO;d6?ou={(Rpw}ir#*pci)25QKr)U@0##__awrfGLhl<<_3jTG zY;Q`ia{Jf)u`oB*RxiBv`&S>V-gEWL(mHzMr)#(W3ujL*E$v*n@2&Ipxf^$GF8{T7 z^D4{|Z*P8ocKG3W?a#}XAOHBN`;VSH`FiGo{m*wkd-l6_bBp^HzMLGWFI_)g__RIw zjZ$Cv2Ax7MGfWbuGtBvoZA(m z=0nhoWt!>XB4jRN+)hX_+6aZ^LzI-=Se1M@q=O9aLzGDKp-RwzaTffW!TY@*KX|;~ z4<7IRlP5w`d#3jQz*PA7d}P3n4DiIbXV5=dyxkbkqbmz9tw{R0mBiA8ILt2VXX7*B zHlraql#5lp>ZEKp=X6S~e%;G~PXfORL=s37 zV~YMzg^blX-HB#fhSfD~v@TLUg~1acDjQ`>3SToMC#^K|M!THu*7JR*jM}!>$Bk((NK#f&3W-D|o2?g%PPN+F+Uj<@2yh+9JVuwid<~Zxl-lAm?U>a`)Vk(YuhQ9V z_R%Ee^)h~chzLkjP+?g^5Hs>%S+bJNZI&vo?etn4$O2|a-jqz38dXSg<&0D-sGH?f zvtH;l?OtyOaR5;O1Hc3*18f4cF+hV7d6YCz*+OnpBtfSk$3Zm&t_Vm1r2A2pMwW=G z8fs*aYr(_AGa&E~6){cmrxH}o43#XUR!cihxzlmbzzbJ_PEK;BU$h9hO6o3ac4OsU zqSnthcB?Ja?2OrR8r3N)&6 z$Po}i9~(aP;Sa1tPDpTU`~JCs_&Pj4d-|=PuUr-O*)x0RzrXa^YQJ@6Je`E z*rkoB$N6jLyH~&2J#hBLpT0VJZ+bhjw*UFp{++$IKcXG@FZ`}4U5@8&{=T>xUEKcV z$v<9CA4}9N|r{epFp)t7sL+8$o T550#6xgor8Vt#Gz)%X4fMv}%f literal 0 HcmV?d00001 diff --git a/resources/g2/track/junior/blockbrake_vertical_open.png b/resources/g2/track/junior/blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..cd9d4cc83a2294ed04c39719b6a3e6b6168a193d GIT binary patch literal 1055 zcmWktQD_@=9R9Uwdui(yMyO$)l5H6ra=3uUxWb8NcP(c**BiZJrqSNIYZ}}shhAMa zqMR;D(8$gbF-jhS94wZD<)IJvkm0fAAxIuhRwQ-zkh#e6Fh&Lu`%vX?2EX6;@xhPp zd-(W$b#942H1*sR032F;eSUe!M}~VM7#QO9cki@@baZp!{HCOBY-ZLzO2OQ^b}@Bq z@q@K=YB{yGe)Yp&Q?CF7;M^N43&Z1)k&)5S(Lf+DHa0dsK0YxqfniuM7@VA(jKpFw zii&d_D@lT)Bz0ZO<#MG`rB-tqja}dG4+c~mSO!F4I++ZsYBZCL=L<}!ELLlB-PK!O zq0_ZE5=$`Cnh-G(QBxr*I<=GI+)|=d)BI+>=Ue;z29JYGLWTuX!m1kP7DDZ6c+kR8 zFOCK>IxrDx!~jG98N;+t$iQ)vAS{O25yfUY-8PIzl?rlQoC?R-NL-9EGQn$P!k`qB z(aT)U7K(MrYRQhDj?#FXk1-M{D0EWew7i(F$Q4I(JfqqG(jdP zI?Zw!Nh&BxIg_as3T~z1IZkJHx8Lt0z%?LB7*!2%bzEwZ=?<6gCaqqk-Zys#wcbH{ zA5D{?5FLr|(U?TW6^79TF)t6zvb937S*`gEZ_r^u7BF238FJKA$#Ryp^HRN>ZrVoM zE%(}u!Qc^M0TKW@fC*p&Gy%F8py7xd%Ie6rklz*w&?qRf;PBv!fFwX#1QjS`iO5k= zE025&o)%Aoz(GR9R3&0$$fC(tEu~)1d7jG$(5`oi{#pz^<@j%;1JHdy(5>N6f9Yp1yP6KsAqxHW~{E}Xu6 zcsBTiIQiu38z(Mva^QLE&cZu;a2Ggsa^&MmLLclPN0v#FiV!)IUkZguNb=kIj$pP38r@2x*@^l^FED8S;v()`Uc H7q0yea>l}J literal 0 HcmV?d00001 diff --git a/resources/g2/track/junior/brake_horizontal.png b/resources/g2/track/junior/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef1fc54a25699a3afd0d2f521dcad95808f021e GIT binary patch literal 1037 zcmWktZ;0D;7=CZPUhdznANnC^2R+ttL4xEoLck1iXYQy+^s-%!b=nW{mg_1Pj-WZ{ zq;6qWR%V5$b=Fa(WBE|9YL!C*c9;(lZlhwrf>nc5EL!G1RIQ`nAwN5KpZDQ`m-l(# z<-K}pJ$`ih;b{Oky7u(S#)y|jn4Jua`fra4ha-AuZ}se+q@CZ(Y`vU<vfB>9&W^;8kJT^9VZnjDmuNNYP^;g^A)*bYqn>&e$neyJ3}YLL0AGj4bdzRCdO3o zc%4W(oaQA89o_1iF4`B#u);(#ak7wLs|w%HB`>G6OM17K>pP{PS3_Ml6lMrAK{IKN z&qz{1QOcQ2y-;u}70RlT3H`d^c(JGL6338q|A-?ID^W zLm>vo_%d+)C@t|7wU2o9gKo&4v3K??LRLOFdtL3FeIekzw+D^IG zb_audhyzFf=l~`_4d4Kvivb#y$fK-|Y8LX_A^{o=MGovZ_#z+)kcOiIjVuw_Dr)AD zZ^47ZGa&Gg5HVH3jSN{d<5f#(G;*F->-9V|@`|K^&dzWqE?QC9CN!Tl`^nlM(-@YT zhjs_G`$QO+C>EzeNiM2NbT%!RhH4d!My=?%wVv;yL5C3pWCQX6AsBgK>Na8KBe^W5 zrkHYxDZgLtcJ*eHDPQN4Nl8_eY*wSG97B~jy2jIvK($1&mxv)biVOmkX=HQA6A(gg z>*4f+AK2Simtg7lAI^`&duuDpn-_li_?_iBcYbz!ID7FlYW0r)dMh|PcKq6j-QXPa zB>wg7=g&NTcH#1e<5zNbKTnJ@;y*h#eEhH7`A?#EtjoXbEPi(B1b*|&XK&s= rX&hr7xw_uiP|=^Eh3j({W)|V%t4?Qe;SGC~5Y|@LS3Z5}h1dQE%}Ttl literal 0 HcmV?d00001 diff --git a/resources/g2/track/junior/brake_vertical.png b/resources/g2/track/junior/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..03f6f679e8133ba5051c3d20a3d5cd7d20250fab GIT binary patch literal 1069 zcmWkte~8<36o2TSG!9xNDJl*~AwS)J0A3pGSA3i+Z zmGg6n1C#en0>FXUv+?->A0FVCZ)DKdp8K{vpnI2Ro>>;;rRChhiYL?|lC zvWy^bl9W;uxlkxnDz!$#Y_+x>$Mrla3QP=m&YwyJvspZsj}}X@N|moS#HOXR?NYa= zvm};``DHGoCUH$7Y6`VcV695B-H@HFV&BpC+*TqCA_+MLGy$v2m{kgN>Orp^M*S%A zM6|CV)QSM`03wFTfq)tgYXqUkVjDcamC1Beb+=YSmKCOg5hfJn@t8;?WHPBzk`_~{ zY{B5lO+jyqrjxQt1TQE;uwo^7CBD-fg!GD*=H zhRq2=Ns_9$T%%O7YBk$5yW88Y>mmrtKvXcQ9$=ecp-pDGY_XTp`?;p8ZF`OWerFH) z$v}V(g%Wr~Afr+&rf_^w94yN>O69G3!)e)GmjRK(6d|CBxRxcWdB!LT&1z=LP&-z& z-)VW?E@A+Z01AKxU;u0Z^e{k!;#rhekf9@|!xJD=P-ehPfWre40LdX#qL9ubGmF|q zK;`|67UFeWGzr;>X>Q8!a?QO; zd*AG$j!OiA#<4^+kYezxK;<)>re^iB+BC{`%ji2Tsg#h-O8LA@MGJJa!cYcFSzL6RC;Q0=5^={G0$!{Bd(>AikW9PhD8~b#|A=?u zqxr<8l}A@TJTWu9^2-Ac9zS<|XSH*qbnIf}>2nvqTc0~rJA7qs=gb;f|M$n)x0a9I z+&ul;+23a^U-8D$<*RVSmx_v~{HM&1H^aAApZ%%$X7I1qn_U_*yzkBU#_w(!Ci~I-p$;B^zZjK#%i2DB4N#EVhPP}pEpKFh)qxZn^ WP~h!dVRCAa0A^?A;-5`F|Hl8|#K{Bz literal 0 HcmV?d00001 diff --git a/resources/g2/track/lim/blockbrake_horizontal_closed.png b/resources/g2/track/lim/blockbrake_horizontal_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..3385f96653d98543a6ad834cc2c94a6b3c3e959e GIT binary patch literal 1002 zcmWlYPl)4m6vyBE&HUM+t`)*=4_Pd1gs54_Az+lum>KF2os5&gszu_M=>{np)(ljQ z7_msvxEKzBd&6IOgEzh-7p<~EVMeR3?p;t+Q#%biCVVFv@B$a1ajTg$Y zTvJu2TyEEDL9-e8{@~;!NfHDZ9mod8v{FJRBljq6AXJA1cU0~q_Q|+CI_saJWh#|o zaXd$4Wr|ig&Jd-lGFfJ}YxQoc9f#3)z=I-UhMck#!Y)yc$$M3~<7i#a>IcrKACAZO z5f6|DFaT@-512@5OjlXf*zF|ksSbsDVm zoiiL7y&mh_5DEpkR8mb-XXpw`H+aSqm_VdYBx;n;B85N}i5v#`Jc>kw(6>ffd-MYb zJ6kfW-n)BsG8midYr7x*b@PuGmVUl;?z20;Unl>0*!}8b{La3|AHI41>Hof`A3OiV zgUj2CN3R{eVZ8gz;!*u@lY4gM!qFFh-h8Hi4_U{h5XLy~hV1-#a|s zCs%j!=hmKH1Aueemp6A~-H0c#vJmq>>t!yMrw+GXKNR&Fho${nMYwdJzfnBD{nox( z+%4`Oy!Xz}#g_pV;OdpVt@wCuZf<^leqmu@adB~JX=!FHi*22nj6w}vx6$wEqmvwDBtxWvJEOgN*NTz6apB;DxFjKP$Iu^=_*j1>tnag3M!vm^9_Ar4e?Sb*o~>R=ch_@a^#+m`+a- z3s3+s04x9(pbId<0L2hER5p<7plBfApi@w1!OKG=01^S|X;h<-BOp&hy()?vcpN+p zJO>2<)0DJXBI;JY5Dg}H z3g|4BCzBGJ)kLbS@|LMNb+hBv!@wO!0h$hJo<|;_2oQqU3)2p8tD32lF|A134ch+P z9*vA%kG8+yBuUgXrCio2vO<#$mU21D=gGc6j0-s=XOW2`n?fFoLLMP>+eoR8J8-zW zBf`cXzut(Kx3@Ph?Y;Zkod?ga-9P`t(k~~U;(z_yee&;%Ki+)t+wWdmtlfKveXw!i z`>pG*9;ljg@@#PTLiPBipN{zDqc^XuU(p{eKb*(Up1FJRhl5*3d(LzBrL)Bse*cp? wNqoG1)405G@2lDH^uO?%N4G!QYQ#l+(0>1;FYol@OaQjGb~e9$<@$&J1FYGt1^@s6 literal 0 HcmV?d00001 diff --git a/resources/g2/track/lim/blockbrake_vertical_closed.png b/resources/g2/track/lim/blockbrake_vertical_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..10674d07f2f3562468433ff597c5b1c50aaf52d7 GIT binary patch literal 1021 zcmWktacJXo6nsV*W-dj&9qA4 zA}d&qBH^e|B|?=b6~b9`98r2l(I{i|j|e?hHLwbm3$nusJ()P%&mO$*eSGkE-v^I( zbtRoVd1B!N0Gv#nUs@e=WQ@mVL*rh%ekMJpM>dyV-W1h~n}xMEa&T@#UC*6Py}Fjq zt>)G?-g$jDw+Ik|l@~57kB28FCMG8*L!r>r)YSC!^vui*hGDa_vvYHE(L^FaQ6$H) zqR7i~R@2l{sZ^`gn@z`cyS_ghjVKaW1_XXSn~f++yig>|6{cniji%IUYaOrBA6OiL zWte%DkLsDYA>(z8+AeYJTBg%f{he~)TZcn883T!c0t<$SHB_u!3HKV2Q74815{)Eu zWFX`w00aOD!_;tCkHriew-{zy5O(tUo~|F%>!{t1QIP~2C51R6;YpRq=#*?Qn#q-H zzSSs6ru2K#qbsW#n6M z|L`>M9ApGck)wKns2a(JCAV57&$ENTLu0R49;o6xYeWSrE;+dBGsZA$j|#2BTIa~= zquvmY03FAYWH`&l6_G0Dc|%vMs@}4zo@)obi$;B#=aB=*2ZUhkg((}jQI3_0n3AK- z8f|`P4hCAMLz^FQ*{rB2aK#6NLLF_Q}F` z-6w{B9~|GMUrYZ&eEVnc=~Mswbp`+L`|6dw8+(ubd+iii41Q;K?^fr+Gv{YVi*rxH Xi`_IFF9_Gii6FI{Ui$L+SGN8K&KkN? literal 0 HcmV?d00001 diff --git a/resources/g2/track/lim/blockbrake_vertical_open.png b/resources/g2/track/lim/blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..a40ae0595fcfd4520bb842192e791acf85c8fcbf GIT binary patch literal 1026 zcmWktZ;0D;7=G_>?vF=5RIILG4(p5%XT>lgWSGs|SBm3v);20AOL|wWak4<53@-nTV!!`Ki?ip4eVKvn{G;w~HGe=Hb+)`d)rU6TCnhE)Cnu+-rlzN-F$|lTnVFrPO{7vOib``F zD~h}<=QK?%m&=w_Z#G@uKM2FYa7d+rWkBHPbGf*p;Kfq9VlY-sXf!3SrL_a2+p{?m z%QEvSpU|_oDHC;#+AVV}E8A|W;a;U5+M|J=NrFT|kp)x48YjN00aOD!_-(zPbN)*uo-4o5cUd%j;`OY*HNpLq~a+ykrr@9A~GtO)hXFzv>I1- z_^Kz`ZOIJ_IGs#qQjAFQGM!U7wIWpNQr%VEK=;FH&~J1{tr!b&5fTN!OF)B4G^%@zX6OgQE(;QmX<|&5a8n^`CDy5kUahd_=$%%r-|>gT z`-la|0%!mxfCI1x(8B;lC2**uA;(5xM<76@pvr=qflvS>0#XymppY#fS3&Ix3T=33 zJPkYtSpiezgkB`8W~O1wo>vY6r{51yq?IfHRhnnbgka;6OQ<1Z4sy=0=#8xQq1#2B z0TBlp$1>?yj>Q#`DiwHBSL~|pIn}^-`k{}8U7F{S3n&DHAkxB=O~R}s%Oy<7(>05( zeO2rAw04`Wea+=^qN2#9l1in^blPGmhof42`amH2*%Xp+q!Xw{A(uq~j}ZDoix(bd zV0(R4gp+^XJ{v8@%F?OR=kDD2ji2*hcw}tM<1bx2Hu*Z^ z+}k?w_%DxrM_A#rrSr!=e*4PewI82+_3j1pt(!M*J*UvMTc0k!`H{1A=F9y*&Xw;z z`0K*ppB(yG4UWHm?Rqz{^WuN^(DmEa^M7-5M;E{ScWi3m!B4Ecm&H3fmrh1+!OHUL(hsk^d;WjOB)km( literal 0 HcmV?d00001 diff --git a/resources/g2/track/lim/brake_horizontal.png b/resources/g2/track/lim/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..33669eb796abfabafa667fe6ccddb5e20c258fb5 GIT binary patch literal 1011 zcmWktPl)4m6n-Z+5U?v{2yDTMIrLDqhdtDxhl+Ff*@gGLj}IR2 z`{41u+TO~XT|T!A0B1MfSl^lQ)hSjMW7GccOGSQ4&mC^OeJJTS4hws?^02nAzn_0` z^MgG#zmwnF|McM3{1t#0Y`?j?F&&!RtIBpSy&9X*N?}<;5XXM)H`vTP!$ze8)4p-?~w-7ymC z(;qn8*^=Pu-@o6OiqAIJ*LFYoxYP1dnkYNQ}p>=>7TzY%)i_{ zesoLey!PeIr4RcTUR4j?N!A}VA_Q%&w zu3vigXKf~a^8N8!2fcH2An#6odEou2z0e+g)c4MCk1s!3eF&@e?Q6eXK7VhT12#9d L)_;8cy)XU;M-{Lc literal 0 HcmV?d00001 diff --git a/resources/g2/track/lim/brake_vertical.png b/resources/g2/track/lim/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..8bae23132aa51f073ad0852e6ad4706cdd1f6557 GIT binary patch literal 1063 zcmWktZ)h8J7=HWr+O=Jf2yq6y(I5w2CEy|V;goZ`*0bE`jb68_2Dx?DHXnjJ=5fv^KN2CTXi{>7}<<;K;Iedgbu! zTT986`IV*Rch2styaX@+$B!+{^oINT`uh9(2L=WP2M33ShK7fSF$^0S85tcNjl^Ox zii&d_D@lT?CUjjhO|wuaRjZEY?FK=o+oj^bG9U_Li9|S+!qb^}Hpdi-Vx_9MHNEcV znyoTNVlp$P2@ylaEtM$g)RxKB3Ua-w1>4znP~Pi!d=wNC(kxgKR?)CpF4U-myY(n) z$5B^7`xZi83_t`>FiZ=DjA+y%h%&=$iQ;xL*)WXzr4p*uqEtA>M&csQC2x)htCdQ=<1}}7JDm=Ks0KsSS5v?O#+n}W37l-#ubOq0>~7lK zE7bR$CTetuFwi*0$3qDgPf1iJDOg6ToHtxM?|XJT@KCo&3j%Tg1%MFrys*?VVP&Ic z21~8b#R6TtUTn4WdYvwQ#3d3^Dy3#J8WlI`c!8yCj;aaqU6E|dF{I$gAW)G)4vTyN zA#_a-Cm;X7+WedZul#X$wI^=PP9IrV|Min=!a?uw`1I?+J#_L)KmXhKMfbU9CXe2n zf8*n=+ZV>x)t}Eix%s0#kv-w|Ez5UzZhd(5#^TP4r~W5X0?9T9Hznw=QtsaK5> z_3DC+Bf?EG$V$X8juF|h1}zdWYUoagBZCuzL_J5;$Rf-cScD)Izh>}0@52Wk@AHAj zJAZOHJUKo+4gix&PcN(t_{0DYJBJ5-|L?;e59pE2#kEadKC_uve1u4u@lCXlQtNcw}T`baZrVYz)INr_j!gS16UrrrEIVZm&lMfer!3PDG=gc-)^z2Gf~PF3%N9LZzzItxT(} zGXxe1O~|ZQjrcVYFDT?*imB!z^^$DY(j8mxcg?U51OgH?XgpSwv1-QMEP8r%AL;~A zPe2D6LS_Jf0}wDwcDq%dPs4FN6x!psnj|$<^-iIHs#PE93DDjk=MM>ZSSBJWDQY1l z&!h}CTjBM(P_`vM@wU~4}s&^8VuGZ+4ItR@@ znjqY6%IgjL13VEFLm`Fb(!yX_vXsfziY42$dMz3R7E^e)D)_ZHkx$Y_ny=)gnxQtU z`A*a9_3j`VAOfHOXaEL44WNwy8WhK%q=F0`*-Z`ynS?A2tW1FbgqF5G{0oi~M47{-T2Ck)j zsU#MUQTZH|zm#vcm3p1Z?=aCQACHU4q)Y}=R4_-A218caV1pw%kpL3>NX1c}L}eOT zEJEl5#UtJSfz6d=9!}i;;mkl>TUwY~ef_7K7oR+29(iDK7XR>AU(kPl{P1;a^@YYm z(({*R-gcQs;&;yS?@K#j6T={>sjw{j~Y*U(-`x-2LMv*Dp`(Y(E-w zy!h$l-Cf7c+uNt|v)I>{{O`W1UV9C{b-Y=d-EDpM+mHXQefbelFa0-l8d81d%*^}e R{uu;^rN!li-TBk!{s+VJ%Ub{d literal 0 HcmV?d00001 diff --git a/resources/g2/track/looping/brake_vertical.png b/resources/g2/track/looping/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..e480d30971bda48b8a3009166b68f99935a8ee50 GIT binary patch literal 1055 zcmWkte`p(Z6n|~nUVm%^79nUH8RU;EJGKmu?fy9NHm@~yxAoTDBw}P|cTEF^actL_ zl^_R33?s-f!-($C`{U3|P8L|fgJm;HkT60$MmI9NKQhT`go1%)wYaKZZ}8sx@Zj-2 zpU2~K<KvIoH}u4+8Z7i7#JKJ^!a>4Lqo&E!y_Xj7>13Gj*g9u1tXCN zNk&5{e?{a=B8;s8sBFea&@y{XQ85h6bLSNF)O3bU2fZ<_mO5=gSqbT2q=% zq1`cA0*liVG8a_iVNJpfgzdoWdMpGY0T~7~0V~T`t>AB!1N~+Q zb)%>+q8$yPx_287AYz#8_p70hhT|qpukd^$m1?Q#hGC#uEkp()OfbraX%UafL|i2$ zjaGCvXK}@2nY~NK{yMz zhEYZ^R>2cBMt0(bwqo|QI$Gh0fJB8dF`^Ks%Mx2v1Sco8N=nDd^=hSU$3mUDKS1F` zoTO3=n-PS9BZyjM zwrYB}RqyvV5CaegPyjRl3!nke!2o%|vnZ<|%S3LA$3Z5c$bcOKmj@&Ol7px~B9ljU z8a4CCHR1W=Dd1R$^H^F6su`lF#mc5st>zrZ>UJIEafMPqW+xae$eUr&#$}h*dI_ta zscx5=J9ZnjdUyb+FcypY6HGWQkl7TcscEyQR;{8_x4Lc}_1hH3Asdhj2!Y3ir5A85 zAIfF1bdu6bl>WKi=_t)6rGLRD5<)sHWwSCF%~8=3Ls~3ZvCCIsDb^{!7>3Nb9q&PbAl$ z-2UnD^~CC1`R=_L?%Jgl+An){b72V OVP<-E>gMb3ee^$_5X=Vv literal 0 HcmV?d00001 diff --git a/resources/g2/track/minetrain/blockbrake_horizontal_closed.png b/resources/g2/track/minetrain/blockbrake_horizontal_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..fa33373f0f6c9c2ad6d6a2c101d0a92064dd3ed4 GIT binary patch literal 1104 zcmWkte`p(Z6o37-YuA>bkwtgabc=Y5(}i)9W1Q?duWeS(_C~KGx?`N%EemqUt-HcG zBit~IC=rh?lPH-4jU%udW-u{-1U%uuA`z}oA+@JQh+EJh5hGS9_%(y~c^^LTcppAI z-a982V&l8_?goJIx#QD|J)Y{}q2YmEKb1K3Wse?PnR#hN)XuLMXD%k-*g5TNVsh@a zGs(na;>@{A%ikoP0~ml4FD}jWhWq;Z`uqC_1_lNP2Zx4+cJ11QVc78S@W{wWC=!WK zRFvabQREdx(seDJPUrK*N~P+$8@}J^cBv?^3<&(FBn4G9Y^0)@ER!z?<%(Q$^tzXA zwn`j{#hFo!51H|>r4U7(x|8Ode7s)K{IyKmFKu_+7!EQC1`C#ml{L)C1{&pHw~nKB z6m?~^V$mpYbZQdX5&m*;cB|*rIkirZ`tXNli&7i)N%tsnjqs8 zon$#f6tjv_FpNqz>lBM#wc6a+=yW;=a1Dq&MwJ6x4HxTVvdLvyQmJj!I@U(F(%xxo zqfs&tphKZpI3ki!g<*7F$jH5AsY*7tR<8K2*KM*O^O!CMOgU_+WFf`c8L?JKuGwb8 zDYP4Iw|gJ40C4~vzyh!V)&N=%OM9N(ZhNTbg(rbZjj~oqD23%Jq4|u}k?gKf z+s@Z_s!i1B5J8~BSS%Wl*sv;6sU&ZiYAI*d?40M?ZQn)RCe8Dx3dje9py!3D=Ljo< zr&E}kpbL4r@Ij%~((84)@F6EjqN*yXltx9sOCo9GhNv`{2I)pI>>j_1*HGn-k{I)mOzE!|$KXu1U*JZqDER_tfuCE!{N!+8SI< zp5OoX^uEC#uP#>3emrxsI6rmd%^TNuPd}mFHZB{>5~p5}IrWd1x%ZZXN4_R9`zG!k zx}~x=CQrY+a3FAK{}%^mGk+eP#S@QguFp=44<)W`&_fQM_~+8K+T)wS7u@y9)Bhd5 z@RR-P=>sQ!Te`mYDXyo2Ay^t_BvoQVH I^RK-1Kk}p1QUCw| literal 0 HcmV?d00001 diff --git a/resources/g2/track/minetrain/blockbrake_horizontal_open.png b/resources/g2/track/minetrain/blockbrake_horizontal_open.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca2eb80334913760e2859f620ebfedf7936a003 GIT binary patch literal 1096 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 I!4KyC2Mgi|l>h($ literal 0 HcmV?d00001 diff --git a/resources/g2/track/minetrain/brake_horizontal.png b/resources/g2/track/minetrain/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..2d54c8ee2403cd95eeaa65bc2fa733a86fa0c2fb GIT binary patch literal 1136 zcmWkte`p(Z6o37B?b?#f=+Z4pWclNqhh}me2j1jbuU%Sh>vg-Q!`#@bbAo(mE;xI_4FMq5wK<(m zl60{wBM6)*dKE>EL?VeqDx1v}3T4x5G@GOg7#eu4&+D~Hk|P*$MPqa#$)~fvysngt zShc3H1m>apWX=}$I8+f&Ddgn{t0z3AtZWvebyHhz6x??35fEfR6|l67=`l+sZEcq9 zsO~~dA6iurDmVdn03U|Q7E9P}S8-gU>B~G{3AIb?IvJabchElEEfbzF zDXO%RWFr|ao)@%|FJ}fEl-=ca(gMMWlvifuC?8GvQaL$igbQZesHdyTx`hF&0JZ=) zLV&9nm9n|BxL0Rn!xO72T0Rd-qw^ZAHjWa@PTwY=;BAVYnOYU4GBFNez} ztv0-wW-z~;D6QtIsM5f#KshkC%i?7ml0b$6oEnz2csQSl8-+~WETCqU;y9E8WCB9a z^1`HpxEi%bLYU;Ik_jrgn5@;5Qi)1_%6h$mB#EJrOu8bJE5VQ%mee^{nJ4NVC-ON^ z7)MDGGhE<{mtL5V$1q8C;z;b zzVQmdd~)TV`Sl+kUKr{AGIjceU!J>gc71W?uM;b8ja^J^Oy1hOecSIJIJI+g`_*f2 z_kO;#;o8yp(_;(ci_a{acW(ASVL$Tqor^thxL^C~kM{=dV%LWcUw_JS6FYc==kpt#3BboS!TyHi8o&)lp&zEpTt+wVEKcz)j(Lp!=3{#*Q!l+L^( z%`DCA>z^_RZ~v6#N_k=BR^L|r)SW+%<10N|U{l+@-r%k$kG4X9iLuGiZ(lwz|35kG B=+^)M literal 0 HcmV?d00001 diff --git a/resources/g2/track/minetrain/brake_vertical.png b/resources/g2/track/minetrain/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..f72cd14f43522d3cc697e39b2ae64783a1c12dfa GIT binary patch literal 1206 zcmWkte{2(V6n|qsZa=_N8!b>>9n~CCVj-7!XpsYsagHN9+(C+|roe3!EO>z%=}1R9 zEKp62$1K`Ov(?eK&YfEcL@N|5Qpq9>UgBbEEJ-B|G)kbsB4f_@wIuKJKA%5c-sg|c zdmn6SXXiC8Yy^OLZLhEEsBlXKi|VT@{no_la)lOjw{Gngq@CUF?fbi6O{cV@>$$eQ z+nrqgwv6nwr|$+Pbl+#x^d^&u zBrOa>3j!yKc3GBuK3^yliN_P^^i(caDwjzM&{p8NCc9ndav9woi$7ouh51P}zZI6@=0z03N`BVG@pe4F-iEqE_o!o}Y9&vtIA*NCc%)22y9D^%mY}br7s% zws}cWvC3h_r*grh5Y0FeIj4~_SXh%)Fmobhml(;<`y-A>LP}`fbS|hBWBKV6PJ>PW zy%UTcAQX&>=-D`7PtlTQ3*_Z!NlBx#yjdqw1~+RC*sL*;Ny>ue6SEM5Zg)HoNJS!AB9Wh(DwRqI3=$9_jEvz-(ja8a&OGBU*rP>v zvZPFvz`YKm;xdOl zwCWd&jc5QHfDE7jr~s1y1q@K7cm{c7q()IL%M&1x5Tqf&LXHO{ z0Fv}5K%yv*5-ybSqg)go1y2FTfQ`poqTcH^2NgCJ6_ZJyrm4lEhALhLCy<^dTG8`S zqa#5`Ijd5#t7Ug`I+U4B1q;UwLep%;y^aI@;?E5Du{UhVY8pQqm6Uy^_PnUNn-S_ZI2M&vyuiSUm{#`nA z=1Q;jivH-ct3q#`T5=??B7 zY~@4m$_vX)_@S%A3)_{!scSXo@bu3&7q`TV)%ULTZhN6|h`!HoZCUix)#D)Yb9i-i_yHzMbJ+Z|aANKh^m!g^qo*?fQe8 c_P#23@zjb17vJfvoESh`Yx}y1wcFnNAJ&c)yZ`_I literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/inverted_blockbrake_horizontal.png b/resources/g2/track/multidim/inverted_blockbrake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..e6373e573f4b93c092ac5845e1bcdcf811b5eeb6 GIT binary patch literal 1145 zcmWkte~8<36o2#>sXluJJw^_RRU<~PXf}FSF|aDZ>mL&<6j!mrF$0U^wsn||iq#d}v}{GHJM?P@@AE#NKOXM` zpT~P^YBD&y>cLe2Fg)?(*mQ?SJ6Jo=)9KgmY+2Kx4Rhmr=LGq{Tzuw81a{8K`y(4C z4$VX((~+6kR}Wu^>;UM2soi_VJHuUFUEST?Jv}|Wy}f;Xef|CY7={fD3=9qqx_v$$ zNd{P!5d=<>!iplNQYl@}6$-^lW!Z6>tri&oh6bJ+3Wr^>m^YpXq*Yqa^7(>TDl3+) z*6If9$3paw%(;^xuO<;Wg*=yH%X-Kv$j(x_;TY{^CFlXs4{-)G0n5u+S;eb)SIhFC zMgX-$w4xzY@d5AvB8JI0p7eM$f-q?M9M3OBqt#^cRxXFiWe@4{G425Gr9~nr`$I`m z(r6{irc5qV5)4Z$I#Dm>2?Tw#;O8VNEVFW&Pv^v3Q7+oaij%P$`C7Y-GvE@y9R+U! z2o0lh?qGokml@d(sWruDY87;j_q!y@6A${;5S^FUk|NkCsj4e=Gu15XZQDfk3htr^ ze~6@_3>y~&Rg$vtctKUmxtv`r)|Qu>%_ahm41|u6d7LeI1j`?-vFUo)Xv9lRZMjuw ztW?`*$dBWc+a2`!1b;xHX@%p{VrN;Rpk|ix1*c-SY7B@RrU-aa^lCAGHo=%_p_Gj- znaOH7+o)Drty_oz2mvSn8h{C~1W?BSb&6+ELP4g1oGMR%OhSf%Vh|i2kN`+_Bb7u3 zkBTv5rIBO6{linhu@K_1nB-2z{TVHoH>6T2W!q+>VWW zY_{U1wr;HyYpB{JTtIoTU;qy@-k3lpqMVkD8JT3s%-9vP;Z#toMsXY}0&)N$=y+kV zSwc&DQVA>;p|U!aJ)N!B70aTsXV`F9h{dEtLM8(#Dxfo@$&zI*u*~}#As-UGC`q6! ziHZ!eIfT&riYt2m2j-?H1sJ_~?LbF&PmJx{^U9C!%s)F{*|>V_ug|Zez0%pAjW^yL z-+kry8dbPTzY9*`0R)E zcV^~p>+fD14IRhNyS}~r`r7S}ukOPaM|TPG!O1^HHk{hN*!AT%SI@7ydTJ_n=I=*d zd}`ex-zojd;Cf@hx5@X!wjHy#e?L5LiPzf1{*RvC6u)pI^4!g@qWhdl9`RRu*Df+$B>p%YO z?Mr=sj`Rr|rMun-#?S6NxS_sz`GV2=$+0s1tIGc8-UsWx=kOE5&!6l>0~6zuV~e}? Go%kO%^zVHD literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/inverted_blockbrake_vertical_closed.png b/resources/g2/track/multidim/inverted_blockbrake_vertical_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..3d977c6674bbe4443e9d121e72928b87d8af4aef GIT binary patch literal 1202 zcmWktacC2F6n?ep#dclB!i+9z#8kt$YUU0+-HA87bXmFTxt(t}N9+ zBTH%2Y#v?Mq8ym9+Xxb7=BnIW9FYYq61Q`dE}J(SM}}dDiDk~ z!N5RZaQN_{Yk{o*?XbIlPj73ut*vdrf(7mE?F$z!T(oG>;>C+G3^SQbOO`CLIvfsy za4`(c^Q<8FBuR|LVyRR*m(z;HS;MF|8iWgI3OKgY=d*-D_He`%Pf#g^%jEp|f>hEI zm8#0%n3w7lS!>j5mj!29BBo}RQL}MmiGt_3i=&^wxhcFE?k7Y!xkT91smPW~j zYA)39qsKBrMF#)};Kwl0Y>wJ&veT(j)HKJ<1cT*h^lmzh3I!WsanM#5XQ%v5kBEDt zgdkIr!o;#{GS90ezh(sOq|N1VP(02Gq)%kTI2TX*)0(L1(V~&mYne*3V5Y&sgEa{D z2smYoOj|uUr>{VZx;Igg)Vf?m(;RLQNL$#0C%jZfVDb{L$Aof9s%B&LLaM1}QMG8c zkWSo7kU^RW^L#=OlyEqgNEFg(UDGPFv-Nr%flUNw3L`RRCU4_Qc(B66t3I_B&e!GH zMy~d_+(ezY*-Tok9=n6bT>?c(EEo5;mPK-j)BdOM=dW~5Qs=8En7L&?$?~6 zLCJMrwh_)ZQ>DjR1(oYg3y^lq<1+hbdx$3@K~|22)MPZDP3pyL%_yQqg=ATz0Wts~ zXnA3wVW%9o#UfZJKq@IxIi*yqQmI5Lrx~A*4~2wCL?m1>(v_l#EJGAn*DQzEybk2I zqo@-p1kz}vvk0Ln$r60}1ET}GczEs3?+03%>T_@3Gj?<2)16-ySDPl@)|#|;Zh!Ci zM9-=(?yTK3GPLd5$Nl~P^!)nY?w%u028QRDRo`wE_Wn5Z=G6R4KlF}>`$%}VYlYMZ zG}^yf`ofx9XRapKt*i9c2Opi(|9CmQ@7%KU<3a7!&rkfl2F5PBk6xL)`O}BbjePR# z%%jM~>sv0I{fs(C{dPQGou>%wU-fm(dObNo$Jbsmjm_V3ckH}(MC*|ru8fUoV}Ige zX@9r-_A{G$zPWn;%8mKW>uu{VU!4kUdF3p1QcC(2lstC*vT$MJ)`#?@G`8$;bIX&t z0sDjTu6yOvWc_>h{E9=w^Fyg$rnHqe4o;wh-MG)#FlqYkc=v?qlN{&qwA~x-Ke#GYP$RqI!=z+6Id0t>vfEJAQ6u3Vpr1 K+~;<@^U?pvM-R~e literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/inverted_blockbrake_vertical_open.png b/resources/g2/track/multidim/inverted_blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..b083639b10f2778f878c9024d38510bd0a0162f2 GIT binary patch literal 1205 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 literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/inverted_brake_vertical.png b/resources/g2/track/multidim/inverted_brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..93705872163b8abe158e5207245c55d806ef25ee GIT binary patch literal 1205 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 G?D-$vM-hks literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/upright_blockbrake_horizontal_open.png b/resources/g2/track/multidim/upright_blockbrake_horizontal_open.png new file mode 100644 index 0000000000000000000000000000000000000000..87664f15a78f04fa8912f153915dcdb8d842d3ec GIT binary patch literal 1182 zcmWkte~i;~6o2=#2PYXaWq2b_98z%VfW}lAu?M}&9D^&lk_@vW1AAk}g*04`3^Pe1 zJzZdu0t*Z>aA469OPB~!b(%#+xOlrbW#9-U%s601{ur?6#EX6%$@{#|=Z}~7`Q!86 zuC)Ws8Pj{F1HcT|>wSYw?rmaLS6j2+xW8~_lb#ywUq8z7n@2;NM*Og1n19p%jBCrL zfPc`xY51M3Klqmew87fd>-w9+EiEmrt*vcsZSC#t9UUE=ot+qlb#--3n>Nj4wOR?n zPSX_2x;f4(2)rao@pv+w)^fR`uGi{y!VZ)J7F-%o7WFt%9Gwx^g2a{LLPeEo*?6O%qDszS zBypREAOjQ~V%aFiB|@QeG@4B&3z}9g7HhQ{0y7VI93xT&I%8(@wm_MVRJ=+xl&Q(Z zdb&DQYM^eL!9bc!PK%Yb**S+pa5E8Kb6GeYjg6<$dah6}Q{Z!B0&5U`7CC53gef(` zW)gvMRV-x_)l#lrzl$gU4}bt51E>Jw02K^SvltqM1*9rSFEKdq1jH!NoS-v+SU|i9 zMG2%ZNDHET1nCMq3Z4Wv4ITyyawaiki^OuF4j1Ed2& z(DcHB!?+wVOJOYNClhfpaVSx#2>CpjI81xJY%s`$!#rV^NPCE$yK+H^sd}9 z|H|@pYyNs}NpjH(`zKuL>SasN8<3n3JLbTD*Z2SP_>FS&f&g6o1AV7gZru4l%{B|$ literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/upright_blockbrake_vertical_closed.png b/resources/g2/track/multidim/upright_blockbrake_vertical_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..706be4a8cb9c3468f06c59f5a5a86821d098a16f GIT binary patch literal 1158 zcmWktacmQH6n@Z++Zb3)fd(2Mfb)z#hI?eus& zBL~a*|n2G|WuPD*0U?5D=k3;jyfQ6_fUA*3qoE zP{WIw0-940DtQ1n00F}!yFKP|DL9_-`KCCo912xqv3uz>Di&R&!$Uj0oZBbheu)Ug zNKx_08WY#qRDsV_guEGYQ!cOHu-nq+Ag{kqr2^b z6ix(4Dnv68o==LR7K!AN$znQfvYBuj78Xy2511JDGKpCKp0csb=ps0-W3^J=64iX6|8uETHIY2xh$%&FA z%5W$jMwJ9IGw}HE6tD~gI4mqWV-X^y__G36b-e?%8?d1vq8SSAJCzo*xd0aAm ziWStGkwQzY%;jsSYT*u`+?d~M57O>1Pewzm5({Tiv4Wm5N_xXAp=OO@S(FE40z%OC z!onlCl5oYNSa_7uR7yLk)$4MlLTRU%V2}@o#b{I_y>ZH`(xlFiMbOIM_53kL1T)DJ}eQ|QlXXlpc%kcec z2Gf&UuKc_AqpLe7HtfI$`XgU%RcCLVy*at^>NkhVm#v>>zOu!i|1^K%%!BV<>y;j^ zwKi(Mc9-vWetxQTY<9UhX*ffUyAOXHzfKm`&$$bCz9`Nfp1Seeg}cAq@*L}U;#zpe z(w|Sit2QoFE*|gt_DJ`E+jo}iyfpK2-=1}~Pm<%W|E`|>XSu7d7rk}!)$D(LkDR-p YZ=Y%Zqi1AoJ0}<%*w%l3^R6TR11oa=mH+?% literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/upright_blockbrake_vertical_open.png b/resources/g2/track/multidim/upright_blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..bd80eb7a2b96fbd9a7bbf4cd662020b6b8387ed7 GIT binary patch literal 1174 zcmWktacC2F6n?d~*V@%=h8bsMaYPo_jh%ABb)4gLSB>Smp7hi>0-p7Z0Z%#fs;Oog zw>Y9kz19q)L&?|t7NkN3g% zcqcXtxqIg=o(BNE1MB;TTfDFZysN#{xiiNPwdkeMwOd97W#?#MWS`=D*mJaM0 z@%x5-BRdZ6z2RF0&<-00H?D0Bx3#s+nKP%oy?yT7xg8xHot>Q+hIMsyb$55$oK7c6 z5-iII0w+mcRaL^_a6F#OW^;xyQ!dvV4Uzzc2A=EjdabhT2n2~pl#VC(bXLskYSD~V zswo!7Jamu3*+L$NCb^O-IT>d4xTly^%7sX+oNCq$w;e*H+$vG_fE$l`=(NPuvjS< z?jb2Z!v+K)DoKezARCS9$)uUfRc2=D^*RE(0FD+ zkO`IaM6F~r8V?Zz-~mtpG=L010icQjY8B6-po%gnR4(x@P)LX|kaI(s2P6PeY$!^i z6pwN;Dn?K_1ZyTErd>VzQ4)#HqyjM763Gi&WwQ>-7q!Z5*;Yy zLJ1P(7-Vt?p$XOMfA#~T!$ShBzW>Y4mUayEuh}^E>*!hTtg-aD{&(pUmXBt$h3@J1 z&7;%1*IgU`;n<~tlzpob zy?^gO-_OInn-4Gg@r=hv#Toyl(#sw~ri}*kfEi{p8x8+Py3Pe0$sR z_1?j|eJdZy%jPdyKY8+th1 nfA5>x``K3Uaptv6EBIrH}(}qt22Y?na7fNEx@TN<%Ji)6N{w zV8yajazZl>sjgtB)m)^&qKDR`F=sMJHK$f7@d%Ap=^q3OG_pVV<7Y|U_rC9sm-qeg zy*Igi(A~LcU}W^|{Z|7U0h(d^w&DK9a8py$f&~kjo0}IdT-egm(%RaJVOU#RTYG!E#csC~ zgp;Nzmi2I)PZ0QMG%CxfY*y8@qG8nPb;1dh3m8v_&u0#WY+=zEi@W3`lgavXd7+@k z%at_kz`U*w-eZY)Z4!s41Y$Ny=Vfmp%NujCs*#?rX>Kd{9T28KVzCU5<>RJO##}F0 zQPqj+e)Ld6NV5Yl0DcVPO{R#|D&ctA<(g%fxnQsqiQG=5P(E)Z%y!D+WNa=!?&cld z2*F7%AxTFSPa?;r3x3rI+DNO@ZFjK_4@dfVnvXHDls~2NsvgmdgkH^*=kq2C%q&=f zU=snCFfwIvXK`Pi;&pGlETn6ahGrRunIo-Xw^i^W>4hQP`LE@MQ-MCYt*!4WLev5GHU4d-f7 zv7W6yEX|`1hsi`*EN+{fbvQYfOYkr;e`A@LjVI$edF-~|u>Bmf0q4xoYoY7|2wQ9w!>86^e>o`3`esv8Uj5DSR6 zpg4ij3{pd=5JN^99tBT=hXyZ$g*Zzj>_|xNOq$E(qPnhBt2%0US%W}`9h78Y(l)<} z^M*^R`ILG%H!l|+s%2EF;btIhnA>UcQMM3Eh(V7O38fQ}oRZKrrD|xXUM4*rqyjPk zA!vAEp;26lS)(Er3Xn;eOrB0wDng+^CO@QoJ~kBMM3E<)QPL?>ghCT}kF&@)s$M(t z+fW2YNdl=9(me>F6M{MT=m*A!23gpA>-tzjKReL3Wq9I`_fPIR5bas~?teGMuhhFI zPCveQTkC-j-s67J`u6I9ww>R}!?;As}&|egXPxgwp zhQ_|{zCRGXzx^L>cax-|7cL(hA3VHkMf~s8oqy7jv3l($ z_d3(E#n-|YzPmDV=(%%$eY@ezGs*U!T7I_xF!%s}GMpv6MLzObTzB zj~qO{e`aUjP5bn^r;fk2Jbmx5G<%VYL_<6l?enMPw$E7?tKDcLa&C`+Mzh($ literal 0 HcmV?d00001 diff --git a/resources/g2/track/multidim/upright_brake_vertical.png b/resources/g2/track/multidim/upright_brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..a987c1076825bc7643196137e138a51d39823d42 GIT binary patch literal 1175 zcmWkuacmQH6nkP>QgKuwA^fbPITs#Y>gg^Meug9 zh*fJEOJZ(Um&{wkZo4WGDTO*0Ve<)hF)LRlqGm;#sTVjKcu5E{po&;p#_}<|oVGNI zHe@>(gjj80j(EaAyBvf++Z6|Jro&^dv$NVF};kukR`EwMR8G$K+tq0};wdOk5@WKgYu zTWErGQ?#F9gQ6Idq+~Fdjm7e*l%ea@QmJ0ABe2OpBrqzCvpJhsB>h!3TJvaTFjrSg zjjTCao$d?KB#6pTid0WXg!A|CeI)c~0cF`1~C zOZq1=;c`A{mJ5x>G-3eU01AK#kO7zgs9}JbC9o)@pp1qpWq|;hf;a;@2NeO32uQY~ z7=<(e=>b%XqKXDjgQtOK!7X3`$r=ulag|GJQZ5%UjErd-sOe?%0~P9GRI8xby*eRR zTx#8uX#{gKiQ=qYMddnS0osmnPTa%T10ogj^J+Mt#lyKw+$dzsN&z*hG|wX)Pz4Zz zrWY0%A=IcX62byLI+>u8N0POgQY_NRqpZgx1_DwjBvZ}^?MyIKhNbenvm}tF+kw1x z6eduTLOO#C9wGFVV(~w{fzb^EBD{HbYFktH^snt5+;ww%eBIfxo@d5x)c!)7j0N)F zo!ff%?Z3)Hn>P4CTk1?{(Vr{L@muSr-}v19dpox2${(A!R}O#s*~rh=?>`8X59O{r zXgv9K>=d`cGkJ7b!t?Gf+z7t(qh&#VYkGc>au?aNo?Ph7maqkH(%1HEfnK0bdfH}vR>mH!3{rx%}pa&__a;f=Ow z>+T`*S|E$RCD)Rz4ZuODA<@IQ6S#qy%bhnAk0dFS5b ovc1D6^$B6%Qd!$~54F7joBM7ZpSm&i^z}f0-@w}M-r9QLf1`Q{ZvX%Q literal 0 HcmV?d00001 diff --git a/resources/g2/track/slc/blockbrake_vertical_open.png b/resources/g2/track/slc/blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..db2d671703c98d49557afed31658d11174798ef1 GIT binary patch literal 1144 zcmWktacC2F82#F4uUaL;2v&+g2PkN4X1RA?*%plzkdu7oD z7F<}fF0j*O7)Sod=7AX=8nlxGQ_LW9RRi9%D-mxqXvC;xW*SEr?ffl;?|tu|kN4nx zyvbcVeXCclTL}QG2j1B+*yeR@ywYuJ?-xG3jN0`4c>kVpLEbkW86FG5wh{S*;7bD^ z4Tpk*!QqjE`!5II0I5A-KvCV6>=)h7Sm!mFIzK-x}~)mC7%ld1Vk861uQ3H#iYHGb2Q5? zRQIB004=Bpl{^4EKmfyJyFKP|sW`6D^c2s}ghG{AY(ASs#iEOJco?UbchdpfClg|f zlvG;DuyLJB6$GsuFszW9a(R6oS|B)y^2@B8;1k(E){qS|R=z)8ma|x@GF9R&B63Hi%#cb9zjOy%cqtQU%k^xU+WX{eOTtb-$RoO(%uhk=khC18K z*B2@+)I-?ql+)>Rdj!HO(X_(xi9lN{nop)?a(Sy{HmeK-I7|`jv4C3*6PYNZCxk*K zG^58V#Z0|YYBuK)10Vt@04jhEFauD-0JVo_QB*;?hO7#YgG@q-0mBCt4@dwcJ5iEE z8jp-HDkqSo!P4U?;8+lOEG#)=5hA7fa+*{q#7$GL*G<&+a)p45_AsiG*W3XEmn~Xt z`1NL_&`OsVj4G-$a0gIs%;&ZH8FyG9qajX>g|$?ypr_1|Ubjl9S*17*8GtN62-;p) zcm!7yu6Ps+2dPY&${fqoYD&3GWxiwmejyx|qEVUj#wl-_A$684a^6{WO4|hBZ?!m)PeEAodRsVcVpjD9|m@8+kN2Xbn4A-;(e>$evhW^JUiv=7SBBU zesY6r&1)wvT^+sf!``QxwEAW+58q$;=V8x(T^oBpOpTqq$-cRX<0UcSLSy&a6l~rx=LL5#lD@*aC zv*#BR@%i}T@~5Bt5T69_!0GqT%nXKyhK7cRhdmz8$jHd(=;*$E`!Ea}8yg!RAIC$X z5JiPqmJtL_mSd`_WHOmTp;WD!mbK$J-CmCh0}}zB^TuNSWHP9w!r5G;P~^*1sa98; zcCOtqSP~N>UWLQcVo;Zfl1go7*m^;1Ru!j_bseMMwW0x#NYEJ21+1)K^_;I&_V=0r zUvd#02M52{WKPi<^y&j3Y^K8HYl6{~OeYbf1L0^WB9NR+#}rn{^4XG9G8NNKTTb3~%k6&M$ADh|JORNJ z5IRPe@Mx8Y)fvSWb8Xe=>K5AONxw`7v?!SqBW0Pbse+x6TLraK$#m<5zFk2b%jc&F zQl#hv!)k(%ljWkORdcy|sbrgGduONH?IH*$Kol^l>|<*Ip-Cp%Y_=0KT&>pCcY0NK zuhmCh(&wXbJQ@rMWLSu8IU+k6?|zas3*x{im7CUS~1b6 zq+9i(+p>DSCx`(M0aO4TpaReU=wN^b#j_}-qKbi>7EgdeL7o9K3JwoQ0Hok3M(R0y*J>HtuDGs^23~;#P$@5?~z#-lP+FkV=*C_lv62%3TNnWfuSlaRp-JxJn4!dBn45LKt&3f z46-?d&{fr+c=-dX^K$~6{NusOKwO`lK6Pg8(KnyJbLhLHuZ$eFQ0e;A^Y4GYdi>vo z!0{E&Y$xGIijbq}%Uyr}K;dQAysh@6sxb)w_HTT&+?zhp6A$W1(*q3i!_^mex46`$H K(>JC*y7WK%B+G{Y literal 0 HcmV?d00001 diff --git a/resources/g2/track/slc/brake_vertical.png b/resources/g2/track/slc/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..1afe3e39501dc2326ad2b6c3494f647a9054ee69 GIT binary patch literal 1142 zcmWktacCQL6nf_sF}+kY(c_yV*V)O{zzy32sLY?T(L^DhXfZ{D0K@ZNdDOLX9n+kA0Is4 z2jAl@oE-J`?;6|%0R1CJhsWAH*v5gL&UW8-aRs$$@4V;Tc|kfoAD;Sf7LLqF)3ZY( zXQzU*W3y8;7d}{-JqXYVCy$SN+QS_k9XodH=gww5?%ug`Cx&4?Jw3g>y>^$& zMNuTnGJ?Q~qF&i^SQZKBp?;X_;D#v4y0soRiE_yl!S%jiT290RqAdr~;Oiu!3T(WNpo| z1Jy~?44@|}LPZw<4-mjG$!d){94d}y-0nr5F9m~@Xml%`Mumcdvbh*L$vfQv+$#~j zC?%?HImN~_E|C{9<$!JmowS4Wy4(W6iL_s0r8pl?2hzHv8_}YfFzVTAt6*ioCV)K% z&IsTtMyKuG9PTeLlHpUTa;Bjc(IQXSMA{Md5{l2A71_Kj7%{Pulxte7QAoB74b_TP z8;uh_iViYtSP&FZOohWaMJc4yhOSrF*Bgxn0*3^65~H$KHt!J1M6k-nYyM0 z&0PISrG+en)k@p#UZ+bSNYU+E)TB=r)%Vj$CHS6~ap^zAfNE8{P$s|K*ELGshb)KmETqxi~ zQ5>Zxq%+9i5JI2Jw&1fLm>(Mz;PAuWPPYXb89p+8eq$*yay9l!pXct2^yBHsC%V){|7VUTMJ@|rOx^wgPL}cN{(zh4RuRQ+s59)m5Ir7IpeV<-hy>t8$OkaJ< zuO7X5V`Am`cmBHl)7E&tV!Sr^@~QV<2p#I)1G!^U8w-VVyW3H~h-Y;8ySFDl`5*Hf B^Z5V( literal 0 HcmV?d00001 diff --git a/resources/g2/track/standup/blockbrake_horizontal_closed.png b/resources/g2/track/standup/blockbrake_horizontal_closed.png new file mode 100644 index 0000000000000000000000000000000000000000..4f7f3c53aec83e8327030c1206308b61e28d7917 GIT binary patch literal 1046 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 I^9%3&53bkR1poj5 literal 0 HcmV?d00001 diff --git a/resources/g2/track/standup/blockbrake_vertical_open.png b/resources/g2/track/standup/blockbrake_vertical_open.png new file mode 100644 index 0000000000000000000000000000000000000000..abd4a3f4cd125dbc929ceda8d4886c6c3b743be8 GIT binary patch literal 1101 zcmWktZ)h8J7=HWr`fnVVZE4Lgr2%hx(kNFvT*hwewPf{XZ}f_B21)BR%ZGCu?Nzc7 z1-w^1kLb-umy}TY><2iuDG8mybsUwz{~sa z^77s|Kkq*@^x_Zz9GW{jv(Vwu4qh4PIZ)cz{SJ+-&%U=V$QRe6%WGjcvm$>O9-q6k z90@OkmshT={uDk5&;#esEzWkDySlo%ySsaOdU|_%`}+F&`};8r8yFZE92|6dJRXYj zvMeJAoG1nrMUKbg>9n5Do2634wwtXMGEUpm9*@}WXeDO<@} zJT+oWk@fkucz!1msjBKzT}Q>Di*k4vrvgMFzN8Gf_>-YEsk`w8m%*qKqp@(!+HZ8Ser>sV<)-K`<&lABSBU^!FP02R3658TPhe*4keli*GCL=XAQ4eMt(Lz(JwDOJp zY8wrcI8HmAez!*;y`s;jaC{=v85YYYQ#-l5U9ws=20|RB2)G(@YZ94>F-AftWFk9; zS}kT8)l#eV6fpn+00lq;FaUM{>KLF-@hpld$jBnQ$`c?{kYd2}gUtgH0Lf02q)?Ve zri97~WM|>v@HB8N1b9pmoobX!Y5rVREEM9FWi%QV>SVbhK*fd`&BRmlr522oRWcfO3AJi8#~~At4G2Le3zJp| zE#ZpCFeyxD(sbr_re0UdWjb?*4F&~C5@Ru$^2TXznxPDqDstWmPc{M`6mlb#Kp6^| z46-{y&!L+tjFIo-Xw_eNUFw^hFpbl<$f=Pb`1|au-)z+K(;om__Mf;mGxdeN`Q^jDBUj(vd;e?c-&0q9 zZSQ^;JFaj4V6p7v>+hc0(ABrJ3H0$xQyFZe@zt|i#}+o<*}ZH0@gVSQPhUH(e%fB$ ze6staM|-H(T-Z>1Mb6vrDgqdSi zDu%6_odgWCLZ=l9=C*~MHwWMt2tJ)@(eV`F3E?J zwF+Obg;GPZ+Op$ka3)42;;cjp3X@WKwI~*=a@A2CPj~&2*ROSVnqdwi5=1kA=YcRW zrW#GuiBywQy`<6AtbysGO_7W!Oe~imjU-!B_=YBV1*KEgdUj#ZEbn+W>bc{DmsM?atC0B{Na8lt!cAd3L|=p`lkS19X0hGozw~%MPLXtT{;8L9Ve= zZtpr>)EN*FU~nu!g;N}!mFRp%F!iie(i?WkbM3zGqM*wN0&)QPfDjD5uGiaBo2h)kr&3ZjtK{=4O%)ib%+WSaHw9`-B>TxYl5wOHs6r!$L!N*T zx}rrg4}V~7abAL>_kKS!Y`&hGIkxovpX(*zQTN~@<3C(K^4g#|yZ+Vl|85$k1Mi%V zKXH5d)@}aN>5&hk=YuQ3gD+Rt(p~rZ<#!+7*!Xz;GxYbH()8(@&n=w0_w+~mrPC+A z>)4kh9`|Yij<513$I)AHPGL z`^_m|yfyJs_fl~9=c_ONdLnuM$YbLhOLvCk!LvWYN@&|T^v&6Y;kGb0J3sU7@wYDg E4*~+j%>V!Z literal 0 HcmV?d00001 diff --git a/resources/g2/track/standup/brake_vertical.png b/resources/g2/track/standup/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..b99285eada4488ad75e2d0f8cceb25aab768b8a0 GIT binary patch literal 1149 zcmWktZ-~=&7=C-bYwnLyT+!-^i?bY=3$w!rnN)}_r`-{~9LCYpx@EWASzXxTmV+vt z>#+(wmk*h%TBS%oWLpQpb=xTw%BZf)P6`X#F{(yZvBM4>E3U))aJb(pybsUw;pKVY zd3jHckA;>GK062i%ST@u+0*6KU2N!gK2`dfAG)+=X2-;gpd6fuO@1&9+ozPbr`L_X zI~kqcGd($V?EM?lTLGLfzH9G}?y|$-=;`TkI-R|}y?uRsE|&|#u>Su3fq?<9-|wfW z0LwChz)4a>Rh48inaSh|g<_?$VB76ZhYA1_1fCm;L_D&L$KrvM7R+S%d_gRg)taR> zng&Z^;oy+Mc@tq=mx!E7%_rG%CR{5hb~V+qjm35)b2(Hl`zVi}@dkK2C=wxs3@0c_ z52{%#e3VARB-9mQ#1Amk4UBqz}kg;i2~DktWOO3_MG?6lR&Hx|oo20Q|IqkzYO z&@npa4Hbw;nNh5;)=-VMUP1Fb>5*t(EJSMIU|wQNs$eChdPZ%U$#yxjXql*4aeHWj z3{!NJVPk@zNm4czD`;9dm$Qn+#==6o-A3S3fXHA}-p!VLLXC_z*iUzR)SO zmg#u+mul(NyP znW&eut$L-?d59Q*Fn|i61DF6+fF=g0J3NcxDl!dZ*LeaI3epS|LtyiO1VD-xX%sSe zRFqLIg=_0`3Td%K{aTa(Y5G(utCpwkl@JuAokX<~URYWCKFb&BEj< zLQnaUaZH}3vl%*jF57IXwHlp0&qgAGEKBjYLIsj^Aj425OO?660#CNWek9^3L7*&! ziVU(igwQF~6MgyvGkeAa*mnQs!LD|Vj%?q1^!ADLwUsBFE-}%yYH+%JD;W)l&?$K9|SM*K%v1;D9MNLpg`qvzCd~*QY zFS=mvjoFD=>iVS*uMYqH@(WiSN7rv!r#YQsWAO0qwbyrTJG1$7r~mZ_=ia=BX}*iQ zho7sQf3Gm`=fB6FA3J+=iktm0bM4}P{Li;9+-Uyv+36JK_>{muQO>*)`PGsh-2Y`_ z{js^>@3$T~jiF^*^vHpKZkCQ+I(wqOZ+8D3ZRe?!{L;RQ!u(}*a&(pZu^&Ad-gx(; z732GQev=*F_1<{q(C=$weT~0Jt7?v2t}>~WON_$>cOUJ%ykYaLUEO+MbjR4p*RQ_y F@&Civ=`{cV literal 0 HcmV?d00001 diff --git a/resources/g2/track/steeplechase/brake_horizontal.png b/resources/g2/track/steeplechase/brake_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..e9782f894e38308ee276ac9e070fa1cce8ba0451 GIT binary patch literal 1014 zcmWktQE20I82`3zOLz0uhk`vV7`+P7%R>iIB4m>7vQbNpWh}!^@(^d%6%A+945H>C zhvlqCIfL|}N*{_uEE=%l)I9VdLOF(33|x^O7g&XY2k*T3V}2DN0^3)1H>blhGc&WZvyn(-ZfbS`H)m*2kg(sz9=uAfKOcG=g3>It=YiO8Xj`bSxaVLp}X*8D6 znT=381t0*(7^cNyRx)W5gu^h$f^bqO^epRsy^ef8NySraA}!#IOk^}NXHkmH=rykB z@|Bk8bYw3q;B+#bNiibHE3~9>T1hC?<+`VNfz=Kx!LZSv_%RmZA|wicn?TqYT~B11 zgygeYkSq6fXJoh0u|UQZI%#Cca*k;zTuT>&qSCAC1GhNxtCPS*gLW)V6J(B}3oK`d zVp&mYhS4mS{dzs{yneSk8jTPnH6W@O)rfJeq}U+~eXcZ+oT1Sg+1+t-c-EVsB{CMH z6NwC-63Mi}Fgh=kJ9*q0oT` zho^z(ASYm|lCTW2VrLqT(rOihz#R?)H1$drfHId@J0Uo@>=9bX*dxgu8?8yTbLRC? zZ$!j_#<5H~Cb76GQf7g-E!C-5Ew>W1-C@{9<37#v$O9AtLNN8h)C0mUC5tAe=IL6M zu6IKe_zpt8=S2|26!*OLxA$o$X#ZRkPQ| zslUvdvFA>|F@D&~U3g>f_LoBaZ|TO$?oX%OYb)Kg*9Y5ApFQ^d`p*|vqurg#y~Ar4 zE`9j^=SP41dN1<9!@zv#*-}@iTF0u6h literal 0 HcmV?d00001 diff --git a/resources/g2/track/steeplechase/brake_vertical.png b/resources/g2/track/steeplechase/brake_vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..d4fb09a3248e5e787d88166cdfb1e0ed3d1e540b GIT binary patch literal 964 zcmWktL5SmI82x5Coy_bw6zn0p=8$Cz1`KQtIRuQ5Su;Z&qLXE^P_aU0Hq*%=NLVva zC1AuJiuMqsVwHeB1nePb4|B*!4-tYC=|T>3sF*_!1$$VrE`gnuL4ULGz3=hh3`nK>DJlayJw1dde%JtumSf@%!iHJ`yU+Z zjl;(A$;Xd=ZM*?cfctMh*vpSsR#sM5R||#0+S*#NSX^IU$1rSTV`Fo36R%V%EX#e=|_%cnGS;jIT@E}WD^?KPb$fnJ-JABWR2SarfS(BtQoBJY- z)%Yz_!krrFYE<81&s$>Dt4)SxI&Lpg|7sam2~cTh3g9Z(z{H|XX*wup69O$5l&R?2 zMJTQS$N(yanWd6L5H3aeJby0BV_ly*&Xay0MG?W4D+12QB(G9cldd_e=JJ*&wgRa; zQv8V;raH+HOtr!*w4`x$Q#9LhyRY^`GfbQ~?Iw%C>?$e=P*woffwX~gF|LnShg3Zh z%%s+tS^mLQ=|ug05{9$O%jI&3fG~mTVeFtJjtFH!>oc)EultMUXz5;N!^QRV3T@G)5{Khe zvZBz8#`BgWx7FOt9(KCp!7z=JY$kvzVU|*IRMItQ&lZBVGV=6s;7lWLF^#kA2@(Km z02Y7?5CDt;<`|%SWD(gG3Vf7KWeQ9dx&nk%NM%3@AQML&7Wpy?4K!(^)Q1yfjao?(EEWmMvj`nndrNR}*(cSIGE?4N)`P4$y6R1?!x@?`sWNaR zR%J?cfix7>)+N_5{H`+!x=9=?(imkkPLfavCmoKD3K6CUs`4T#Sfev9w@N$ z$8V>(cxQk2-h+>Re|U8C{J)GV+=N@|-|WT3&P(*&^}F<)n@7LAzx&#&GQR!8^Jo9! zyH7)NcJcEU(I?lZ#jjtt|GM+lqZMlY_^0!o^_@>w;PIc|F}J^enaYh}fA3)T$2X5Y F`yXTPme~LR literal 0 HcmV?d00001 diff --git a/src/openrct2-ui/ride/Construction.h b/src/openrct2-ui/ride/Construction.h index 1c18a5b1cc..bb902b33ef 100644 --- a/src/openrct2-ui/ride/Construction.h +++ b/src/openrct2-ui/ride/Construction.h @@ -19,6 +19,25 @@ enum class RideConstructionState : uint8_t; */ constexpr std::array DropdownOrder = { TrackElemType::EndStation, +<<<<<<< HEAD +======= + TrackElemType::Brakes, + TrackElemType::DiagBrakes, + TrackElemType::BlockBrakes, + TrackElemType::DiagBlockBrakes, + TrackElemType::Booster, + TrackElemType::RotationControlToggle, + TrackElemType::LogFlumeReverser, + TrackElemType::BrakeForDrop, + TrackElemType::HeartLineTransferUp, + TrackElemType::HeartLineTransferDown, + TrackElemType::LeftCurvedLiftHill, + TrackElemType::RightCurvedLiftHill, + TrackElemType::PoweredLift, + TrackElemType::CableLiftHill, + + // Simple track elements +>>>>>>> b8810fc4a (Diagonal Brakes and Block Brakes) TrackElemType::SBendLeft, TrackElemType::SBendRight, TrackElemType::LeftVerticalLoop, @@ -136,8 +155,13 @@ constexpr std::array DropdownOrder = { }; constexpr size_t DropdownLength = DropdownOrder.size(); +<<<<<<< HEAD // Update the magic number with the current number of track elements to silence static_assert(TrackElemType::Count == 337, "Reminder to add new track element to special dropdown list"); +======= +// Reminder to add your track element to the list, if applicable +static_assert(TrackElemType::Count == 339); +>>>>>>> b8810fc4a (Diagonal Brakes and Block Brakes) constexpr bool TrackPieceDirectionIsDiagonal(const uint8_t direction) { diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index b94e878897..2e382ce1d7 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -2327,7 +2327,8 @@ private: auto trackType = vehicle->GetTrackType(); if (trackType == TrackElemType::BlockBrakes || trackType == TrackElemType::CableLiftHill || trackType == TrackElemType::Up25ToFlat || trackType == TrackElemType::Up60ToFlat - || trackType == TrackElemType::DiagUp25ToFlat || trackType == TrackElemType::DiagUp60ToFlat) + || trackType == TrackElemType::DiagUp25ToFlat || trackType == TrackElemType::DiagUp60ToFlat + || trackType == TrackElemType::DiagBlockBrakes) { if (ride->GetRideTypeDescriptor().SupportsTrackPiece(TRACK_BLOCK_BRAKES) && vehicle->velocity == 0) { diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 62bcd88e3b..19bdc4e0cc 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -1420,6 +1420,7 @@ public: _currentTrackLiftHill &= ~CONSTRUCTION_LIFT_HILL_SELECTED; break; case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: _currentBrakeSpeed2 = kRCT2DefaultBlockBrakeSpeed; } _currentTrackCurve = trackPiece | RideConstructionSpecialPieceSelected; diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 9b67536538..a0b7b0888d 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -574,6 +574,7 @@ GameActions::Result TrackPlaceAction::Execute() const MapAnimationCreate(MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() }); break; case TrackElemType::Brakes: + case TrackElemType::DiagBrakes: trackElement->SetBrakeClosed(true); break; } @@ -666,6 +667,7 @@ GameActions::Result TrackPlaceAction::Execute() const ride->lifecycle_flags |= RIDE_LIFECYCLE_CABLE_LIFT_HILL_COMPONENT_USED; ride->CableLiftLoc = originLocation; break; + case TrackElemType::DiagBlockBrakes: case TrackElemType::BlockBrakes: { ride->num_block_brakes++; diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp index 546f96dba4..e39f352bca 100644 --- a/src/openrct2/actions/TrackRemoveAction.cpp +++ b/src/openrct2/actions/TrackRemoveAction.cpp @@ -463,6 +463,7 @@ GameActions::Result TrackRemoveAction::Execute() const ride->lifecycle_flags &= ~RIDE_LIFECYCLE_CABLE_LIFT_HILL_COMPONENT_USED; break; case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: ride->num_block_brakes--; if (ride->num_block_brakes == 0) { diff --git a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp index 0c564f7fc7..840a470c4f 100644 --- a/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp +++ b/src/openrct2/actions/TrackSetBrakeSpeedAction.cpp @@ -69,7 +69,9 @@ GameActions::Result TrackSetBrakeSpeedAction::QueryExecute(bool isExecuting) con if (isExecuting) { - tileElement->AsTrack()->SetBrakeBoosterSpeed(_brakeSpeed); + GetTrackElementOriginAndApplyChanges( + { _loc, tileElement->GetDirection() }, tileElement->AsTrack()->GetTrackType(), _brakeSpeed, nullptr, + TRACK_ELEMENT_SET_BRAKE_BOOSTER_SPEED); } return res; } diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 03d2e600e1..028dd66630 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2021,7 +2021,8 @@ static void RideMeasurementUpdate(Ride& ride, RideMeasurement& measurement) auto trackType = vehicle->GetTrackType(); if (trackType == TrackElemType::BlockBrakes || trackType == TrackElemType::CableLiftHill || trackType == TrackElemType::Up25ToFlat || trackType == TrackElemType::Up60ToFlat - || trackType == TrackElemType::DiagUp25ToFlat || trackType == TrackElemType::DiagUp60ToFlat) + || trackType == TrackElemType::DiagUp25ToFlat || trackType == TrackElemType::DiagUp60ToFlat + || trackType == TrackElemType::DiagBlockBrakes) if (vehicle->velocity == 0) return; @@ -2716,7 +2717,7 @@ static ResultWithMessage RideCheckBlockBrakes(const CoordsXYE& input, CoordsXYE* TrackCircuitIteratorBegin(&it, input); while (TrackCircuitIteratorNext(&it)) { - if (it.current.element->AsTrack()->GetTrackType() == TrackElemType::BlockBrakes) + if (TrackTypeIsBlockBrakes(it.current.element->AsTrack()->GetTrackType())) { auto type = it.last.element->AsTrack()->GetTrackType(); if (type == TrackElemType::EndStation) @@ -2724,7 +2725,7 @@ static ResultWithMessage RideCheckBlockBrakes(const CoordsXYE& input, CoordsXYE* *output = it.current; return { false, STR_BLOCK_BRAKES_CANNOT_BE_USED_DIRECTLY_AFTER_STATION }; } - if (type == TrackElemType::BlockBrakes) + if (TrackTypeIsBlockBrakes(type)) { *output = it.current; return { false, STR_BLOCK_BRAKES_CANNOT_BE_USED_DIRECTLY_AFTER_EACH_OTHER }; @@ -3060,17 +3061,18 @@ static void RideOpenBlockBrakes(const CoordsXYE& startElement) switch (trackType) { case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: BlockBrakeSetLinkedBrakesClosed( CoordsXYZ(currentElement.x, currentElement.y, currentElement.element->GetBaseZ()), *currentElement.element->AsTrack(), false); [[fallthrough]]; - case TrackElemType::EndStation: - case TrackElemType::CableLiftHill: - case TrackElemType::Up25ToFlat: - case TrackElemType::Up60ToFlat: case TrackElemType::DiagUp25ToFlat: case TrackElemType::DiagUp60ToFlat: - currentElement.element->AsTrack()->SetBrakeClosed(false); + case TrackElemType::CableLiftHill: + case TrackElemType::EndStation: + case TrackElemType::Up25ToFlat: + case TrackElemType::Up60ToFlat: + currentElement.element->AsTrack()->SetBrakeClosed2({ currentElement.x, currentElement.y }, false); break; } } while (TrackBlockGetNext(¤tElement, ¤tElement, nullptr, nullptr) @@ -3107,10 +3109,11 @@ void BlockBrakeSetLinkedBrakesClosed(const CoordsXYZ& vehicleTrackLocation, Trac location.z = trackBeginEnd.begin_z; tileElement = trackBeginEnd.begin_element; - if (trackBeginEnd.begin_element->AsTrack()->GetTrackType() == TrackElemType::Brakes) + if (TrackTypeIsBrakes(tileElement->AsTrack()->GetTrackType())) { - trackBeginEnd.begin_element->AsTrack()->SetBrakeClosed( - (trackBeginEnd.begin_element->AsTrack()->GetBrakeBoosterSpeed() >= brakeSpeed) || isClosed); + tileElement->AsTrack()->SetBrakeClosed2( + { trackBeginEnd.begin_x, trackBeginEnd.begin_y }, + (tileElement->AsTrack()->GetBrakeBoosterSpeed() >= brakeSpeed) || isClosed); } // prevent infinite loop @@ -3128,7 +3131,7 @@ void BlockBrakeSetLinkedBrakesClosed(const CoordsXYZ& vehicleTrackLocation, Trac return; } } - } while (trackBeginEnd.begin_element->AsTrack()->GetTrackType() == TrackElemType::Brakes); + } while (TrackTypeIsBrakes(trackBeginEnd.begin_element->AsTrack()->GetTrackType())); } /** @@ -3511,30 +3514,29 @@ static void RideCreateVehiclesFindFirstBlock(const Ride& ride, CoordsXYE* outXYE auto trackType = trackElement->GetTrackType(); switch (trackType) { - case TrackElemType::Up25ToFlat: - case TrackElemType::Up60ToFlat: - if (trackElement->HasChain()) + case TrackElemType::DiagUp25ToFlat: + case TrackElemType::DiagUp60ToFlat: + if (!trackElement->HasChain()) { - *outXYElement = { trackPos, reinterpret_cast(trackElement) }; + break; + } + [[fallthrough]]; + case TrackElemType::DiagBlockBrakes: + { + TileElement* tileElement = MapGetTrackElementAtOfTypeSeq( + { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }, trackType, 0); + + if (tileElement != nullptr) + { + outXYElement->x = trackBeginEnd.begin_x; + outXYElement->y = trackBeginEnd.begin_y; + outXYElement->element = tileElement; return; } break; - case TrackElemType::DiagUp25ToFlat: - case TrackElemType::DiagUp60ToFlat: - if (trackElement->HasChain()) - { - TileElement* tileElement = MapGetTrackElementAtOfTypeSeq( - { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }, trackType, 0); - - if (tileElement != nullptr) - { - outXYElement->x = trackBeginEnd.begin_x; - outXYElement->y = trackBeginEnd.begin_y; - outXYElement->element = tileElement; - return; - } - } - break; + } + case TrackElemType::Up25ToFlat: + case TrackElemType::Up60ToFlat: case TrackElemType::EndStation: case TrackElemType::CableLiftHill: case TrackElemType::BlockBrakes: @@ -3687,8 +3689,8 @@ void Ride::MoveTrainsToBlockBrakes(const CoordsXYZ& firstBlockPosition, TrackEle // All vehicles are in position, set the block brake directly before the station one last time and make sure the brakes // are set appropriately - firstBlock.SetBrakeClosed(true); - if (firstBlock.GetTrackType() == TrackElemType::BlockBrakes) + firstBlock.SetBrakeClosed2(firstBlockPosition, true); + if (TrackTypeIsBlockBrakes(firstBlock.GetTrackType())) { BlockBrakeSetLinkedBrakesClosed(firstBlockPosition, firstBlock, true); } diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 63d673fe1b..e1ba812e22 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -895,7 +895,9 @@ enum TRACK_ELEMENT_SET_COLOUR_SCHEME = (1 << 2), TRACK_ELEMENT_SET_HAS_CABLE_LIFT_TRUE = (1 << 3), TRACK_ELEMENT_SET_HAS_CABLE_LIFT_FALSE = (1 << 4), - TRACK_ELEMENT_SET_SEAT_ROTATION = (1 << 5) + TRACK_ELEMENT_SET_SEAT_ROTATION = (1 << 5), + TRACK_ELEMENT_SET_BRAKE_CLOSED_STATE = (1 << 6), + TRACK_ELEMENT_SET_BRAKE_BOOSTER_SPEED = (1 << 7) }; #define MAX_RIDE_MEASUREMENTS 8 diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index 9ab451c44b..7d075c9f4d 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -452,6 +452,14 @@ std::optional GetTrackElementOriginAndApplyChanges( { trackElement->SetHasCableLift(false); } + if (flags & TRACK_ELEMENT_SET_BRAKE_CLOSED_STATE) + { + trackElement->SetBrakeClosed(extra_params != 0); + } + if (flags & TRACK_ELEMENT_SET_BRAKE_BOOSTER_SPEED) + { + trackElement->SetBrakeBoosterSpeed(static_cast(extra_params & 0xFF)); + } } return retCoordsXYZ; } diff --git a/src/openrct2/ride/RideConstruction.h b/src/openrct2/ride/RideConstruction.h index 52e88b95f6..8c0b463b33 100644 --- a/src/openrct2/ride/RideConstruction.h +++ b/src/openrct2/ride/RideConstruction.h @@ -69,9 +69,6 @@ extern StationIndex gRideEntranceExitPlaceStationIndex; extern RideConstructionState gRideEntranceExitPlacePreviousRideConstructionState; extern uint8_t gRideEntranceExitPlaceDirection; -std::optional GetTrackElementOriginAndApplyChanges( - const CoordsXYZD& location, track_type_t type, uint16_t extra_params, TileElement** output_element, uint16_t flags); - void RideEntranceExitPlaceProvisionalGhost(); void RideEntranceExitRemoveGhost(); void RideRestoreProvisionalTrackPiece(); diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index 9b90e52cfa..591243bd67 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -549,6 +549,7 @@ bool TrackElement::IsBlockStart() const case TrackElemType::EndStation: case TrackElemType::CableLiftHill: case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: return true; case TrackElemType::Up25ToFlat: case TrackElemType::Up60ToFlat: @@ -563,6 +564,24 @@ bool TrackElement::IsBlockStart() const return false; } +void TrackElement::SetBrakeClosed2(const CoordsXY& trackLocation, bool isClosed) +{ + switch (GetTrackType()) + { + case TrackElemType::DiagUp25ToFlat: + case TrackElemType::DiagUp60ToFlat: + case TrackElemType::CableLiftHill: + case TrackElemType::DiagBrakes: + case TrackElemType::DiagBlockBrakes: + GetTrackElementOriginAndApplyChanges( + { trackLocation, GetBaseZ(), GetDirection() }, GetTrackType(), isClosed, nullptr, + TRACK_ELEMENT_SET_BRAKE_CLOSED_STATE); + break; + default: + SetBrakeClosed(isClosed); + } +} + roll_type_t TrackGetActualBank(TileElement* tileElement, roll_type_t bank) { auto ride = GetRide(tileElement->AsTrack()->GetRideIndex()); @@ -624,6 +643,16 @@ bool TrackTypeIsStation(track_type_t trackType) } } +bool TrackTypeIsBrakes(track_type_t trackType) +{ + return (trackType == TrackElemType::Brakes) || (trackType == TrackElemType::DiagBrakes); +} + +bool TrackTypeIsBlockBrakes(track_type_t trackType) +{ + return (trackType == TrackElemType::BlockBrakes) || (trackType == TrackElemType::DiagBlockBrakes); +} + bool TrackElementIsCovered(track_type_t trackElementType) { switch (trackElementType) @@ -655,7 +684,7 @@ bool TrackElementIsCovered(track_type_t trackElementType) bool TrackTypeHasSpeedSetting(track_type_t trackType) { - return trackType == TrackElemType::Brakes || trackType == TrackElemType::Booster || trackType == TrackElemType::BlockBrakes; + return trackType == TrackElemType::Booster || TrackTypeIsBrakes(trackType) || TrackTypeIsBlockBrakes(trackType); } bool TrackTypeIsHelix(track_type_t trackType) diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index 4a2f945986..8e33603349 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -206,6 +206,9 @@ enum TRACK_SLOPE_CURVE_LARGE, TRACK_SLOPE_CURVE_LARGE_BANKED, + TRACK_DIAG_BRAKES, + TRACK_DIAG_BLOCK_BRAKES, + TRACK_GROUP_COUNT, }; @@ -631,7 +634,10 @@ namespace TrackElemType constexpr track_type_t LeftEighthBankToOrthogonalDown25 = 335; constexpr track_type_t RightEighthBankToOrthogonalDown25 = 336; - constexpr track_type_t Count = 337; + constexpr track_type_t DiagBrakes = 337; + constexpr track_type_t DiagBlockBrakes = 338; + + constexpr track_type_t Count = 339; constexpr track_type_t None = 65535; }; // namespace TrackElemType @@ -680,6 +686,11 @@ void TrackGetFront(const CoordsXYE& input, CoordsXYE* output); bool TrackElementIsCovered(track_type_t trackElementType); bool TrackTypeIsStation(track_type_t trackType); +bool TrackTypeIsBrakes(track_type_t trackType); +bool TrackTypeIsBlockBrakes(track_type_t trackType); + +std::optional GetTrackElementOriginAndApplyChanges( + const CoordsXYZD& location, track_type_t type, uint16_t extra_params, TileElement** output_element, uint16_t flags); roll_type_t TrackGetActualBank(TileElement* tileElement, roll_type_t bank); roll_type_t TrackGetActualBank2(int32_t rideType, bool isInverted, roll_type_t bank); diff --git a/src/openrct2/ride/TrackData.cpp b/src/openrct2/ride/TrackData.cpp index 381261a677..ffabe84275 100644 --- a/src/openrct2/ride/TrackData.cpp +++ b/src/openrct2/ride/TrackData.cpp @@ -355,6 +355,8 @@ static constexpr TrackCoordinates _trackCoordinates[] = { { 4, 1, 0, 48, -32, 64 }, // TrackElemType::RightEighthBankToOrthogonalUp25 { 4, 0, 0,-48, -64, 32 }, // TrackElemType::LeftEighthBankToOrthogonalDown25 { 4, 1, 0,-48, -32, 64 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { 4, 4, 0, 0, -32, 32 }, // TrackElemType::DiagBrakes + { 4, 4, 0, 0, -32, 32 }, // TrackElemType::DiagBlockBrakes }; static_assert(std::size(_trackCoordinates) == TrackElemType::Count); @@ -698,6 +700,8 @@ static constexpr uint8_t TrackSequenceProperties[][MaxSequencesPerPiece] = { { 0 }, // TrackElemType::RightEighthBankToOrthogonalUp25 { 0 }, // TrackElemType::LeftEighthBankToOrthogonalDown25 { 0 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + /* DiagonalBrakes */ { 0 }, + /* DiagonalBlockBrakes */ { 0 }, }; static_assert(std::size(TrackSequenceProperties) == TrackElemType::Count); @@ -3344,6 +3348,8 @@ static constexpr std::array TrackBloc TrackBlocksRightEighthToOrthogonalUp25, // TrackElemType::RightEighthBankToOrthogonalUp25 TrackBlocksLeftEighthToOrthogonalDown25, // TrackElemType::LeftEighthBankToOrthogonalDown25 TrackBlocksRightEighthToOrthogonalDown25, // TrackElemType::RightEighthBankToOrthogonalDown25 + TrackBlocks141, // TrackElemType::DiagBrakes + TrackBlocks141, // TrackElemType::DiagBlockBrakes }; static constexpr uint8_t TrackPieceLengths[] = { @@ -3683,7 +3689,9 @@ static constexpr uint8_t TrackPieceLengths[] = { 92, // TrackElemType::LeftEighthBankToOrthogonalUp25 92, // TrackElemType::RightEighthBankToOrthogonalUp25 92, // TrackElemType::LeftEighthBankToOrthogonalDown25 - 92, // TrackElemType::RightEighthBankToOrthogonalDown25 + 92, // TrackElemType::RightEighthBankToOrthogonalDown25 + 45, // TrackElemType::DiagBrakes + 45, // TrackElemType::DiagBlockBrakes }; static_assert(std::size(TrackPieceLengths) == TrackElemType::Count); @@ -4026,6 +4034,8 @@ static constexpr TrackCurveChain gTrackCurveChain[] = { { TRACK_CURVE_RIGHT_LARGE, TRACK_CURVE_RIGHT_LARGE }, // TrackElemType::RightEighthBankToOrthogonalUp25 { TRACK_CURVE_LEFT_LARGE, TRACK_CURVE_LEFT_LARGE }, // TrackElemType::LeftEighthBankToOrthogonalDown25 { TRACK_CURVE_RIGHT_LARGE, TRACK_CURVE_RIGHT_LARGE }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { RideConstructionSpecialPieceSelected | TrackElemType::DiagBrakes, RideConstructionSpecialPieceSelected | TrackElemType::DiagBrakes }, // TrackElemType::DiagBrakes + { TRACK_CURVE_NONE, TRACK_CURVE_NONE }, // TrackElemType::DiagBlockBrakes }; static_assert(std::size(gTrackCurveChain) == TrackElemType::Count); @@ -4557,6 +4567,8 @@ static constexpr track_type_t AlternativeTrackTypes[] = { TrackElemType::None, // TrackElemType::RightEighthBankToOrthogonalUp25 TrackElemType::None, // TrackElemType::LeftEighthBankToOrthogonalDown25 TrackElemType::None, // TrackElemType::RightEighthBankToOrthogonalDown25 + TrackElemType::None, // TrackElemType::DiagBrakes + TrackElemType::None, // TrackElemType::DiagBlockBrakes }; static_assert(std::size(AlternativeTrackTypes) == TrackElemType::Count); @@ -4899,6 +4911,8 @@ static constexpr money64 TrackPricing[] = { 233281, // TrackElemType::RightEighthBankToOrthogonalUp25 233281, // TrackElemType::LeftEighthBankToOrthogonalDown25 233281, // TrackElemType::RightEighthBankToOrthogonalDown25 + 123456, // TrackElemType::DiagBrakes + 123456, // TrackElemType::DiagBlockBrakes }; @@ -5244,6 +5258,8 @@ static constexpr track_type_t TrackElementMirrorMap[] = { TrackElemType::LeftEighthBankToOrthogonalUp25, // TrackElemType::LeftEighthBankToOrthogonalUp25 TrackElemType::RightEighthBankToOrthogonalDown25, // TrackElemType::RightEighthBankToOrthogonalDown25 TrackElemType::LeftEighthBankToOrthogonalDown25, // TrackElemType::LeftEighthBankToOrthogonalDown25 + TrackElemType::DiagBrakes, + TrackElemType::DiagBlockBrakes, }; static_assert(std::size(TrackElementMirrorMap) == TrackElemType::Count); @@ -5585,7 +5601,9 @@ static constexpr uint32_t TrackHeightMarkerPositions[] = { (1 << 0) | (1 << 4), // TrackElemType::RightEighthBankToOrthogonalUp25 (1 << 0) | (1 << 4), // TrackElemType::LeftEighthBankToOrthogonalUp25 (1 << 0) | (1 << 4), // TrackElemType::RightEighthBankToOrthogonalDown25 - (1 << 0) | (1 << 4), // TrackElemType::LeftEighthBankToOrthogonalDown25 + (1 << 0) | (1 << 4), // TrackElemType::LeftEighthBankToOrthogonalDown25 + (1 << 0), // TrackElemType::DiagBrakes + (1 << 0), // TrackElemType::DiagBlockBrakes }; static_assert(std::size(TrackHeightMarkerPositions) == TrackElemType::Count); @@ -5928,7 +5946,9 @@ static constexpr uint8_t TrackSequenceElementAllowedWallEdges[][MaxSequencesPerP { 0, 0b1000, 0b0110, 0b0010, 0b0010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::LeftEighthBankToOrthogonalUp25 { 0, 0b0100, 0b1001, 0b0001, 0b0001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::RightEighthBankToOrthogonalUp25 { 0, 0b1000, 0b0110, 0b0010, 0b0010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::LeftEighthBankToOrthogonalDown25 - { 0, 0b0100, 0b1001, 0b0001, 0b0001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { 0, 0b0100, 0b1001, 0b0001, 0b0001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { 0, 0b0110, 0b1001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::DiagBrakes + { 0, 0b0110, 0b1001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::DiagBlockBrakes }; @@ -6274,6 +6294,8 @@ static constexpr uint16_t TrackFlags[] = { /* TrackElemType::RightEighthBankToOrthogonalUp25 */ TRACK_ELEM_FLAG_TURN_RIGHT | TRACK_ELEM_FLAG_TURN_SLOPED | TRACK_ELEM_FLAG_UP | TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT | TRACK_ELEM_FLAG_ALLOW_LIFT_HILL | TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT, /* TrackElemType::LeftEighthBankToOrthogonalDown25 */ TRACK_ELEM_FLAG_TURN_LEFT | TRACK_ELEM_FLAG_TURN_SLOPED | TRACK_ELEM_FLAG_DOWN | TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT | TRACK_ELEM_FLAG_ALLOW_LIFT_HILL | TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT, /* TrackElemType::RightEighthBankToOrthogonalDown25 */ TRACK_ELEM_FLAG_TURN_RIGHT | TRACK_ELEM_FLAG_TURN_SLOPED | TRACK_ELEM_FLAG_DOWN | TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT | TRACK_ELEM_FLAG_ALLOW_LIFT_HILL | TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT, + /* TrackElemType::DiagBrakes */ 0, + /* TrackElemType::DiagBlockBrakes */ 0, }; static_assert(std::size(TrackFlags) == TrackElemType::Count); // clang-format on @@ -6619,7 +6641,9 @@ static constexpr TrackDefinition TrackDefinitions[] = { TRACK_SLOPE_CURVE_LARGE_BANKED, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, 16 }, // TrackElemType::LeftEighthBankToOrthogonalUp25 { TRACK_SLOPE_CURVE_LARGE_BANKED, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, 16 }, // TrackElemType::RightEighthBankToOrthogonalUp25 { TRACK_SLOPE_CURVE_LARGE_BANKED, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, -16 }, // TrackElemType::LeftEighthBankToOrthogonalDown25 - { TRACK_SLOPE_CURVE_LARGE_BANKED, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, -16 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { TRACK_SLOPE_CURVE_LARGE_BANKED, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, -16 }, // TrackElemType::RightEighthBankToOrthogonalDown25 + { TRACK_DIAG_BRAKES, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, 0 }, // TrackElemType::DiagBrakes + { TRACK_DIAG_BLOCK_BRAKES, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, 0 }, // TrackElemType::DiagBlockBrakes }; static_assert(std::size(TrackDefinitions) == TrackElemType::Count); @@ -6651,7 +6675,8 @@ constexpr static uint8_t TrackTypeToSpinFunction[] = { NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, - NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, + NO_SPIN, NO_SPIN, NO_SPIN, NO_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, L9_SPIN, R9_SPIN, NO_SPIN, + NO_SPIN, }; static_assert(std::size(TrackTypeToSpinFunction) == TrackElemType::Count); @@ -7942,6 +7967,8 @@ static constexpr StringId RideConfigurationStringIds[] = { STR_EMPTY, // TrackElemType::RightEighthBankToOrthogonalUp25 STR_EMPTY, // TrackElemType::LeftEighthBankToOrthogonalDown25 STR_EMPTY, // TrackElemType::RightEighthBankToOrthogonalDown25 + STR_BRAKES, // TrackElemType::DiagBrakes + STR_BLOCK_BRAKES // TrackElemType::DiagBlockBrakes }; static_assert(std::size(RideConfigurationStringIds) == TrackElemType::Count); diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp index 2b5fe0633c..83902874d1 100644 --- a/src/openrct2/ride/TrackPaint.cpp +++ b/src/openrct2/ride/TrackPaint.cpp @@ -110,6 +110,20 @@ const uint8_t edges_4x4[] = { }; // clang-format on +const int32_t DiagBlockedSegments[] = { + SEGMENT_C4 | SEGMENT_CC | SEGMENT_D4 | SEGMENT_BC, + SEGMENT_C4 | SEGMENT_CC | SEGMENT_C8 | SEGMENT_B4, + SEGMENT_D0 | SEGMENT_C4 | SEGMENT_C0 | SEGMENT_D4, + SEGMENT_D0 | SEGMENT_C4 | SEGMENT_B8 | SEGMENT_C8, +}; + +const uint8_t DiagSupportSegments[] = { + 1, + 0, + 2, + 3, +}; + const uint8_t track_map_1x4[][4] = { { 0, 1, 2, 3 }, { 2, 3, 0, 1 }, diff --git a/src/openrct2/ride/TrackPaint.h b/src/openrct2/ride/TrackPaint.h index c95f8cbf85..65a7e85a66 100644 --- a/src/openrct2/ride/TrackPaint.h +++ b/src/openrct2/ride/TrackPaint.h @@ -28,6 +28,9 @@ extern const uint8_t edges_4x4[]; extern const uint8_t track_map_1x4[][4]; +extern const int32_t DiagBlockedSegments[]; +extern const uint8_t DiagSupportSegments[]; + enum { SPR_FLOOR_PLANKS = 3395, diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 214d157e05..98033d02e7 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -6081,6 +6081,7 @@ void Vehicle::CheckAndApplyBlockSectionStopSite() switch (trackType) { case TrackElemType::BlockBrakes: + case TrackElemType::DiagBlockBrakes: if (curRide->IsBlockSectioned() && trackElement->AsTrack()->IsBrakeClosed()) ApplyStopBlockBrake(); else @@ -6185,12 +6186,13 @@ static void block_brakes_open_previous_section( // Get the start of the track block instead of the end location = { trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_z }; - auto trackElement = MapGetTrackElementAt(location); - if (trackElement == nullptr) + auto trackOrigin = MapGetTrackElementAtOfTypeSeq(location, trackBeginEnd.begin_element->AsTrack()->GetTrackType(), 0); + if (trackOrigin == nullptr) { return; } - trackElement->SetBrakeClosed(false); + auto trackElement = trackOrigin->AsTrack(); + trackElement->SetBrakeClosed2(location, false); MapInvalidateElement(location, reinterpret_cast(trackElement)); auto trackType = trackElement->GetTrackType(); @@ -6198,7 +6200,7 @@ static void block_brakes_open_previous_section( { OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BlockBrakeClose, location); } - else if (trackType == TrackElemType::BlockBrakes) + else if (TrackTypeIsBlockBrakes(trackType)) { OpenRCT2::Audio::Play3D(OpenRCT2::Audio::SoundId::BlockBrakeClose, location); BlockBrakeSetLinkedBrakesClosed(location, *trackElement, false); @@ -6414,7 +6416,7 @@ void Vehicle::UpdateSwingingCar() break; } - if (TrackTypeIsStation(trackType) || trackType == TrackElemType::Brakes || trackType == TrackElemType::BlockBrakes) + if (TrackTypeIsStation(trackType) || TrackTypeIsBrakes(trackType) || TrackTypeIsBlockBrakes(trackType)) { dx = 0; cx = 0; @@ -7398,7 +7400,7 @@ void Vehicle::Sub6DBF3E() */ uint8_t Vehicle::ChooseBrakeSpeed() const { - if (GetTrackType() != TrackElemType::Brakes) + if (!TrackTypeIsBrakes(GetTrackType())) return brake_speed; auto trackElement = MapGetTrackElementAtOfTypeSeq(TrackLocation, GetTrackType(), 0); if (trackElement != nullptr) @@ -7418,7 +7420,7 @@ void Vehicle::PopulateBrakeSpeed(const CoordsXYZ& vehicleTrackLocation, TrackEle { auto trackSpeed = brake.GetBrakeBoosterSpeed(); brake_speed = trackSpeed; - if (brake.GetTrackType() != TrackElemType::Brakes) + if (!TrackTypeIsBrakes(brake.GetTrackType())) { BlockBrakeSpeed = trackSpeed; return; @@ -7430,12 +7432,12 @@ void Vehicle::PopulateBrakeSpeed(const CoordsXYZ& vehicleTrackLocation, TrackEle uint16_t timeoutCount = 256; do { - if (output.element->AsTrack()->GetTrackType() == TrackElemType::BlockBrakes) + if (TrackTypeIsBlockBrakes(output.element->AsTrack()->GetTrackType())) { BlockBrakeSpeed = output.element->AsTrack()->GetBrakeBoosterSpeed(); return; } - if (output.element->AsTrack()->GetTrackType() != TrackElemType::Brakes) + if (TrackTypeIsBrakes(output.element->AsTrack()->GetTrackType())) { break; } @@ -7471,9 +7473,8 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Rid { if (next_vehicle_on_train.IsNull()) { - tileElement->AsTrack()->SetBrakeClosed(true); - - if (trackType == TrackElemType::BlockBrakes || trackType == TrackElemType::EndStation) + tileElement->AsTrack()->SetBrakeClosed2(TrackLocation, true); + if (TrackTypeIsBlockBrakes(trackType) || trackType == TrackElemType::EndStation) { if (!(rideEntry.Cars[0].flags & CAR_ENTRY_FLAG_POWERED)) { @@ -7482,7 +7483,7 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, const Rid } MapInvalidateElement(TrackLocation, tileElement); block_brakes_open_previous_section(curRide, TrackLocation, tileElement); - if (trackType == TrackElemType::BlockBrakes) + if (TrackTypeIsBlockBrakes(trackType)) { BlockBrakeSetLinkedBrakesClosed(TrackLocation, *tileElement->AsTrack(), true); } @@ -7656,7 +7657,7 @@ Loc6DAEB9: acceleration = 0x50000; } } - else if (trackType == TrackElemType::Brakes) + else if (TrackTypeIsBrakes(trackType)) { bool hasBrakesFailure = curRide.lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN && curRide.breakdown_reason_pending == BREAKDOWN_BRAKES_FAILURE; @@ -8050,7 +8051,7 @@ bool Vehicle::UpdateTrackMotionBackwards(const CarEntry* carEntry, const Ride& c } } - if (trackType == TrackElemType::Brakes) + if (TrackTypeIsBrakes(trackType)) { auto brakeSpeed = ChooseBrakeSpeed(); diff --git a/src/openrct2/ride/VehicleSubpositionData.cpp b/src/openrct2/ride/VehicleSubpositionData.cpp index 4377f320aa..cfdd3638b5 100644 --- a/src/openrct2/ride/VehicleSubpositionData.cpp +++ b/src/openrct2/ride/VehicleSubpositionData.cpp @@ -30076,6 +30076,8 @@ static constexpr const VehicleInfoList *TrackVehicleInfoListDefault[] = { &TrackVehicleInfoRightEighthBankToOrthogonalUp250, &TrackVehicleInfoRightEighthBankToOrthogonalUp251, &TrackVehicleInfoRightEighthBankToOrthogonalUp252, &TrackVehicleInfoRightEighthBankToOrthogonalUp253, // TrackElemType::RightEighthBankBankToOrthogonalUp25 &TrackVehicleInfoLeftEighthBankToOrthogonalDown250, &TrackVehicleInfoLeftEighthBankToOrthogonalDown251, &TrackVehicleInfoLeftEighthBankToOrthogonalDown252, &TrackVehicleInfoLeftEighthBankToOrthogonalDown253, // TrackElemType::LeftEighthBankBankToOrthogonalDown25 &TrackVehicleInfoRightEighthBankToOrthogonalDown250, &TrackVehicleInfoRightEighthBankToOrthogonalDown251, &TrackVehicleInfoRightEighthBankToOrthogonalDown252, &TrackVehicleInfoRightEighthBankToOrthogonalDown253, // TrackElemType::RightEighthBankBankToOrthogonalDown25 + &TrackVehicleInfo_9162E6, &TrackVehicleInfo_916408, &TrackVehicleInfo_91652A, &TrackVehicleInfo_91664C, // DiagBrakes + &TrackVehicleInfo_9162E6, &TrackVehicleInfo_916408, &TrackVehicleInfo_91652A, &TrackVehicleInfo_91664C, // DiagBlockBrakes }; static_assert(std::size(TrackVehicleInfoListDefault) == VehicleTrackSubpositionSizeDefault); diff --git a/src/openrct2/ride/coaster/CompactInvertedCoaster.cpp b/src/openrct2/ride/coaster/CompactInvertedCoaster.cpp index c7b7eff7ff..25c054904f 100644 --- a/src/openrct2/ride/coaster/CompactInvertedCoaster.cpp +++ b/src/openrct2/ride/coaster/CompactInvertedCoaster.cpp @@ -18,6 +18,28 @@ #include "../TrackData.h" #include "../TrackPaint.h" +static constexpr const uint32_t CompactInvertedDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, +}; + +static constexpr const uint32_t CompactInvertedDiagBlockBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, + }, + { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + }, +}; + /** rct2: 0x008AE6E0 */ static void CompactInvertedRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -6344,6 +6366,47 @@ static void CompactInvertedRCTrackDiagFlat( } } +static void CompactInvertedRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height + 29, direction, trackSequence, session.TrackColours[SCHEME_TRACK], CompactInvertedDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 38, + session.TrackColours[SCHEME_SUPPORTS]); + } + PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); +} + +static void CompactInvertedRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height + 29, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + CompactInvertedDiagBlockBrakeImages[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 38, + session.TrackColours[SCHEME_SUPPORTS]); + } + PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); +} + /** rct2: 0x008AEBB0 */ static void CompactInvertedRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -9094,6 +9157,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCompactInvertedRC(int32_t trackType) return CompactInvertedRCTrackDiagRightBank; case TrackElemType::BlockBrakes: return CompactInvertedRCTrackBlockBrakes; + case TrackElemType::DiagBrakes: + return CompactInvertedRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return CompactInvertedRCTrackDiagBlockBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/CorkscrewRollerCoaster.cpp b/src/openrct2/ride/coaster/CorkscrewRollerCoaster.cpp index 01cdb6f6b9..01bc122f11 100644 --- a/src/openrct2/ride/coaster/CorkscrewRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/CorkscrewRollerCoaster.cpp @@ -30,6 +30,28 @@ static constexpr uint32_t _CorkscrewRCBlockBrakeImages[NumOrthogonalDirections][ { CORKSCREW_RC_BLOCK_BRAKE_NW_SE_OPEN, CORKSCREW_RC_BLOCK_BRAKE_NW_SE_CLOSED }, }; +static constexpr const uint32_t CorkscrewRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_CORKSCREW_DIAG_BRAKES, + SPR_G2_CORKSCREW_DIAG_BRAKES + 1, + SPR_G2_CORKSCREW_DIAG_BRAKES, + SPR_G2_CORKSCREW_DIAG_BRAKES + 1, +}; + +static constexpr const uint32_t CorkscrewRCDiagBlockBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_CORKSCREW_DIAG_BRAKES + 3, + SPR_G2_CORKSCREW_DIAG_BRAKES + 5, + SPR_G2_CORKSCREW_DIAG_BRAKES + 3, + SPR_G2_CORKSCREW_DIAG_BRAKES + 5, + }, + { + SPR_G2_CORKSCREW_DIAG_BRAKES + 2, + SPR_G2_CORKSCREW_DIAG_BRAKES + 4, + SPR_G2_CORKSCREW_DIAG_BRAKES + 2, + SPR_G2_CORKSCREW_DIAG_BRAKES + 4, + }, +}; + /** rct2: 0x008A7AF8 */ static void CorkscrewRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -6055,6 +6077,45 @@ static void CorkscrewRCTrackDiagFlat( } } +static void CorkscrewRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], CorkscrewRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + +static void CorkscrewRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + CorkscrewRCDiagBlockBrakeImages[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + /** rct2: 0x008A8008 */ static void CorkscrewRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -10280,6 +10341,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionCorkscrewRC(int32_t trackType) return CorkscrewRCTrackDiagRightBank; case TrackElemType::BlockBrakes: return CorkscrewRCTrackBlockBrakes; + case TrackElemType::DiagBrakes: + return CorkscrewRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return CorkscrewRCTrackDiagBlockBrakes; case TrackElemType::Booster: return CorkscrewRCTrackBooster; diff --git a/src/openrct2/ride/coaster/InvertedRollerCoaster.cpp b/src/openrct2/ride/coaster/InvertedRollerCoaster.cpp index 077312e15c..b061aad999 100644 --- a/src/openrct2/ride/coaster/InvertedRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/InvertedRollerCoaster.cpp @@ -18,6 +18,13 @@ #include "../TrackData.h" #include "../TrackPaint.h" +static constexpr const uint32_t InvertedRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_BM_INVERTED_DIAG_BRAKES, + SPR_G2_BM_INVERTED_DIAG_BRAKES + 1, + SPR_G2_BM_INVERTED_DIAG_BRAKES, + SPR_G2_BM_INVERTED_DIAG_BRAKES + 1, +}; + /** rct2: 0x008A92E8 */ static void InvertedRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -6068,6 +6075,26 @@ static void InvertedRCTrackDiagFlat( } } +static void inverted_rc_track_diag_brakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 1, height + 29, direction, trackSequence, session.TrackColours[SCHEME_TRACK], InvertedRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Boxed, DiagSupportSegments[direction], 0, height + 44, + session.TrackColours[SCHEME_SUPPORTS]); + } + PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); +} + /** rct2: 0x008A97B8 */ static void InvertedRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -10852,6 +10879,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionInvertedRC(int32_t trackType) case TrackElemType::RightBankedDown25ToFlat: return InvertedRCTrackRightBanked25DegDownToFlat; + case TrackElemType::DiagBrakes: + case TrackElemType::DiagBlockBrakes: + return inverted_rc_track_diag_brakes; + case TrackElemType::Booster: return InvertedRCTrackBooster; } diff --git a/src/openrct2/ride/coaster/JuniorRollerCoaster.cpp b/src/openrct2/ride/coaster/JuniorRollerCoaster.cpp index 38993eb026..8d3ff7ee2a 100644 --- a/src/openrct2/ride/coaster/JuniorRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/JuniorRollerCoaster.cpp @@ -606,6 +606,12 @@ enum SPR_JUNIOR_RC_DIAG_RIGHT_BANK_TO_25_DEG_UP_E_W = 28380, SPR_JUNIOR_RC_DIAG_RIGHT_BANK_TO_25_DEG_UP_S_N = 28381, SPR_JUNIOR_RC_DIAG_RIGHT_BANK_TO_25_DEG_UP_E_W_PART_0_2 = 28382, + SPR_JUNIOR_RC_DIAG_BRAKES_E_W = SPR_G2_JUNIOR_DIAG_BRAKES, + SPR_JUNIOR_RC_DIAG_BRAKES_N_S = SPR_G2_JUNIOR_DIAG_BRAKES + 1, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_CLOSED = SPR_G2_JUNIOR_DIAG_BRAKES + 2, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_OPEN = SPR_G2_JUNIOR_DIAG_BRAKES + 3, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_CLOSED = SPR_G2_JUNIOR_DIAG_BRAKES + 4, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_OPEN = SPR_G2_JUNIOR_DIAG_BRAKES + 5, }; static constexpr uint32_t junior_rc_track_pieces_flat[3][4] = { @@ -1813,6 +1819,29 @@ static constexpr uint32_t junior_rc_track_pieces_diag_60_deg_down_to_25_deg_down }, }; +static constexpr const uint32_t junior_rc_track_pieces_diag_brakes[4] = { + SPR_JUNIOR_RC_DIAG_BRAKES_E_W, + SPR_JUNIOR_RC_DIAG_BRAKES_N_S, + SPR_JUNIOR_RC_DIAG_BRAKES_E_W, + SPR_JUNIOR_RC_DIAG_BRAKES_N_S, +}; + +static constexpr const uint32_t junior_rc_track_pieces_diag_blockbrakes[2][4] = { + { + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_OPEN, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_OPEN, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_OPEN, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_OPEN, + }, + { + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_CLOSED, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_CLOSED, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_E_W_CLOSED, + SPR_JUNIOR_RC_DIAG_BLOCKBRAKES_N_S_CLOSED, + }, +}; + + void JuniorRCPaintTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, uint16_t height, const TrackElement& trackElement, JuniorRCChainType chainType) @@ -4368,20 +4397,6 @@ static void JuniorRCRightEighthToOrthogonalBankPaintSetup( JuniorRCLeftEighthToDiagBankPaintSetup(session, ride, trackSequence, (direction + 3) % 4, height, trackElement); } -static constexpr int32_t junior_rc_diag_blocked_segments[] = { - SEGMENT_C4 | SEGMENT_CC | SEGMENT_D4 | SEGMENT_BC, - SEGMENT_C4 | SEGMENT_CC | SEGMENT_C8 | SEGMENT_B4, - SEGMENT_D0 | SEGMENT_C4 | SEGMENT_C0 | SEGMENT_D4, - SEGMENT_D0 | SEGMENT_C4 | SEGMENT_B8 | SEGMENT_C8, -}; - -static constexpr uint8_t junior_rc_diag_support_segment[] = { - 1, - 0, - 2, - 3, -}; - void JuniorRCPaintTrackDiagFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, uint16_t height, const TrackElement& trackElement, JuniorRCChainType chainType) @@ -4394,14 +4409,55 @@ void JuniorRCPaintTrackDiagFlat( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } +static void JuniorRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 1, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], junior_rc_track_pieces_diag_brakes, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); +} + +static void JuniorRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 1, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + junior_rc_track_pieces_diag_blockbrakes[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); +} + void JuniorRCPaintTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, uint16_t height, const TrackElement& trackElement, JuniorRCChainType chainType) @@ -4414,10 +4470,10 @@ void JuniorRCPaintTrackDiag25DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4435,10 +4491,10 @@ void JuniorRCPaintTrackDiagFlatTo25DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -4459,10 +4515,10 @@ void JuniorRCPaintTrackDiagFlatTo60DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height + 6, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height + 6, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 64, 0x20); } @@ -4480,10 +4536,10 @@ void JuniorRCPaintTrackDiag25DegUpToFlat( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4504,10 +4560,10 @@ void JuniorRCPaintTrackDiag60DegUpToFlat( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height + 13, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height + 13, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 64, 0x20); } @@ -4525,10 +4581,10 @@ void JuniorRCPaintTrackDiag25DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4546,10 +4602,10 @@ void JuniorRCPaintTrackDiagFlatTo25DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4570,10 +4626,10 @@ void JuniorRCPaintTrackDiagFlatTo60DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height + 7, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height + 7, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -4591,10 +4647,10 @@ void JuniorRCPaintTrackDiag25DegDownToFlat( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -4615,10 +4671,10 @@ void JuniorRCPaintTrackDiag60DegDownToFlat( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4759,10 +4815,10 @@ static void JuniorRCDiagFlatToLeftBankPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -4786,10 +4842,10 @@ static void JuniorRCDiagFlatToRightBankPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -4813,10 +4869,10 @@ static void JuniorRCDiagLeftBankToFlatPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -4840,10 +4896,10 @@ static void JuniorRCDiagRightBankToFlatPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -4867,10 +4923,10 @@ static void JuniorRCDiagLeftBankTo25DegUpPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -4894,10 +4950,10 @@ static void JuniorRCDiagRightBankTo25DegUpPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -4921,10 +4977,10 @@ static void JuniorRCDiag25DegUpToLeftBankPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4948,10 +5004,10 @@ static void JuniorRCDiag25DegUpToRightBankPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -4975,10 +5031,10 @@ static void JuniorRCDiagLeftBankTo25DegDownPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -5002,10 +5058,10 @@ static void JuniorRCDiagRightBankTo25DegDownPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 4, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20); } @@ -5029,10 +5085,10 @@ static void JuniorRCDiag25DegDownToLeftBankPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -5056,10 +5112,10 @@ static void JuniorRCDiag25DegDownToRightBankPaintSetup( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20); } @@ -5093,10 +5149,10 @@ static void JuniorRCDiagLeftBankPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -5116,10 +5172,10 @@ static void JuniorRCDiagRightBankPaintSetup( { MetalASupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } @@ -5384,10 +5440,10 @@ void JuniorRCPaintTrackDiag60DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 36, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 36, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 104, 0x20); } @@ -5405,10 +5461,10 @@ void JuniorRCPaintTrackDiag60DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 28, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 28, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 104, 0x20); } @@ -5426,10 +5482,10 @@ void JuniorRCPaintTrackDiag25DegUpTo60DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 16, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 16, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 72, 0x20); } @@ -5458,10 +5514,10 @@ void JuniorRCPaintTrackDiag60DegUpTo25DegUp( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 21, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 21, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 72, 0x20); } @@ -5490,10 +5546,10 @@ void JuniorRCPaintTrackDiag25DegDownTo60DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 17, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 17, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 72, 0x20); } @@ -5511,10 +5567,10 @@ void JuniorRCPaintTrackDiag60DegDownTo25DegDown( { MetalBSupportsPaintSetup( session, (direction & 1) ? MetalSupportType::ForkAlt : MetalSupportType::Fork, - junior_rc_diag_support_segment[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + DiagSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); } - int32_t blockedSegments = junior_rc_diag_blocked_segments[trackSequence]; + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); PaintUtilSetGeneralSupportHeight(session, height + 72, 0x20); } @@ -6111,6 +6167,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionJuniorRC(int32_t trackType) case TrackElemType::BlockBrakes: return JuniorRCBlockBrakePaintSetup; + case TrackElemType::DiagBrakes: + return JuniorRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return JuniorRCTrackDiagBlockBrakes; case TrackElemType::Booster: return JuniorRCBoosterPaintSetup; diff --git a/src/openrct2/ride/coaster/LayDownRollerCoaster.cpp b/src/openrct2/ride/coaster/LayDownRollerCoaster.cpp index 115839110a..059d895981 100644 --- a/src/openrct2/ride/coaster/LayDownRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/LayDownRollerCoaster.cpp @@ -17,6 +17,51 @@ #include "../RideData.h" #include "../TrackData.h" #include "../TrackPaint.h" +static constexpr const uint32_t LaydownDiagBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_CORKSCREW_DIAG_BRAKES, + SPR_G2_CORKSCREW_DIAG_BRAKES + 1, + SPR_G2_CORKSCREW_DIAG_BRAKES, + SPR_G2_CORKSCREW_DIAG_BRAKES + 1, + }, + { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + }, +}; + +static constexpr const uint32_t LaydownDiagBlockBrakeImages[2][2][NumOrthogonalDirections] = { + { + { + SPR_G2_CORKSCREW_DIAG_BRAKES + 3, + SPR_G2_CORKSCREW_DIAG_BRAKES + 5, + SPR_G2_CORKSCREW_DIAG_BRAKES + 3, + SPR_G2_CORKSCREW_DIAG_BRAKES + 5, + }, + { + SPR_G2_CORKSCREW_DIAG_BRAKES + 2, + SPR_G2_CORKSCREW_DIAG_BRAKES + 4, + SPR_G2_CORKSCREW_DIAG_BRAKES + 2, + SPR_G2_CORKSCREW_DIAG_BRAKES + 4, + }, + }, + { + { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 2, + }, + { + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, + SPR_G2_SLC_DIAG_BRAKES, + SPR_G2_SLC_DIAG_BRAKES + 1, + }, + }, +}; /** rct2: 0x0082491C */ static void LayDownRCTrackFlat( @@ -4433,6 +4478,86 @@ static void LayDownRCTrackDiagFlat( } } +static void LayDownRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + if (trackElement.IsInverted()) + { + TrackPaintUtilDiagTilesPaint( + session, -3, height + 24, direction, trackSequence, session.TrackColours[SCHEME_TRACK], LaydownDiagBrakeImages[1], + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 33, + session.TrackColours[SCHEME_SUPPORTS]); + } + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + } + else + { + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], LaydownDiagBrakeImages[0], + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + } +} + +static void LayDownRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + if (trackElement.IsInverted()) + { + TrackPaintUtilDiagTilesPaint( + session, -3, height + 24, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + LaydownDiagBlockBrakeImages[1][trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 33, + session.TrackColours[SCHEME_SUPPORTS]); + } + PaintUtilSetGeneralSupportHeight(session, height + 33, 0x20); + } + else + { + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + LaydownDiagBlockBrakeImages[0][trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + } +} + /** rct2: 0x00824E2C */ static void LayDownRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -8616,6 +8741,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLayDownRC(int32_t trackType) return LayDownRCTrackDiagRightBank; case TrackElemType::BlockBrakes: return LayDownRCTrackBlockBrakes; + case TrackElemType::DiagBrakes: + return LayDownRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return LayDownRCTrackDiagBlockBrakes; // Inverted only case TrackElemType::LeftFlyerTwistDown: diff --git a/src/openrct2/ride/coaster/LimLaunchedRollerCoaster.cpp b/src/openrct2/ride/coaster/LimLaunchedRollerCoaster.cpp index e1f4b9b842..18f7427dc7 100644 --- a/src/openrct2/ride/coaster/LimLaunchedRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/LimLaunchedRollerCoaster.cpp @@ -30,6 +30,28 @@ static constexpr uint32_t _LimLauncherBlockBrakeImages[NumOrthogonalDirections][ { LIM_LAUNCHED_RC_BLOCK_BRAKE_NW_SE_OPEN, LIM_LAUNCHED_RC_BLOCK_BRAKE_NW_SE_CLOSED }, }; +static constexpr const uint32_t LimLaunchedRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 1, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 1, +}; + +static constexpr const uint32_t LimLaunchedRCDiagBlockBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 3, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 5, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 3, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 5, + }, + { + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 2, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 4, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 2, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 4, + }, +}; + /** rct2: 0x008A6D50, 0x008A6D60, 0x008A6D70 */ static void LimLaunchedRCTrackStation( PaintSession& session, const Ride& ride, [[maybe_unused]] uint8_t trackSequence, uint8_t direction, int32_t height, @@ -5695,6 +5717,45 @@ static void LimLaunchedRCTrackBooster( PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); } +static void LimLaunchedRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], LimLaunchedRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + +static void LimLaunchedRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + LimLaunchedRCDiagBlockBrakeImages[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(int32_t trackType) { switch (trackType) @@ -5968,6 +6029,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLimLaunchedRC(int32_t trackType) return LimLaunchedRCTrackRightLargeZeroGRollDown; case TrackElemType::Booster: return LimLaunchedRCTrackBooster; + case TrackElemType::DiagBrakes: + return LimLaunchedRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return LimLaunchedRCTrackDiagBlockBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/LoopingRollerCoaster.cpp b/src/openrct2/ride/coaster/LoopingRollerCoaster.cpp index 1964af1394..929cb013dd 100644 --- a/src/openrct2/ride/coaster/LoopingRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/LoopingRollerCoaster.cpp @@ -24,6 +24,13 @@ static constexpr auto SPR_LOOPING_RC_BOOSTER_NW_SE = 15011; static constexpr auto SPR_LOOPING_RC_FLAT_CHAINED_SW_NE = 15016; static constexpr auto SPR_LOOPING_RC_FLAT_CHAINED_NW_SE = 15017; +static constexpr const uint32_t LoopingRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_LOOPING_DIAG_BRAKES, + SPR_G2_LOOPING_DIAG_BRAKES + 1, + SPR_G2_LOOPING_DIAG_BRAKES, + SPR_G2_LOOPING_DIAG_BRAKES + 1, +}; + /** rct2: 0x008A6370 */ static void LoopingRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -5480,6 +5487,26 @@ static void LoopingRCTrackDiagFlat( } } +static void LoopingRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], LoopingRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + // TODO: draw brake sprite layers + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, SEGMENTS_ALL, 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + /** rct2: 0x008A67C0 */ static void LoopingRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -9895,6 +9922,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionLoopingRC(int32_t trackType) case TrackElemType::Booster: return LoopingRCTrackBooster; + + case TrackElemType::DiagBrakes: + case TrackElemType::DiagBlockBrakes: + return LoopingRCTrackDiagBrakes; } return GetTrackPaintFunctionLimLaunchedRC(trackType); } diff --git a/src/openrct2/ride/coaster/MineTrainCoaster.cpp b/src/openrct2/ride/coaster/MineTrainCoaster.cpp index e40be7ec65..27bd728580 100644 --- a/src/openrct2/ride/coaster/MineTrainCoaster.cpp +++ b/src/openrct2/ride/coaster/MineTrainCoaster.cpp @@ -30,6 +30,27 @@ static constexpr uint32_t _MineTrainBlockBrakeImages[NumOrthogonalDirections][2] { MINE_TRAIN_BLOCK_BRAKE_NW_SE_OPEN, MINE_TRAIN_BLOCK_BRAKE_NW_SE_CLOSED }, }; +static constexpr const uint32_t MinetrainRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_MINETRAIN_DIAG_BRAKES, + SPR_G2_MINETRAIN_DIAG_BRAKES + 1, + SPR_G2_MINETRAIN_DIAG_BRAKES, + SPR_G2_MINETRAIN_DIAG_BRAKES + 1, +}; + +static constexpr const uint32_t MinetrainRCDiagBlockBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_MINETRAIN_DIAG_BRAKES + 3, + SPR_G2_MINETRAIN_DIAG_BRAKES + 5, + SPR_G2_MINETRAIN_DIAG_BRAKES + 3, + SPR_G2_MINETRAIN_DIAG_BRAKES + 5, + }, + { + SPR_G2_MINETRAIN_DIAG_BRAKES + 2, + SPR_G2_MINETRAIN_DIAG_BRAKES + 4, + SPR_G2_MINETRAIN_DIAG_BRAKES + 2, + SPR_G2_MINETRAIN_DIAG_BRAKES + 4, + }, +}; /** rct2: 0x0071BFA4 */ static void MineTrainRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -5393,6 +5414,53 @@ static void MineTrainRCTrackDiagFlat( } } +static void MineTrainRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 1, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], MinetrainRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 1) + { + int32_t woodenSupportSegments[] = { 8, 9, 10, 11 }; + WoodenASupportsPaintSetup(session, woodenSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + if (trackSequence == 2) + { + int32_t woodenSupportSegments[] = { 10, 11, 8, 9 }; + WoodenASupportsPaintSetup(session, woodenSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, SEGMENTS_ALL, 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + +static void MineTrainRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 13, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + MinetrainRCDiagBlockBrakeImages[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 1) + { + int32_t woodenSupportSegments[] = { 8, 9, 10, 11 }; + WoodenASupportsPaintSetup(session, woodenSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + if (trackSequence == 2) + { + int32_t woodenSupportSegments[] = { 10, 11, 8, 9 }; + WoodenASupportsPaintSetup(session, woodenSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, SEGMENTS_ALL, 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + /** rct2: 0x0071C414 */ static void MineTrainRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -7269,6 +7337,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMineTrainRC(int32_t trackType) return MineTrainRCTrackDiagRightBank; case TrackElemType::BlockBrakes: return MineTrainRCTrackBlockBrakes; + case TrackElemType::DiagBrakes: + return MineTrainRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return MineTrainRCTrackDiagBlockBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/MultiDimensionRollerCoaster.cpp b/src/openrct2/ride/coaster/MultiDimensionRollerCoaster.cpp index aa239a9986..392a68ffff 100644 --- a/src/openrct2/ride/coaster/MultiDimensionRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/MultiDimensionRollerCoaster.cpp @@ -33,6 +33,52 @@ static constexpr uint32_t MULTI_DIM_INVERTED_BLOCK_BRAKE_NW_SE_OPEN = 26552; static constexpr uint32_t MULTI_DIM_INVERTED_BLOCK_BRAKE_SW_NE_CLOSED = 26553; static constexpr uint32_t MULTI_DIM_INVERTED_BLOCK_BRAKE_NW_SE_CLOSED = 26554; +static constexpr const uint32_t MultidimDiagBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 1, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 1, + }, + { + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 1, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 1, + }, +}; + +static constexpr const uint32_t MultidimDiagBlockBrakeImages[2][2][NumOrthogonalDirections] = { + { + { + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 3, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 5, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 3, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 5, + }, + { + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 4, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 4, + }, + }, + { + { + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 4, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 4, + }, + { + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 3, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 2, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 3, + }, + }, +}; + /** rct2: 0x00792D88 */ static void MultiDimensionRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -7038,6 +7084,86 @@ static void MultiDimensionRCTrackDiagFlat( } } +static void MultiDimensionRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + if (trackElement.IsInverted()) + { + TrackPaintUtilDiagTilesPaint( + session, -3, height + 24, direction, trackSequence, session.TrackColours[SCHEME_TRACK], MultidimDiagBrakeImages[1], + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 36, + session.TrackColours[SCHEME_SUPPORTS]); + } + } + else + { + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], MultidimDiagBrakeImages[0], + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + } +} + +static void MultiDimensionRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + if (trackElement.IsInverted()) + { + TrackPaintUtilDiagTilesPaint( + session, -3, height + 24, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + MultidimDiagBlockBrakeImages[1][trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height + 36, + session.TrackColours[SCHEME_SUPPORTS]); + } + } + else + { + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + MultidimDiagBlockBrakeImages[0][trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, + nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::TubesInverted, DiagSupportSegments[direction], 0, height, + session.TrackColours[SCHEME_SUPPORTS]); + } + + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); + } +} + /** rct2: 0x00793158 */ static void MultiDimensionRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -13294,6 +13420,11 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionMultiDimensionRC(int32_t trackType) return MultiDimensionRCTrackMultidimFlatTo90DegDownQuarterLoop; case TrackElemType::MultiDimInvertedUp90ToFlatQuarterLoop: return MultiDimensionRCTrackMultidimInverted90DegUpToFlatQuarterLoop; + + case TrackElemType::DiagBrakes: + return MultiDimensionRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return MultiDimensionRCTrackDiagBlockBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/StandUpRollerCoaster.cpp b/src/openrct2/ride/coaster/StandUpRollerCoaster.cpp index dc73abd592..02b8ab4440 100644 --- a/src/openrct2/ride/coaster/StandUpRollerCoaster.cpp +++ b/src/openrct2/ride/coaster/StandUpRollerCoaster.cpp @@ -30,6 +30,28 @@ static constexpr uint32_t _StandUpBlockBrakeImages[NumOrthogonalDirections][2] = { STAND_UP_BLOCK_BRAKE_NW_SE_OPEN, STAND_UP_BLOCK_BRAKE_NW_SE_CLOSED }, }; +static constexpr const uint32_t StandupRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_STANDUP_DIAG_BRAKES, + SPR_G2_STANDUP_DIAG_BRAKES + 1, + SPR_G2_STANDUP_DIAG_BRAKES, + SPR_G2_STANDUP_DIAG_BRAKES + 1, +}; + +static constexpr const uint32_t StandupRCDiagBlockBrakeImages[2][NumOrthogonalDirections] = { + { + SPR_G2_STANDUP_DIAG_BRAKES + 3, + SPR_G2_STANDUP_DIAG_BRAKES + 5, + SPR_G2_STANDUP_DIAG_BRAKES + 3, + SPR_G2_STANDUP_DIAG_BRAKES + 5, + }, + { + SPR_G2_STANDUP_DIAG_BRAKES + 2, + SPR_G2_STANDUP_DIAG_BRAKES + 4, + SPR_G2_STANDUP_DIAG_BRAKES + 2, + SPR_G2_STANDUP_DIAG_BRAKES + 4, + }, +}; + /** rct2: 0x008A7114 */ static void StandUpRCTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -5906,6 +5928,44 @@ static void StandUpRCTrackDiagFlat( } } +static void StandUpRCTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], StandupRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + +static void StandUpRCTrackDiagBlockBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], + StandupRCDiagBlockBrakeImages[trackElement.IsBrakeClosed()], defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Tubes, DiagSupportSegments[direction], 8, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + /** rct2: 0x008A7524 */ static void StandUpRCTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -8978,6 +9038,10 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionStandUpRC(int32_t trackType) return StandUpRCTrackDiagRightBank; case TrackElemType::BlockBrakes: return StandUpRCTrackBlockBrakes; + case TrackElemType::DiagBrakes: + return StandUpRCTrackDiagBrakes; + case TrackElemType::DiagBlockBrakes: + return StandUpRCTrackDiagBlockBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/Steeplechase.cpp b/src/openrct2/ride/coaster/Steeplechase.cpp index fa7493a8b4..c843105db4 100644 --- a/src/openrct2/ride/coaster/Steeplechase.cpp +++ b/src/openrct2/ride/coaster/Steeplechase.cpp @@ -18,6 +18,13 @@ #include "../TrackData.h" #include "../TrackPaint.h" +static constexpr const uint32_t SteeplechaseRCDiagBrakeImages[NumOrthogonalDirections] = { + SPR_G2_STEEPLECHASE_DIAG_BRAKES, + SPR_G2_STEEPLECHASE_DIAG_BRAKES + 1, + SPR_G2_STEEPLECHASE_DIAG_BRAKES, + SPR_G2_STEEPLECHASE_DIAG_BRAKES + 1, +}; + /** rct2: 0x008A59A8 */ static void SteeplechaseTrackFlat( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -1491,6 +1498,25 @@ static void SteeplechaseTrackDiagFlat( } } +static void SteeplechaseTrackDiagBrakes( + PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, + const TrackElement& trackElement) +{ + TrackPaintUtilDiagTilesPaint( + session, 3, height, direction, trackSequence, session.TrackColours[SCHEME_TRACK], SteeplechaseRCDiagBrakeImages, + defaultDiagTileOffsets, defaultDiagBoundLengths, nullptr); + + if (trackSequence == 3) + { + MetalASupportsPaintSetup( + session, MetalSupportType::Stick, DiagSupportSegments[direction], 0, height, session.TrackColours[SCHEME_SUPPORTS]); + } + + int32_t blockedSegments = DiagBlockedSegments[trackSequence]; + PaintUtilSetSegmentSupportHeight(session, PaintUtilRotateSegments(blockedSegments, direction), 0xFFFF, 0); + PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20); +} + /** rct2: 0x008A5B38 */ static void SteeplechaseTrackDiag25DegUp( PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -2451,6 +2477,9 @@ TRACK_PAINT_FUNCTION GetTrackPaintFunctionSteeplechase(int32_t trackType) return SteeplechaseTrackDiag25DegDownToFlat; case TrackElemType::BlockBrakes: return SteeplechaseTrackBlockBrakes; + case TrackElemType::DiagBrakes: + case TrackElemType::DiagBlockBrakes: + return SteeplechaseTrackDiagBrakes; } return nullptr; } diff --git a/src/openrct2/ride/coaster/meta/CompactInvertedCoaster.h b/src/openrct2/ride/coaster/meta/CompactInvertedCoaster.h index c473c94516..2892bbe119 100644 --- a/src/openrct2/ride/coaster/meta/CompactInvertedCoaster.h +++ b/src/openrct2/ride/coaster/meta/CompactInvertedCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor CompactInvertedCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_QUARTER, TRACK_HELIX_UP_BANKED_QUARTER, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_QUARTER, TRACK_HELIX_UP_BANKED_QUARTER, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/CorkscrewRollerCoaster.h b/src/openrct2/ride/coaster/meta/CorkscrewRollerCoaster.h index 82b5afaddc..e7cbc3f423 100644 --- a/src/openrct2/ride/coaster/meta/CorkscrewRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/CorkscrewRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor CorkscrewRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES,TRACK_BOOSTER, TRACK_SLOPE_STEEP_LONG}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES,TRACK_BOOSTER, TRACK_SLOPE_STEEP_LONG, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {TRACK_TWIST}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/InvertedRollerCoaster.h b/src/openrct2/ride/coaster/meta/InvertedRollerCoaster.h index 77afe84790..87be14f563 100644 --- a/src/openrct2/ride/coaster/meta/InvertedRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/InvertedRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor InvertedRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_QUARTER, TRACK_HELIX_UP_BANKED_QUARTER, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_HALF_LOOP_LARGE, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_QUARTER, TRACK_HELIX_UP_BANKED_QUARTER, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_HALF_LOOP_LARGE, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {TRACK_BOOSTER}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/LIMLaunchedRollerCoaster.h b/src/openrct2/ride/coaster/meta/LIMLaunchedRollerCoaster.h index f15cee5bcd..1aa5e7bfa9 100644 --- a/src/openrct2/ride/coaster/meta/LIMLaunchedRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/LIMLaunchedRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor LIMLaunchedRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING, TRACK_CURVE_VERTICAL, TRACK_QUARTER_LOOP, TRACK_BARREL_ROLL, TRACK_SLOPE_CURVE_BANKED, TRACK_SLOPE_STEEP_LONG, TRACK_HALF_LOOP, TRACK_HALF_LOOP_MEDIUM, TRACK_HALF_LOOP_LARGE, TRACK_CORKSCREW_LARGE}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_TWIST, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING, TRACK_CURVE_VERTICAL, TRACK_QUARTER_LOOP, TRACK_BARREL_ROLL, TRACK_SLOPE_CURVE_BANKED, TRACK_SLOPE_STEEP_LONG, TRACK_HALF_LOOP, TRACK_HALF_LOOP_MEDIUM, TRACK_HALF_LOOP_LARGE, TRACK_CORKSCREW_LARGE, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {TRACK_SLOPE_LONG, TRACK_ZERO_G_ROLL, TRACK_ZERO_G_ROLL_LARGE}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/LayDownRollerCoaster.h b/src/openrct2/ride/coaster/meta/LayDownRollerCoaster.h index 3d20dba063..0886ee76e0 100644 --- a/src/openrct2/ride/coaster/meta/LayDownRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/LayDownRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor LayDownRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_LAY_DOWN_ROLLER_COASTER_ALT), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_INLINE_TWIST_UNINVERTED, TRACK_FLYING_HALF_LOOP_UNINVERTED_UP, TRACK_CORKSCREW_UNINVERTED, TRACK_SLOPE_STEEP_LONG}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_INLINE_TWIST_UNINVERTED, TRACK_FLYING_HALF_LOOP_UNINVERTED_UP, TRACK_CORKSCREW_UNINVERTED, TRACK_SLOPE_STEEP_LONG, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {TRACK_FLYING_HALF_LOOP_UNINVERTED_DOWN, TRACK_BOOSTER}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/LoopingRollerCoaster.h b/src/openrct2/ride/coaster/meta/LoopingRollerCoaster.h index 0109d89716..2f6b1da328 100644 --- a/src/openrct2/ride/coaster/meta/LoopingRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/LoopingRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor LoopingRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING, TRACK_BOOSTER, TRACK_SLOPE_CURVE_BANKED, TRACK_SLOPE_STEEP_LONG}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_SLOPE_CURVE_STEEP, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_SLOPE_ROLL_BANKING, TRACK_BOOSTER, TRACK_SLOPE_CURVE_BANKED, TRACK_SLOPE_STEEP_LONG, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {TRACK_SLOPE_VERTICAL, TRACK_TWIST, TRACK_CORKSCREW, TRACK_CURVE_VERTICAL, TRACK_QUARTER_LOOP, TRACK_SLOPE_LONG, TRACK_BARREL_ROLL, TRACK_HALF_LOOP, TRACK_HALF_LOOP_MEDIUM, TRACK_HALF_LOOP_LARGE,TRACK_CORKSCREW_LARGE, TRACK_ZERO_G_ROLL, TRACK_ZERO_G_ROLL_LARGE}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/MultiDimensionRollerCoaster.h b/src/openrct2/ride/coaster/meta/MultiDimensionRollerCoaster.h index d10375fd20..c91e623373 100644 --- a/src/openrct2/ride/coaster/meta/MultiDimensionRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/MultiDimensionRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor MultiDimensionRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER_ALT), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, { TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES, TRACK_INLINE_TWIST_UNINVERTED,TRACK_QUARTER_LOOP_UNINVERTED_UP, TRACK_QUARTER_LOOP_UNINVERTED_DOWN}), + SET_FIELD(EnabledTrackPieces, { TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_VERTICAL, TRACK_BLOCK_BRAKES, TRACK_INLINE_TWIST_UNINVERTED,TRACK_QUARTER_LOOP_UNINVERTED_UP, TRACK_QUARTER_LOOP_UNINVERTED_DOWN, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h b/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h index 8a784bcf40..e37c117273 100644 --- a/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h +++ b/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h @@ -19,7 +19,7 @@ constexpr RideTypeDescriptor StandUpRollerCoasterRTD = { SET_FIELD(AlternateType, RIDE_TYPE_NULL), SET_FIELD(Category, RIDE_CATEGORY_ROLLERCOASTER), - SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES}), + SET_FIELD(EnabledTrackPieces, {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_HELIX_DOWN_BANKED_HALF, TRACK_HELIX_UP_BANKED_HALF, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES}), SET_FIELD(ExtraTrackPieces, {}), SET_FIELD(CoveredTrackPieces, {}), SET_FIELD(StartTrackPiece, TrackElemType::EndStation), diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index 3ffdff017b..f2d99083ad 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -1445,7 +1445,22 @@ enum SPR_G2_ALPINE_LIFT_TRACK_GENTLE_DIAGONAL = SPR_G2_ALPINE_LIFT_TRACK_FLAT_DIAGONAL + 4, SPR_G2_ALPINE_END = SPR_G2_ALPINE_LIFT_TRACK_GENTLE_DIAGONAL + 12, - SPR_G2_END = SPR_G2_ALPINE_END, + SPR_G2_DIAG_BRAKES_START = SPR_G2_ALPINE_END, + + SPR_G2_JUNIOR_DIAG_BRAKES = SPR_G2_DIAG_BRAKES_START, + SPR_G2_CORKSCREW_DIAG_BRAKES = SPR_G2_JUNIOR_DIAG_BRAKES + 6, + SPR_G2_SLC_DIAG_BRAKES = SPR_G2_CORKSCREW_DIAG_BRAKES + 6, + SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES = SPR_G2_SLC_DIAG_BRAKES + 3, + SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES = SPR_G2_MULTIDIM_UPRIGHT_DIAG_BRAKES + 6, + SPR_G2_STEEPLECHASE_DIAG_BRAKES = SPR_G2_MULTIDIM_INVERTED_DIAG_BRAKES + 5, + SPR_G2_STANDUP_DIAG_BRAKES = SPR_G2_STEEPLECHASE_DIAG_BRAKES + 2, + SPR_G2_MINETRAIN_DIAG_BRAKES = SPR_G2_STANDUP_DIAG_BRAKES + 6, + SPR_G2_LOOPING_DIAG_BRAKES = SPR_G2_MINETRAIN_DIAG_BRAKES + 6, + SPR_G2_LIM_LAUNCHED_DIAG_BRAKES = SPR_G2_LOOPING_DIAG_BRAKES + 2, + SPR_G2_BM_INVERTED_DIAG_BRAKES = SPR_G2_LIM_LAUNCHED_DIAG_BRAKES + 6, + SPR_G2_DIAG_BRAKES_END = SPR_G2_BM_INVERTED_DIAG_BRAKES + 2, + + SPR_G2_END = SPR_G2_DIAG_BRAKES_END, SPR_CSG_BEGIN = SPR_G2_END, SPR_CSG_END = SPR_CSG_BEGIN + RCT1::Limits::Num_LL_CSG_Entries, diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 40df792e67..10fcfe4025 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -425,6 +425,8 @@ public: bool IsStation() const; bool IsBlockStart() const; + + void SetBrakeClosed2(const CoordsXY& trackLocation, bool isClosed); }; assert_struct_size(TrackElement, 16);