mirror of https://github.com/OpenTTD/OpenTTD.git
Feature: Add NotRoadTypes (NRT)
This commit is contained in:
parent
21edf67f89
commit
c02ef3e456
Binary file not shown.
|
@ -98,6 +98,32 @@
|
|||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span style="font-weight: bold;">m4:</span><br>
|
||||
<a name="RoadType"></a>
|
||||
Road roadtype. Used for all tiles with road (road, station, tunnelbridge).
|
||||
<ul>
|
||||
<li>
|
||||
Bits 5..0: Road roadtype, 0x3F for no road.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span style="font-weight: bold;">m8:</span><br>
|
||||
<a name="TramType"></a>
|
||||
Tram roadtype. Used for all tiles with road (road, station, tunnelbridge).
|
||||
<ul>
|
||||
<li>
|
||||
Bits 11..6: Tram roadtype, 0x3F for no tram.
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span style="font-weight: bold;">m8:</span><br>
|
||||
<ul>
|
||||
<li>
|
||||
<a name="RailType"></a>
|
||||
Bits 5..0: Railtype. Used for all tiles with rail (road, rail, station, tunnelbridge).
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><span style="font-weight: bold;">m7:</span><br>
|
||||
Animation frame/state. Used for houses, industries, objects and stations.
|
||||
</li>
|
||||
|
@ -108,7 +134,7 @@
|
|||
<table border=1 cellpadding=3>
|
||||
<tr bgcolor="#0099FF">
|
||||
<th align=left><font color="#FFFFFF">Class</font></th>
|
||||
<th align=left><font color="#FFFFFF">Meaning & details of encoding</font></th>
|
||||
<th align=left><font color="#FFFFFF">Meaning & details of encoding</font></th>
|
||||
</tr>
|
||||
<tr bgcolor="#CCCCCC">
|
||||
<td align=left><strong><a name="Class0"><tt> 0 </tt></a></strong></td>
|
||||
|
@ -535,21 +561,10 @@
|
|||
<td>
|
||||
<ul>
|
||||
<li>m2: Index into the array of towns (owning town for town roads; closest town otherwise, INVALID_TOWN if there is no town or we are creating a town)</li>
|
||||
<li>m7 bit 5 set = on snow or desert</li>
|
||||
<li>m7 bits 7..6: present road types
|
||||
<table>
|
||||
<tr>
|
||||
<td>bit 0 </td>
|
||||
<td>normal road</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>bit 1 </td>
|
||||
<td>tram</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of road type 1 (tram); OWNER_NONE (<tt>10</tt>) is stored as OWNER_TOWN (<tt>0F</tt>)
|
||||
<li>m4 bits 5..0: <a href="#RoadType">Roadtype</a></li>
|
||||
<li>m7 bit 5 set = on snow or desert</li>
|
||||
<li>m8 bits 11..6: <a href="#TramType">Tramtype</a></li>
|
||||
<li>m5 bits 7 clear: road or level-crossing
|
||||
<ul>
|
||||
<li>m6 bits 5..3:
|
||||
|
@ -862,6 +877,7 @@
|
|||
<li>m3 bits 7..4: persistent random data for railway stations/waypoints and airports)</li>
|
||||
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of tram tracks (road stop)</li>
|
||||
<li>m4: custom station id; 0 means standard graphics</li>
|
||||
<li>m4: <a href="#RoadType">Roadtype</a> for road stops</li>
|
||||
<li>m5: graphics index (range from 0..255 for each station type):
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -977,8 +993,8 @@
|
|||
<li>m6 bit 2: pbs reservation state for railway stations/waypoints</li>
|
||||
|
||||
<li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road (road stops)</li>
|
||||
<li>m7 bits 7..6: present road types (road stops)</li>
|
||||
<li>m7: animation frame (railway stations/waypoints, airports)</li>
|
||||
<li>m8 bits 11..6: <a href="#TramType">Tramtype</a></li>
|
||||
<li>m8 bits 5..0: <a href="#TrackType">track type</a> for railway stations/waypoints</li>
|
||||
</ul>
|
||||
</td>
|
||||
|
@ -1445,6 +1461,7 @@
|
|||
<ul>
|
||||
<li>m1 bits 4..0: <a href="#OwnershipInfo">owner</a></li>
|
||||
<li>m3 bits 7..4: <a href="#OwnershipInfo">owner</a> of tram</li>
|
||||
<li>m4: <a href="#RoadType">Roadtype</a></li>
|
||||
<li>m5 bit 4: pbs reservation state for railway</li>
|
||||
<li>m5 bits 7 clear: tunnel entrance/exit</li>
|
||||
<li>m5 bit 7 set: bridge ramp
|
||||
|
@ -1581,7 +1598,7 @@
|
|||
</li>
|
||||
<li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road</li>
|
||||
<li>m7 bit 5 set = on snow or desert</li>
|
||||
<li>m7 bits 7..6: present road types for road</li>
|
||||
<li>m8 bits 11..6: <a href="#TramType">Tramtype</a></li>
|
||||
<li>m8 bits 5..0: <a href="#TrackType">track type</a> for railway</li>
|
||||
</ul>
|
||||
</td>
|
||||
|
|
|
@ -143,11 +143,11 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits">XXXX XXXX XXXX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">OOO</span></td>
|
||||
<td class="bits">XXX<span class="free">O</span> XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OO</span>X<span class="free">O</span> XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX XX<span class="free">OO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">level crossing</td>
|
||||
|
@ -159,8 +159,8 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX <span class="free">OOO</span>X</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">OOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">road depot</td>
|
||||
|
@ -169,11 +169,11 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX <span class="free">OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XX<span class="free">OO OO</span>XX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXX<span class="free">O</span> XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OO</span>X<span class="free">O</span> XXXX</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
|
@ -237,11 +237,11 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">XXXX <span class="free">OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="option">~~~~ ~</span>XXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX X<span class="free">OOO</span></td>
|
||||
<td class="bits">XX<span class="free">O</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX XX<span class="free">OO OOOO</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="caption">dock</td>
|
||||
|
@ -357,11 +357,11 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits"><span class="free">OOO</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX <span class="free">OOOO</span></td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits">X<span class="free">OO</span>X XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">XXXX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XXXX</td>
|
||||
<td class="bits"><span class="free">OOOO</span> XXXX XXXX XXXX</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bridge ramp</td>
|
||||
|
@ -370,7 +370,7 @@ the array so you can quickly see what is used and what is not.
|
|||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits">-inherit-</td>
|
||||
<td class="bits"><span class="free">OO</span>XX XX<span class="free">OO</span></td>
|
||||
<td class="bits">-inherit-</td>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
-1 * 0 0C "OpenTTD GUI graphics"
|
||||
-1 * 3 05 15 \b 179 // OPENTTD_SPRITE_COUNT
|
||||
-1 * 3 05 15 \b 184 // OPENTTD_SPRITE_COUNT
|
||||
-1 sprites/openttdgui.png 8bpp 66 8 64 31 -31 7 normal
|
||||
-1 sprites/openttdgui.png 8bpp 146 8 64 31 -31 7 normal
|
||||
-1 sprites/openttdgui.png 8bpp 226 8 64 31 -31 7 normal
|
||||
|
@ -187,3 +187,8 @@
|
|||
-1 sprites/openttdgui_group_livery.png 8bpp 21 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_group_livery.png 8bpp 42 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_group_livery.png 8bpp 63 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_build_tram.png 8bpp 0 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_convert_road.png 8bpp 0 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_convert_road.png 8bpp 24 0 32 32 0 0 normal
|
||||
-1 sprites/openttdgui_convert_tram.png 8bpp 0 0 20 20 0 0 normal
|
||||
-1 sprites/openttdgui_convert_tram.png 8bpp 24 0 32 32 0 0 normal
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1017 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -7,7 +7,7 @@
|
|||
// See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
-1 * 0 0C "Tram track graphics by PikkaBird"
|
||||
-1 * 3 05 0B 71
|
||||
-1 * 3 05 0B 77
|
||||
-1 sprites/tramtracks.png 8bpp 18 8 20 13 0 4 normal
|
||||
-1 sprites/tramtracks.png 8bpp 50 8 20 13 0 4 normal
|
||||
-1 sprites/tramtracks.png 8bpp 82 8 64 36 -18 -8 normal
|
||||
|
@ -121,3 +121,9 @@
|
|||
-1 sprites/tramtracks.png 8bpp 722 696 64 23 -31 0 normal
|
||||
-1 sprites/tramtracks.png 8bpp 2 776 64 23 -31 0 normal
|
||||
-1 sprites/tramtracks.png 8bpp 82 776 64 39 -31 -8 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 0 0 64 31 -31 0 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 80 0 62 64 2 -49 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 158 0 64 31 -31 0 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 238 0 62 64 -62 -49 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 318 0 62 64 -62 -49 normal
|
||||
-1 sprites/tramtracks_bare_depot.png 8bpp 398 0 62 64 2 -49 normal
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
|
@ -584,6 +584,7 @@
|
|||
<ClInclude Include="..\src\newgrf_object.h" />
|
||||
<ClInclude Include="..\src\newgrf_properties.h" />
|
||||
<ClInclude Include="..\src\newgrf_railtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_sound.h" />
|
||||
<ClInclude Include="..\src\newgrf_spritegroup.h" />
|
||||
<ClInclude Include="..\src\newgrf_station.h" />
|
||||
|
@ -614,6 +615,7 @@
|
|||
<ClInclude Include="..\src\rail_gui.h" />
|
||||
<ClInclude Include="..\src\rail_type.h" />
|
||||
<ClInclude Include="..\src\rev.h" />
|
||||
<ClInclude Include="..\src\road.h" />
|
||||
<ClInclude Include="..\src\road_cmd.h" />
|
||||
<ClInclude Include="..\src\road_func.h" />
|
||||
<ClInclude Include="..\src\road_gui.h" />
|
||||
|
@ -951,6 +953,7 @@
|
|||
<ClInclude Include="..\src\table\railtypes.h" />
|
||||
<ClInclude Include="..\src\table\road_land.h" />
|
||||
<ClInclude Include="..\src\table\roadveh_movement.h" />
|
||||
<ClInclude Include="..\src\table\roadtypes.h" />
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h" />
|
||||
<ClInclude Include="..\src\table\sprites.h" />
|
||||
<ClInclude Include="..\src\table\station_land.h" />
|
||||
|
@ -1228,6 +1231,7 @@
|
|||
<ClCompile Include="..\src\newgrf_industrytiles.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_object.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_railtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_spritegroup.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_station.cpp" />
|
||||
|
|
|
@ -840,6 +840,9 @@
|
|||
<ClInclude Include="..\src\newgrf_railtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_sound.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -930,6 +933,9 @@
|
|||
<ClInclude Include="..\src\rev.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road_cmd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1941,6 +1947,9 @@
|
|||
<ClInclude Include="..\src\table\roadveh_movement.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\table\roadtypes.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2772,6 +2781,9 @@
|
|||
<ClCompile Include="..\src\newgrf_railtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -584,6 +584,7 @@
|
|||
<ClInclude Include="..\src\newgrf_object.h" />
|
||||
<ClInclude Include="..\src\newgrf_properties.h" />
|
||||
<ClInclude Include="..\src\newgrf_railtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_sound.h" />
|
||||
<ClInclude Include="..\src\newgrf_spritegroup.h" />
|
||||
<ClInclude Include="..\src\newgrf_station.h" />
|
||||
|
@ -614,6 +615,7 @@
|
|||
<ClInclude Include="..\src\rail_gui.h" />
|
||||
<ClInclude Include="..\src\rail_type.h" />
|
||||
<ClInclude Include="..\src\rev.h" />
|
||||
<ClInclude Include="..\src\road.h" />
|
||||
<ClInclude Include="..\src\road_cmd.h" />
|
||||
<ClInclude Include="..\src\road_func.h" />
|
||||
<ClInclude Include="..\src\road_gui.h" />
|
||||
|
@ -951,6 +953,7 @@
|
|||
<ClInclude Include="..\src\table\railtypes.h" />
|
||||
<ClInclude Include="..\src\table\road_land.h" />
|
||||
<ClInclude Include="..\src\table\roadveh_movement.h" />
|
||||
<ClInclude Include="..\src\table\roadtypes.h" />
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h" />
|
||||
<ClInclude Include="..\src\table\sprites.h" />
|
||||
<ClInclude Include="..\src\table\station_land.h" />
|
||||
|
@ -1228,6 +1231,7 @@
|
|||
<ClCompile Include="..\src\newgrf_industrytiles.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_object.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_railtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_spritegroup.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_station.cpp" />
|
||||
|
|
|
@ -840,6 +840,9 @@
|
|||
<ClInclude Include="..\src\newgrf_railtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_sound.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -930,6 +933,9 @@
|
|||
<ClInclude Include="..\src\rev.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road_cmd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1941,6 +1947,9 @@
|
|||
<ClInclude Include="..\src\table\roadveh_movement.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\table\roadtypes.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2772,6 +2781,9 @@
|
|||
<ClCompile Include="..\src\newgrf_railtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -584,6 +584,7 @@
|
|||
<ClInclude Include="..\src\newgrf_object.h" />
|
||||
<ClInclude Include="..\src\newgrf_properties.h" />
|
||||
<ClInclude Include="..\src\newgrf_railtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h" />
|
||||
<ClInclude Include="..\src\newgrf_sound.h" />
|
||||
<ClInclude Include="..\src\newgrf_spritegroup.h" />
|
||||
<ClInclude Include="..\src\newgrf_station.h" />
|
||||
|
@ -614,6 +615,7 @@
|
|||
<ClInclude Include="..\src\rail_gui.h" />
|
||||
<ClInclude Include="..\src\rail_type.h" />
|
||||
<ClInclude Include="..\src\rev.h" />
|
||||
<ClInclude Include="..\src\road.h" />
|
||||
<ClInclude Include="..\src\road_cmd.h" />
|
||||
<ClInclude Include="..\src\road_func.h" />
|
||||
<ClInclude Include="..\src\road_gui.h" />
|
||||
|
@ -951,6 +953,7 @@
|
|||
<ClInclude Include="..\src\table\railtypes.h" />
|
||||
<ClInclude Include="..\src\table\road_land.h" />
|
||||
<ClInclude Include="..\src\table\roadveh_movement.h" />
|
||||
<ClInclude Include="..\src\table\roadtypes.h" />
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h" />
|
||||
<ClInclude Include="..\src\table\sprites.h" />
|
||||
<ClInclude Include="..\src\table\station_land.h" />
|
||||
|
@ -1228,6 +1231,7 @@
|
|||
<ClCompile Include="..\src\newgrf_industrytiles.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_object.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_railtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_spritegroup.cpp" />
|
||||
<ClCompile Include="..\src\newgrf_station.cpp" />
|
||||
|
|
|
@ -840,6 +840,9 @@
|
|||
<ClInclude Include="..\src\newgrf_railtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_roadtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\newgrf_sound.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -930,6 +933,9 @@
|
|||
<ClInclude Include="..\src\rev.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\road_cmd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1941,6 +1947,9 @@
|
|||
<ClInclude Include="..\src\table\roadveh_movement.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\table\roadtypes.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\..\objs\settings\table\settings.h">
|
||||
<Filter>Tables</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2772,6 +2781,9 @@
|
|||
<ClCompile Include="..\src\newgrf_railtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_roadtype.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\newgrf_sound.cpp">
|
||||
<Filter>NewGRF</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -271,6 +271,7 @@ newgrf_industrytiles.h
|
|||
newgrf_object.h
|
||||
newgrf_properties.h
|
||||
newgrf_railtype.h
|
||||
newgrf_roadtype.h
|
||||
newgrf_sound.h
|
||||
newgrf_spritegroup.h
|
||||
newgrf_station.h
|
||||
|
@ -301,6 +302,7 @@ rail.h
|
|||
rail_gui.h
|
||||
rail_type.h
|
||||
rev.h
|
||||
road.h
|
||||
road_cmd.h
|
||||
road_func.h
|
||||
road_gui.h
|
||||
|
@ -666,6 +668,7 @@ table/pricebase.h
|
|||
table/railtypes.h
|
||||
table/road_land.h
|
||||
table/roadveh_movement.h
|
||||
table/roadtypes.h
|
||||
../objs/settings/table/settings.h
|
||||
table/sprites.h
|
||||
table/station_land.h
|
||||
|
@ -978,6 +981,7 @@ newgrf_industries.cpp
|
|||
newgrf_industrytiles.cpp
|
||||
newgrf_object.cpp
|
||||
newgrf_railtype.cpp
|
||||
newgrf_roadtype.cpp
|
||||
newgrf_sound.cpp
|
||||
newgrf_spritegroup.cpp
|
||||
newgrf_station.cpp
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "articulated_vehicles.h"
|
||||
#include "core/random_func.hpp"
|
||||
#include "vehiclelist.h"
|
||||
#include "road.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -74,6 +75,9 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
|
|||
}
|
||||
|
||||
case VEH_ROAD:
|
||||
/* make sure the roadtypes are compatible */
|
||||
if ((GetRoadTypeInfo(e_from->u.road.roadtype)->powered_roadtypes & GetRoadTypeInfo(e_to->u.road.roadtype)->powered_roadtypes) == ROADTYPES_NONE) return false;
|
||||
|
||||
/* make sure that we do not replace a tram with a normal road vehicles or vice versa */
|
||||
if (HasBit(e_from->info.misc_flags, EF_ROAD_TRAM) != HasBit(e_to->info.misc_flags, EF_ROAD_TRAM)) return false;
|
||||
break;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "vehicle_gui.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "autoreplace_func.h"
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "settings_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "rail_gui.h"
|
||||
#include "road_gui.h"
|
||||
#include "widgets/dropdown_func.h"
|
||||
|
||||
#include "widgets/autoreplace_widget.h"
|
||||
|
@ -86,6 +88,7 @@ class ReplaceVehicleWindow : public Window {
|
|||
bool descending_sort_order; ///< Order of sorting vehicles.
|
||||
bool show_hidden_engines; ///< Whether to show the hidden engines.
|
||||
RailType sel_railtype; ///< Type of rail tracks selected. #INVALID_RAILTYPE to show all.
|
||||
RoadType sel_roadtype; ///< Type of road selected. #INVALID_ROADTYPE to show all.
|
||||
Scrollbar *vscroll[2];
|
||||
|
||||
/**
|
||||
|
@ -127,7 +130,21 @@ class ReplaceVehicleWindow : public Window {
|
|||
FOR_ALL_ENGINES_OF_TYPE(e, type) {
|
||||
if (!draw_left && !this->show_hidden_engines && e->IsHidden(_local_company)) continue;
|
||||
EngineID eid = e->index;
|
||||
if (type == VEH_TRAIN && !this->GenerateReplaceRailList(eid, draw_left, this->replace_engines)) continue; // special rules for trains
|
||||
switch (type) {
|
||||
case VEH_TRAIN:
|
||||
if (!this->GenerateReplaceRailList(eid, draw_left, this->replace_engines)) continue; // special rules for trains
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
if (draw_left && this->sel_roadtype != INVALID_ROADTYPE) {
|
||||
/* Ensure that the roadtype is specific to the selected one */
|
||||
if (e->u.road.roadtype != this->sel_roadtype) continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (draw_left) {
|
||||
const uint num_engines = GetGroupNumEngines(_local_company, this->sel_group, eid);
|
||||
|
@ -210,6 +227,7 @@ public:
|
|||
ReplaceVehicleWindow(WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
|
||||
{
|
||||
this->sel_railtype = INVALID_RAILTYPE;
|
||||
this->sel_roadtype = INVALID_ROADTYPE;
|
||||
this->replace_engines = true; // start with locomotives (all other vehicles will not read this bool)
|
||||
this->engines[0].ForceRebuild();
|
||||
this->engines[1].ForceRebuild();
|
||||
|
@ -229,6 +247,11 @@ public:
|
|||
widget->SetLowered(this->show_hidden_engines);
|
||||
this->FinishInitNested(vehicletype);
|
||||
|
||||
if (vehicletype == VEH_TRAIN || vehicletype == VEH_ROAD) {
|
||||
widget = this->GetWidget<NWidgetCore>(WID_RV_RAIL_ROAD_TYPE_DROPDOWN);
|
||||
widget->tool_tip = STR_REPLACE_HELP_RAILTYPE + vehicletype;
|
||||
}
|
||||
|
||||
this->sort_criteria = _engine_sort_last_criteria[vehicletype];
|
||||
this->descending_sort_order = _engine_sort_last_order[vehicletype];
|
||||
this->owner = _local_company;
|
||||
|
@ -287,13 +310,28 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: {
|
||||
case WID_RV_RAIL_ROAD_TYPE_DROPDOWN: {
|
||||
Dimension d = {0, 0};
|
||||
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||
/* Skip rail type if it has no label */
|
||||
if (rti->label == 0) continue;
|
||||
d = maxdim(d, GetStringBoundingBox(rti->strings.replace_text));
|
||||
switch (this->window_number) {
|
||||
case VEH_TRAIN:
|
||||
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||
/* Skip rail type if it has no label */
|
||||
if (rti->label == 0) continue;
|
||||
d = maxdim(d, GetStringBoundingBox(rti->strings.replace_text));
|
||||
}
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
/* Skip road type if it has no label */
|
||||
if (rti->label == 0) continue;
|
||||
d = maxdim(d, GetStringBoundingBox(rti->strings.replace_text));
|
||||
}
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
d.width += padding.width;
|
||||
d.height += padding.height;
|
||||
|
@ -409,9 +447,18 @@ public:
|
|||
* or The selected vehicle has no replacement set up */
|
||||
this->SetWidgetDisabledState(WID_RV_STOP_REPLACE, this->sel_engine[0] == INVALID_ENGINE || !EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group));
|
||||
|
||||
if (this->window_number == VEH_TRAIN) {
|
||||
/* Show the selected railtype in the pulldown menu */
|
||||
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||
switch (this->window_number) {
|
||||
case VEH_TRAIN:
|
||||
/* Show the selected railtype in the pulldown menu */
|
||||
this->GetWidget<NWidgetCore>(WID_RV_RAIL_ROAD_TYPE_DROPDOWN)->widget_data = sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
/* Show the selected roadtype in the pulldown menu */
|
||||
this->GetWidget<NWidgetCore>(WID_RV_RAIL_ROAD_TYPE_DROPDOWN)->widget_data = sel_roadtype == INVALID_ROADTYPE ? STR_REPLACE_ALL_ROADTYPE : GetRoadTypeInfo(sel_roadtype)->strings.replace_text;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
this->DrawWidgets();
|
||||
|
@ -472,8 +519,16 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: // Railtype selection dropdown menu
|
||||
ShowDropDownList(this, GetRailTypeDropDownList(true, true), sel_railtype, WID_RV_TRAIN_RAILTYPE_DROPDOWN);
|
||||
case WID_RV_RAIL_ROAD_TYPE_DROPDOWN: // Rail/roadtype selection dropdown menu
|
||||
switch (this->window_number) {
|
||||
case VEH_TRAIN:
|
||||
ShowDropDownList(this, GetRailTypeDropDownList(true, true), sel_railtype, WID_RV_RAIL_ROAD_TYPE_DROPDOWN);
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
ShowDropDownList(this, GetRoadTypeDropDownList(RTTB_ROAD | RTTB_TRAM, true, true), sel_roadtype, WID_RV_RAIL_ROAD_TYPE_DROPDOWN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: // toggle renew_keep_length
|
||||
|
@ -533,10 +588,25 @@ public:
|
|||
}
|
||||
break;
|
||||
|
||||
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: {
|
||||
RailType temp = (RailType)index;
|
||||
if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
|
||||
sel_railtype = temp;
|
||||
case WID_RV_RAIL_ROAD_TYPE_DROPDOWN:
|
||||
switch (this->window_number) {
|
||||
case VEH_TRAIN: {
|
||||
RailType temp = (RailType)index;
|
||||
if (temp == sel_railtype) return; // we didn't select a new one. No need to change anything
|
||||
sel_railtype = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_ROAD: {
|
||||
RoadType temp = (RoadType)index;
|
||||
if (temp == sel_roadtype) return; // we didn't select a new one. No need to change anything
|
||||
sel_roadtype = temp;
|
||||
break;
|
||||
}
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
/* Reset scrollbar positions */
|
||||
this->vscroll[0]->SetPosition(0);
|
||||
this->vscroll[1]->SetPosition(0);
|
||||
|
@ -546,7 +616,6 @@ public:
|
|||
this->reset_sel_engine = true;
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
|
||||
this->replace_engines = index != 0;
|
||||
|
@ -603,7 +672,7 @@ static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
|||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_RAIL_ROAD_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetDataTip(STR_BLACK_STRING, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
|
||||
|
@ -648,6 +717,64 @@ static WindowDesc _replace_rail_vehicle_desc(
|
|||
_nested_replace_rail_vehicle_widgets, lengthof(_nested_replace_rail_vehicle_widgets)
|
||||
);
|
||||
|
||||
static const NWidgetPart _nested_replace_road_vehicle_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetDataTip(STR_REPLACE_VEHICLES_WHITE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY),
|
||||
NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_VEHICLES_IN_USE, STR_REPLACE_VEHICLE_VEHICLES_IN_USE_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY),
|
||||
NWidget(WWT_LABEL, COLOUR_GREY), SetDataTip(STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES, STR_REPLACE_VEHICLE_AVAILABLE_VEHICLES_TOOLTIP), SetFill(1, 1), SetMinimalSize(0, 12), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_RAIL_ROAD_TYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_SORT_DROPDOWN), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_RV_SHOW_HIDDEN_ENGINES), SetDataTip(STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN, STR_SHOW_HIDDEN_ENGINES_VEHICLE_TRAIN_TOOLTIP),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_LEFT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_LEFT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_LEFT_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_LEFT_SCROLLBAR),
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, WID_RV_RIGHT_MATRIX), SetMinimalSize(216, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_REPLACE_HELP_RIGHT_ARRAY), SetResize(1, 1), SetScrollbar(WID_RV_RIGHT_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_RV_RIGHT_SCROLLBAR),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
static WindowDesc _replace_road_vehicle_desc(
|
||||
WDP_AUTO, "replace_vehicle_road", 500, 140,
|
||||
WC_REPLACE_VEHICLE, WC_NONE,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_replace_road_vehicle_widgets, lengthof(_nested_replace_road_vehicle_widgets)
|
||||
);
|
||||
|
||||
static const NWidgetPart _nested_replace_vehicle_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
|
@ -710,5 +837,11 @@ static WindowDesc _replace_vehicle_desc(
|
|||
void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
|
||||
{
|
||||
DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
|
||||
new ReplaceVehicleWindow(vehicletype == VEH_TRAIN ? &_replace_rail_vehicle_desc : &_replace_vehicle_desc, vehicletype, id_g);
|
||||
WindowDesc *desc;
|
||||
switch (vehicletype) {
|
||||
case VEH_TRAIN: desc = &_replace_rail_vehicle_desc; break;
|
||||
case VEH_ROAD: desc = &_replace_road_vehicle_desc; break;
|
||||
default: desc = &_replace_vehicle_desc; break;
|
||||
}
|
||||
new ReplaceVehicleWindow(desc, vehicletype, id_g);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "error.h"
|
||||
#include "command_func.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "strings_func.h"
|
||||
#include "window_func.h"
|
||||
#include "sound_func.h"
|
||||
|
@ -403,11 +404,25 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
|
|||
|
||||
Money infra_cost = 0;
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_ROAD:
|
||||
infra_cost = (bridge_len + 2) * _price[PR_BUILD_ROAD] * 2;
|
||||
case TRANSPORT_ROAD: {
|
||||
/* In case we add a new road type as well, we must be aware of those costs. */
|
||||
if (IsBridgeTile(start)) infra_cost *= CountBits(GetRoadTypes(start) | (RoadTypes)road_rail_type);
|
||||
RoadType road_rt = INVALID_ROADTYPE;
|
||||
RoadType tram_rt = INVALID_ROADTYPE;
|
||||
if (IsBridgeTile(start)) {
|
||||
road_rt = GetRoadTypeRoad(start);
|
||||
tram_rt = GetRoadTypeTram(start);
|
||||
}
|
||||
if (RoadTypeIsRoad((RoadType)road_rail_type)) {
|
||||
road_rt = (RoadType)road_rail_type;
|
||||
} else {
|
||||
tram_rt = (RoadType)road_rail_type;
|
||||
}
|
||||
|
||||
if (road_rt != INVALID_ROADTYPE) infra_cost += (bridge_len + 2) * 2 * RoadBuildCost(road_rt);
|
||||
if (tram_rt != INVALID_ROADTYPE) infra_cost += (bridge_len + 2) * 2 * RoadBuildCost(tram_rt);
|
||||
|
||||
break;
|
||||
}
|
||||
case TRANSPORT_RAIL: infra_cost = (bridge_len + 2) * RailBuildCost((RailType)road_rail_type); break;
|
||||
default: break;
|
||||
}
|
||||
|
|
|
@ -132,11 +132,11 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D
|
|||
SetTileOwner(t, o);
|
||||
_m[t].m2 = 0;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m4 = INVALID_ROADTYPE;
|
||||
_m[t].m5 = 1 << 7 | tt << 2 | d;
|
||||
SB(_me[t].m6, 2, 4, bridgetype);
|
||||
_me[t].m7 = 0;
|
||||
_me[t].m8 = 0;
|
||||
_me[t].m8 = INVALID_ROADTYPE << 6;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,14 +147,15 @@ static inline void MakeBridgeRamp(TileIndex t, Owner o, BridgeType bridgetype, D
|
|||
* @param owner_tram the new owner of the tram on the bridge
|
||||
* @param bridgetype the type of bridge this bridge ramp belongs to
|
||||
* @param d the direction this ramp must be facing
|
||||
* @param rts the road types of the bridge
|
||||
* @param road_rt the road type of the bridge
|
||||
* @param tram_rt the tram type of the bridge
|
||||
*/
|
||||
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadTypes rts)
|
||||
static inline void MakeRoadBridgeRamp(TileIndex t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadType road_rt, RoadType tram_rt)
|
||||
{
|
||||
MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD);
|
||||
SetRoadOwner(t, ROADTYPE_ROAD, owner_road);
|
||||
if (owner_tram != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, owner_tram);
|
||||
SetRoadTypes(t, rts);
|
||||
SetRoadOwner(t, RTT_ROAD, owner_road);
|
||||
if (owner_tram != OWNER_TOWN) SetRoadOwner(t, RTT_TRAM, owner_tram);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1014,8 +1014,8 @@ void DisplayVehicleSortDropDown(Window *w, VehicleType vehicle_type, int selecte
|
|||
struct BuildVehicleWindow : Window {
|
||||
VehicleType vehicle_type; ///< Type of vehicles shown in the window.
|
||||
union {
|
||||
RailType railtype; ///< Rail type to show, or #RAILTYPE_END.
|
||||
RoadTypes roadtypes; ///< Road type to show, or #ROADTYPES_ALL.
|
||||
RailType railtype; ///< Rail type to show, or #INVALID_RAILTYPE.
|
||||
RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE.
|
||||
} filter; ///< Filter to apply.
|
||||
bool descending_sort_order; ///< Sort direction, @see _engine_sort_direction
|
||||
byte sort_criteria; ///< Current sort criterium.
|
||||
|
@ -1050,7 +1050,8 @@ struct BuildVehicleWindow : Window {
|
|||
BuildVehicleWindow(WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc)
|
||||
{
|
||||
this->vehicle_type = type;
|
||||
this->window_number = tile == INVALID_TILE ? (int)type : tile;
|
||||
this->listview_mode = tile == INVALID_TILE;
|
||||
this->window_number = this->listview_mode ? (int)type : tile;
|
||||
|
||||
this->sel_engine = INVALID_ENGINE;
|
||||
|
||||
|
@ -1058,19 +1059,7 @@ struct BuildVehicleWindow : Window {
|
|||
this->descending_sort_order = _engine_sort_last_order[type];
|
||||
this->show_hidden_engines = _engine_sort_show_hidden_engines[type];
|
||||
|
||||
switch (type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
this->filter.railtype = (tile == INVALID_TILE) ? RAILTYPE_END : GetRailType(tile);
|
||||
break;
|
||||
case VEH_ROAD:
|
||||
this->filter.roadtypes = (tile == INVALID_TILE) ? ROADTYPES_ALL : GetRoadTypes(tile);
|
||||
case VEH_SHIP:
|
||||
case VEH_AIRCRAFT:
|
||||
break;
|
||||
}
|
||||
|
||||
this->listview_mode = (this->window_number <= VEH_END);
|
||||
this->UpdateFilterByTile();
|
||||
|
||||
this->CreateNestedTree();
|
||||
|
||||
|
@ -1114,6 +1103,36 @@ struct BuildVehicleWindow : Window {
|
|||
}
|
||||
}
|
||||
|
||||
/** Set the filter type according to the depot type */
|
||||
void UpdateFilterByTile()
|
||||
{
|
||||
switch (this->vehicle_type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
if (this->listview_mode) {
|
||||
this->filter.railtype = INVALID_RAILTYPE;
|
||||
} else {
|
||||
this->filter.railtype = GetRailType(this->window_number);
|
||||
}
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
if (this->listview_mode) {
|
||||
this->filter.roadtype = INVALID_ROADTYPE;
|
||||
} else {
|
||||
this->filter.roadtype = GetRoadTypeRoad(this->window_number);
|
||||
if (this->filter.roadtype == INVALID_ROADTYPE) {
|
||||
this->filter.roadtype = GetRoadTypeTram(this->window_number);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
case VEH_AIRCRAFT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Populate the filter list and set the cargo filter criteria. */
|
||||
void SetCargoFilterArray()
|
||||
{
|
||||
|
@ -1223,8 +1242,6 @@ struct BuildVehicleWindow : Window {
|
|||
int num_engines = 0;
|
||||
int num_wagons = 0;
|
||||
|
||||
this->filter.railtype = (this->listview_mode) ? RAILTYPE_END : GetRailType(this->window_number);
|
||||
|
||||
this->eng_list.clear();
|
||||
|
||||
/* Make list of all available train engines and wagons.
|
||||
|
@ -1237,7 +1254,7 @@ struct BuildVehicleWindow : Window {
|
|||
EngineID eid = e->index;
|
||||
const RailVehicleInfo *rvi = &e->u.rail;
|
||||
|
||||
if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
|
||||
if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
|
||||
if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue;
|
||||
|
||||
/* Filter now! So num_engines and num_wagons is valid */
|
||||
|
@ -1280,7 +1297,8 @@ struct BuildVehicleWindow : Window {
|
|||
if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
|
||||
EngineID eid = e->index;
|
||||
if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue;
|
||||
if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
|
||||
if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue;
|
||||
|
||||
this->eng_list.push_back(eid);
|
||||
|
||||
if (eid == this->sel_engine) sel_id = eid;
|
||||
|
@ -1338,6 +1356,10 @@ struct BuildVehicleWindow : Window {
|
|||
void GenerateBuildList()
|
||||
{
|
||||
if (!this->eng_list.NeedRebuild()) return;
|
||||
|
||||
/* Update filter type in case the road/railtype of the depot got converted */
|
||||
this->UpdateFilterByTile();
|
||||
|
||||
switch (this->vehicle_type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_TRAIN:
|
||||
|
@ -1460,6 +1482,9 @@ struct BuildVehicleWindow : Window {
|
|||
if (this->vehicle_type == VEH_TRAIN && !this->listview_mode) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(this->filter.railtype);
|
||||
SetDParam(0, rti->strings.build_caption);
|
||||
} else if (this->vehicle_type == VEH_ROAD && !this->listview_mode) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(this->filter.roadtype);
|
||||
SetDParam(0, rti->strings.build_caption);
|
||||
} else {
|
||||
SetDParam(0, (this->listview_mode ? STR_VEHICLE_LIST_AVAILABLE_TRAINS : STR_BUY_VEHICLE_TRAIN_ALL_CAPTION) + this->vehicle_type);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ CommandProc CmdBuildRoad;
|
|||
|
||||
CommandProc CmdBuildRoadDepot;
|
||||
|
||||
CommandProc CmdConvertRoad;
|
||||
|
||||
CommandProc CmdBuildAirport;
|
||||
|
||||
CommandProc CmdBuildDock;
|
||||
|
@ -235,6 +237,7 @@ static const Command _command_proc_table[] = {
|
|||
DEF_CMD(CmdRemoveLongRoad, CMD_NO_TEST | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_LONG_ROAD; towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed.
|
||||
DEF_CMD(CmdBuildRoad, CMD_DEITY | CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_ROAD
|
||||
DEF_CMD(CmdBuildRoadDepot, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_ROAD_DEPOT
|
||||
DEF_CMD(CmdConvertRoad, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_CONVERT_ROAD
|
||||
|
||||
DEF_CMD(CmdBuildAirport, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_AIRPORT
|
||||
DEF_CMD(CmdBuildDock, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_DOCK
|
||||
|
|
|
@ -202,6 +202,7 @@ enum Commands {
|
|||
CMD_REMOVE_LONG_ROAD, ///< remove a complete road (not a "half" one)
|
||||
CMD_BUILD_ROAD, ///< build a "half" road
|
||||
CMD_BUILD_ROAD_DEPOT, ///< build a road depot
|
||||
CMD_CONVERT_ROAD, ///< convert a road type
|
||||
|
||||
CMD_BUILD_AIRPORT, ///< build an airport
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ struct CompanyInfrastructure {
|
|||
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) total += this->rail[rt];
|
||||
return total;
|
||||
}
|
||||
|
||||
uint32 GetRoadTotal() const;
|
||||
uint32 GetTramTotal() const;
|
||||
};
|
||||
|
||||
typedef Pool<Company, CompanyID, 1, MAX_COMPANIES> CompanyPool;
|
||||
|
|
|
@ -562,7 +562,7 @@ Company *DoStartupNewCompany(bool is_ai, CompanyID company = INVALID_COMPANY)
|
|||
c->share_owners[0] = c->share_owners[1] = c->share_owners[2] = c->share_owners[3] = INVALID_OWNER;
|
||||
|
||||
c->avail_railtypes = GetCompanyRailtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
|
||||
c->inaugurated_year = _cur_year;
|
||||
RandomCompanyManagerFaceBits(c->face, (GenderEthnicity)Random(), false, false); // create a random company manager face
|
||||
|
||||
|
@ -1165,3 +1165,29 @@ int CompanyServiceInterval(const Company *c, VehicleType type)
|
|||
case VEH_SHIP: return vds->servint_ships;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total sum of all owned road bits.
|
||||
* @return Combined total road road bits.
|
||||
*/
|
||||
uint32 CompanyInfrastructure::GetRoadTotal() const
|
||||
{
|
||||
uint32 total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsRoad(rt)) total += this->road[rt];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total sum of all owned tram bits.
|
||||
* @return Combined total of tram road bits.
|
||||
*/
|
||||
uint32 CompanyInfrastructure::GetTramTotal() const
|
||||
{
|
||||
uint32 total = 0;
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsTram(rt)) total += this->road[rt];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "core/geometry_func.hpp"
|
||||
#include "object_type.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "engine_base.h"
|
||||
#include "window_func.h"
|
||||
#include "road_func.h"
|
||||
|
@ -1782,6 +1783,10 @@ static const NWidgetPart _nested_company_infrastructure_widgets[] = {
|
|||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
|
||||
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
|
||||
|
@ -1819,7 +1824,7 @@ struct CompanyInfrastructureWindow : Window
|
|||
void UpdateRailRoadTypes()
|
||||
{
|
||||
this->railtypes = RAILTYPES_NONE;
|
||||
this->roadtypes = ROADTYPES_ROAD; // Road is always available.
|
||||
this->roadtypes = ROADTYPES_NONE;
|
||||
|
||||
/* Find the used railtypes. */
|
||||
Engine *e;
|
||||
|
@ -1832,14 +1837,16 @@ struct CompanyInfrastructureWindow : Window
|
|||
/* Get the date introduced railtypes as well. */
|
||||
this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY);
|
||||
|
||||
/* Tram is only visible when there will be a tram. */
|
||||
/* Find the used roadtypes. */
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
|
||||
if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
|
||||
|
||||
this->roadtypes |= ROADTYPES_TRAM;
|
||||
break;
|
||||
this->roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
|
||||
}
|
||||
|
||||
/* Get the date introduced roadtypes as well. */
|
||||
this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DAY);
|
||||
this->roadtypes &= ~_roadtypes_hidden_mask;
|
||||
}
|
||||
|
||||
/** Get total infrastructure maintenance cost. */
|
||||
|
@ -1854,8 +1861,11 @@ struct CompanyInfrastructureWindow : Window
|
|||
}
|
||||
total += SignalMaintenanceCost(c->infrastructure.signal);
|
||||
|
||||
if (HasBit(this->roadtypes, ROADTYPE_ROAD)) total += RoadMaintenanceCost(ROADTYPE_ROAD, c->infrastructure.road[ROADTYPE_ROAD]);
|
||||
if (HasBit(this->roadtypes, ROADTYPE_TRAM)) total += RoadMaintenanceCost(ROADTYPE_TRAM, c->infrastructure.road[ROADTYPE_TRAM]);
|
||||
uint32 road_total = c->infrastructure.GetRoadTotal();
|
||||
uint32 tram_total = c->infrastructure.GetTramTotal();
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
|
||||
}
|
||||
|
||||
total += CanalMaintenanceCost(c->infrastructure.water);
|
||||
total += StationMaintenanceCost(c->infrastructure.station);
|
||||
|
@ -1883,7 +1893,8 @@ struct CompanyInfrastructureWindow : Window
|
|||
|
||||
size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width);
|
||||
|
||||
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
|
||||
RailType rt;
|
||||
FOR_ALL_SORTED_RAILTYPES(rt) {
|
||||
if (HasBit(this->railtypes, rt)) {
|
||||
lines++;
|
||||
SetDParam(0, GetRailTypeInfo(rt)->strings.name);
|
||||
|
@ -1899,18 +1910,19 @@ struct CompanyInfrastructureWindow : Window
|
|||
break;
|
||||
}
|
||||
|
||||
case WID_CI_ROAD_DESC: {
|
||||
uint lines = 1;
|
||||
case WID_CI_ROAD_DESC:
|
||||
case WID_CI_TRAM_DESC: {
|
||||
uint lines = 0;
|
||||
|
||||
size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT).width);
|
||||
size->width = max(size->width, GetStringBoundingBox(widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT).width);
|
||||
|
||||
if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
|
||||
lines++;
|
||||
size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD).width + WD_FRAMERECT_LEFT);
|
||||
}
|
||||
if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
|
||||
lines++;
|
||||
size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY).width + WD_FRAMERECT_LEFT);
|
||||
RoadType rt;
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
|
||||
lines++;
|
||||
SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
|
||||
size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
|
||||
|
@ -1930,6 +1942,7 @@ struct CompanyInfrastructureWindow : Window
|
|||
|
||||
case WID_CI_RAIL_COUNT:
|
||||
case WID_CI_ROAD_COUNT:
|
||||
case WID_CI_TRAM_COUNT:
|
||||
case WID_CI_WATER_COUNT:
|
||||
case WID_CI_STATION_COUNT:
|
||||
case WID_CI_TOTAL: {
|
||||
|
@ -1943,9 +1956,12 @@ struct CompanyInfrastructureWindow : Window
|
|||
}
|
||||
max_val = max(max_val, c->infrastructure.signal);
|
||||
max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
|
||||
uint32 road_total = c->infrastructure.GetRoadTotal();
|
||||
uint32 tram_total = c->infrastructure.GetTramTotal();
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
|
||||
max_val = max(max_val, c->infrastructure.road[rt]);
|
||||
max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
|
||||
max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
|
||||
|
||||
}
|
||||
max_val = max(max_val, c->infrastructure.water);
|
||||
max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
|
||||
|
@ -2041,26 +2057,32 @@ struct CompanyInfrastructureWindow : Window
|
|||
}
|
||||
|
||||
case WID_CI_ROAD_DESC:
|
||||
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT);
|
||||
case WID_CI_TRAM_DESC: {
|
||||
DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
|
||||
|
||||
if (this->roadtypes != ROADTYPES_NONE) {
|
||||
if (HasBit(this->roadtypes, ROADTYPE_ROAD)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD);
|
||||
if (HasBit(this->roadtypes, ROADTYPE_TRAM)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY);
|
||||
} else {
|
||||
/* No valid roadtypes. */
|
||||
DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
|
||||
/* Draw name of each valid roadtype. */
|
||||
RoadType rt;
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
|
||||
SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
|
||||
DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_CI_ROAD_COUNT:
|
||||
if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
|
||||
this->DrawCountLine(r, y, c->infrastructure.road[ROADTYPE_ROAD], RoadMaintenanceCost(ROADTYPE_ROAD, c->infrastructure.road[ROADTYPE_ROAD]));
|
||||
}
|
||||
if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
|
||||
this->DrawCountLine(r, y, c->infrastructure.road[ROADTYPE_TRAM], RoadMaintenanceCost(ROADTYPE_TRAM, c->infrastructure.road[ROADTYPE_TRAM]));
|
||||
case WID_CI_TRAM_COUNT: {
|
||||
uint32 road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal();
|
||||
RoadType rt;
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
|
||||
this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_CI_WATER_DESC:
|
||||
DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
|
||||
|
|
|
@ -685,8 +685,10 @@ static void CompaniesGenStatistics()
|
|||
if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
|
||||
}
|
||||
cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal));
|
||||
uint32 road_total = c->infrastructure.GetRoadTotal();
|
||||
uint32 tram_total = c->infrastructure.GetTramTotal();
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
|
||||
if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
|
||||
if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
|
||||
}
|
||||
cost.AddCost(CanalMaintenanceCost(c->infrastructure.water));
|
||||
cost.AddCost(StationMaintenanceCost(c->infrastructure.station));
|
||||
|
|
|
@ -708,7 +708,7 @@ void StartupEngines()
|
|||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->avail_railtypes = GetCompanyRailtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
|
||||
}
|
||||
|
||||
/* Invalidate any open purchase lists */
|
||||
|
@ -730,7 +730,8 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company)
|
|||
assert(e->u.rail.railtype < RAILTYPE_END);
|
||||
c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
|
||||
} else if (e->type == VEH_ROAD) {
|
||||
SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
|
||||
assert(e->u.road.roadtype < ROADTYPE_END);
|
||||
c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, _date);
|
||||
}
|
||||
|
||||
e->preview_company = INVALID_COMPANY;
|
||||
|
@ -810,6 +811,7 @@ void EnginesDailyLoop()
|
|||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
|
||||
c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, _date);
|
||||
}
|
||||
|
||||
if (_cur_year >= _year_engine_aging_stops) return;
|
||||
|
@ -951,7 +953,8 @@ static void NewVehicleAvailable(Engine *e)
|
|||
FOR_ALL_COMPANIES(c) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date);
|
||||
} else if (e->type == VEH_ROAD) {
|
||||
/* maybe make another road type available */
|
||||
FOR_ALL_COMPANIES(c) SetBit(c->avail_roadtypes, HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
|
||||
assert(e->u.road.roadtype < ROADTYPE_END);
|
||||
FOR_ALL_COMPANIES(c) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, _date);
|
||||
}
|
||||
|
||||
/* Only broadcast event if AIs are able to build this vehicle type. */
|
||||
|
@ -1098,6 +1101,11 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
|
|||
const Company *c = Company::Get(company);
|
||||
if (((GetRailTypeInfo(e->u.rail.railtype))->compatible_railtypes & c->avail_railtypes) == 0) return false;
|
||||
}
|
||||
if (type == VEH_ROAD && company != OWNER_DEITY) {
|
||||
/* Check if the road type is available to this company */
|
||||
const Company *c = Company::Get(company);
|
||||
if ((GetRoadTypeInfo(e->u.road.roadtype)->powered_roadtypes & c->avail_roadtypes) == ROADTYPES_NONE) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "vehicle_func.h"
|
||||
#include "company_func.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "settings_type.h"
|
||||
#include "train.h"
|
||||
#include "roadveh.h"
|
||||
|
@ -41,7 +42,8 @@ StringID GetEngineCategoryName(EngineID engine)
|
|||
const Engine *e = Engine::Get(engine);
|
||||
switch (e->type) {
|
||||
default: NOT_REACHED();
|
||||
case VEH_ROAD: return STR_ENGINE_PREVIEW_ROAD_VEHICLE;
|
||||
case VEH_ROAD:
|
||||
return GetRoadTypeInfo(e->u.road.roadtype)->strings.new_engine;
|
||||
case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
|
||||
case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
|
||||
case VEH_TRAIN:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "economy_type.h"
|
||||
#include "rail_type.h"
|
||||
#include "road_type.h"
|
||||
#include "cargo_type.h"
|
||||
#include "date_type.h"
|
||||
#include "sound_type.h"
|
||||
|
@ -123,6 +124,7 @@ struct RoadVehicleInfo {
|
|||
uint8 air_drag; ///< Coefficient of air drag
|
||||
byte visual_effect; ///< Bitstuffed NewGRF visual effect data
|
||||
byte shorten_factor; ///< length on main map for this type is 8 - shorten_factor
|
||||
RoadType roadtype; ///< Road type
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,7 @@ void GroundVehicle<T, Type>::PowerChanged()
|
|||
uint32 total_power = 0;
|
||||
uint32 max_te = 0;
|
||||
uint32 number_of_parts = 0;
|
||||
uint16 max_track_speed = v->GetDisplayMaxSpeed();
|
||||
uint16 max_track_speed = this->vcache.cached_max_speed; // Max track speed in internal units.
|
||||
|
||||
for (const T *u = v; u != nullptr; u = u->Next()) {
|
||||
uint32 current_power = u->GetPower() + u->GetPoweredPartPower(u);
|
||||
|
|
|
@ -36,7 +36,7 @@ struct GroundVehicleCache {
|
|||
uint16 cached_axle_resistance; ///< Resistance caused by the axles of the vehicle (valid only for the first engine).
|
||||
|
||||
/* Cached acceleration values, recalculated on load and each time a vehicle is added to/removed from the consist. */
|
||||
uint16 cached_max_track_speed; ///< Maximum consist speed limited by track type (valid only for the first engine).
|
||||
uint16 cached_max_track_speed; ///< Maximum consist speed (in internal units) limited by track type (valid only for the first engine).
|
||||
uint32 cached_power; ///< Total power of the consist (valid only for the first engine).
|
||||
uint32 cached_air_drag; ///< Air drag coefficient of the vehicle (valid only for the first engine).
|
||||
|
||||
|
|
|
@ -341,6 +341,7 @@ STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_IN :{BLACK}Zoom the
|
|||
STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT :{BLACK}Zoom the view out
|
||||
STR_TOOLBAR_TOOLTIP_BUILD_RAILROAD_TRACK :{BLACK}Build railway track
|
||||
STR_TOOLBAR_TOOLTIP_BUILD_ROADS :{BLACK}Build roads
|
||||
STR_TOOLBAR_TOOLTIP_BUILD_TRAMWAYS :{BLACK}Build tramways
|
||||
STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS :{BLACK}Build ship docks
|
||||
STR_TOOLBAR_TOOLTIP_BUILD_AIRPORTS :{BLACK}Build airports
|
||||
STR_TOOLBAR_TOOLTIP_LANDSCAPING :{BLACK}Open the landscaping toolbar to raise/lower land, plant trees, etc.
|
||||
|
@ -361,6 +362,7 @@ STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION :{BLACK}Landscap
|
|||
STR_SCENEDIT_TOOLBAR_TOWN_GENERATION :{BLACK}Town generation
|
||||
STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION :{BLACK}Industry generation
|
||||
STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}Road construction
|
||||
STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}Tramway construction
|
||||
STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}Plant trees. Shift toggles building/showing cost estimate
|
||||
STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}Place sign
|
||||
STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Place object. Shift toggles building/showing cost estimate
|
||||
|
@ -2434,6 +2436,11 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL :{BLACK}Build ro
|
|||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL :{BLACK}Build tramway tunnel. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD :{BLACK}Toggle build/remove for road construction
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS :{BLACK}Toggle build/remove for tramway construction
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD :{BLACK}Convert/Upgrade the type of road. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM :{BLACK}Convert/Upgrade the type of tram. Shift toggles building/showing cost estimate
|
||||
|
||||
STR_ROAD_NAME_ROAD :Road
|
||||
STR_ROAD_NAME_TRAM :Tramway
|
||||
|
||||
# Road depot construction window
|
||||
STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION :{WHITE}Road Depot Orientation
|
||||
|
@ -2618,8 +2625,11 @@ STR_LAND_AREA_INFORMATION_NEWGRF_NAME :{BLACK}NewGRF:
|
|||
STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED :{BLACK}Cargo accepted: {LTBLUE}
|
||||
STR_LAND_AREA_INFORMATION_CARGO_EIGHTS :({COMMA}/8 {STRING})
|
||||
STR_LANG_AREA_INFORMATION_RAIL_TYPE :{BLACK}Rail type: {LTBLUE}{STRING}
|
||||
STR_LANG_AREA_INFORMATION_ROAD_TYPE :{BLACK}Road type: {LTBLUE}{STRING}
|
||||
STR_LANG_AREA_INFORMATION_TRAM_TYPE :{BLACK}Tram type: {LTBLUE}{STRING}
|
||||
STR_LANG_AREA_INFORMATION_RAIL_SPEED_LIMIT :{BLACK}Rail speed limit: {LTBLUE}{VELOCITY}
|
||||
STR_LANG_AREA_INFORMATION_ROAD_SPEED_LIMIT :{BLACK}Road speed limit: {LTBLUE}{VELOCITY}
|
||||
STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT :{BLACK}Tram speed limit: {LTBLUE}{VELOCITY}
|
||||
|
||||
# Description of land area of different tiles
|
||||
STR_LAI_CLEAR_DESCRIPTION_ROCKS :Rocks
|
||||
|
@ -3359,8 +3369,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION :{WHITE}Infrastr
|
|||
STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT :{GOLD}Rail pieces:
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS :{WHITE}Signals
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT :{GOLD}Road pieces:
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD :{WHITE}Road
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY :{WHITE}Tramway
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT :{GOLD}Tram pieces:
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT :{GOLD}Water tiles:
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}Canals
|
||||
STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}Stations:
|
||||
|
@ -3468,10 +3477,15 @@ STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION :New Electric Ra
|
|||
STR_BUY_VEHICLE_TRAIN_MONORAIL_CAPTION :New Monorail Vehicles
|
||||
STR_BUY_VEHICLE_TRAIN_MAGLEV_CAPTION :New Maglev Vehicles
|
||||
|
||||
STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :New Rail Vehicles
|
||||
STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION :New Road Vehicles
|
||||
STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION :New Tram Vehicles
|
||||
|
||||
############ range for vehicle availability starts
|
||||
STR_BUY_VEHICLE_TRAIN_ALL_CAPTION :New Rail Vehicles
|
||||
STR_BUY_VEHICLE_ROAD_VEHICLE_ALL_CAPTION :New Road Vehicles
|
||||
STR_BUY_VEHICLE_SHIP_CAPTION :New Ships
|
||||
STR_BUY_VEHICLE_AIRCRAFT_CAPTION :New Aircraft
|
||||
############ range for vehicle availability ends
|
||||
|
||||
STR_PURCHASE_INFO_COST_WEIGHT :{BLACK}Cost: {GOLD}{CURRENCY_LONG}{BLACK} Weight: {GOLD}{WEIGHT_SHORT}
|
||||
STR_PURCHASE_INFO_COST_REFIT_WEIGHT :{BLACK}Cost: {GOLD}{CURRENCY_LONG}{BLACK} (Refit Cost: {GOLD}{CURRENCY_LONG}{BLACK}) Weight: {GOLD}{WEIGHT_SHORT}
|
||||
|
@ -3632,13 +3646,18 @@ STR_DEPOT_SELL_CONFIRMATION_TEXT :{YELLOW}You are
|
|||
# Engine preview window
|
||||
STR_ENGINE_PREVIEW_CAPTION :{WHITE}Message from vehicle manufacturer
|
||||
STR_ENGINE_PREVIEW_MESSAGE :{GOLD}We have just designed a new {STRING} - would you be interested in a year's exclusive use of this vehicle, so we can see how it performs before making it universally available?
|
||||
|
||||
STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE :railway locomotive
|
||||
STR_ENGINE_PREVIEW_ROAD_VEHICLE :road vehicle
|
||||
STR_ENGINE_PREVIEW_AIRCRAFT :aircraft
|
||||
STR_ENGINE_PREVIEW_SHIP :ship
|
||||
STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE :electrified railway locomotive
|
||||
STR_ENGINE_PREVIEW_MONORAIL_LOCOMOTIVE :monorail locomotive
|
||||
STR_ENGINE_PREVIEW_MAGLEV_LOCOMOTIVE :maglev locomotive
|
||||
|
||||
STR_ENGINE_PREVIEW_ROAD_VEHICLE :road vehicle
|
||||
STR_ENGINE_PREVIEW_TRAM_VEHICLE :tramway vehicle
|
||||
|
||||
STR_ENGINE_PREVIEW_AIRCRAFT :aircraft
|
||||
STR_ENGINE_PREVIEW_SHIP :ship
|
||||
|
||||
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY_LONG} Weight: {WEIGHT_SHORT}{}Speed: {VELOCITY} Power: {POWER}{}Running Cost: {CURRENCY_LONG}/yr{}Capacity: {CARGO_LONG}
|
||||
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {CURRENCY_LONG} Weight: {WEIGHT_SHORT}{}Speed: {VELOCITY} Power: {POWER} Max. T.E.: {6:FORCE}{}Running Cost: {4:CURRENCY_LONG}/yr{}Capacity: {5:CARGO_LONG}
|
||||
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
|
||||
|
@ -3676,14 +3695,19 @@ STR_REPLACE_ENGINE_WAGON_SELECT_HELP :{BLACK}Switch b
|
|||
STR_REPLACE_ENGINES :Engines
|
||||
STR_REPLACE_WAGONS :Wagons
|
||||
STR_REPLACE_ALL_RAILTYPE :All rail vehicles
|
||||
STR_REPLACE_ALL_ROADTYPE :All road vehicles
|
||||
|
||||
STR_REPLACE_HELP_RAILTYPE :{BLACK}Choose the rail type you want to replace engines for
|
||||
STR_REPLACE_HELP_ROADTYPE :{BLACK}Choose the road type you want to replace engines for
|
||||
STR_REPLACE_HELP_REPLACE_INFO_TAB :{BLACK}Displays which engine the left selected engine is being replaced with, if any
|
||||
STR_REPLACE_RAIL_VEHICLES :Rail Vehicles
|
||||
STR_REPLACE_ELRAIL_VEHICLES :Electrified Rail Vehicles
|
||||
STR_REPLACE_MONORAIL_VEHICLES :Monorail Vehicles
|
||||
STR_REPLACE_MAGLEV_VEHICLES :Maglev Vehicles
|
||||
|
||||
STR_REPLACE_ROAD_VEHICLES :Road Vehicles
|
||||
STR_REPLACE_TRAM_VEHICLES :Tramway Vehicles
|
||||
|
||||
STR_REPLACE_REMOVE_WAGON :{BLACK}Wagon removal: {ORANGE}{STRING}
|
||||
STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Make autoreplace keep the length of a train the same by removing wagons (starting at the front), if replacing the engine would make the train longer
|
||||
|
||||
|
@ -4406,7 +4430,8 @@ STR_ERROR_MUST_REMOVE_SIGNALS_FIRST :{WHITE}Must rem
|
|||
STR_ERROR_NO_SUITABLE_RAILROAD_TRACK :{WHITE}No suitable railway track
|
||||
STR_ERROR_MUST_REMOVE_RAILROAD_TRACK :{WHITE}Must remove railway track first
|
||||
STR_ERROR_CROSSING_ON_ONEWAY_ROAD :{WHITE}Road is one way or blocked
|
||||
STR_ERROR_CROSSING_DISALLOWED :{WHITE}Level crossings not allowed for this rail type
|
||||
STR_ERROR_CROSSING_DISALLOWED_RAIL :{WHITE}Level crossings not allowed for this rail type
|
||||
STR_ERROR_CROSSING_DISALLOWED_ROAD :{WHITE}Level crossings not allowed for this road type
|
||||
STR_ERROR_CAN_T_BUILD_SIGNALS_HERE :{WHITE}Can't build signals here...
|
||||
STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK :{WHITE}Can't build railway track here...
|
||||
STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK :{WHITE}Can't remove railway track from here...
|
||||
|
@ -4426,6 +4451,12 @@ STR_ERROR_CAN_T_REMOVE_ROAD_FROM :{WHITE}Can't re
|
|||
STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM :{WHITE}Can't remove tramway from here...
|
||||
STR_ERROR_THERE_IS_NO_ROAD :{WHITE}... there is no road
|
||||
STR_ERROR_THERE_IS_NO_TRAMWAY :{WHITE}... there is no tramway
|
||||
STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Can't convert road type here...
|
||||
STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Can't convert tram type here...
|
||||
STR_ERROR_NO_SUITABLE_ROAD :{WHITE}No suitable road
|
||||
STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}No suitable tramway
|
||||
STR_ERROR_INCOMPATIBLE_ROAD :{WHITE}... incompatible road
|
||||
STR_ERROR_INCOMPATIBLE_TRAMWAY :{WHITE}... incompatible tramway
|
||||
|
||||
# Waterway construction errors
|
||||
STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Can't build canals here...
|
||||
|
|
|
@ -166,7 +166,10 @@ public:
|
|||
td.airport_tile_name = STR_NULL;
|
||||
td.railtype = STR_NULL;
|
||||
td.rail_speed = 0;
|
||||
td.roadtype = STR_NULL;
|
||||
td.road_speed = 0;
|
||||
td.tramtype = STR_NULL;
|
||||
td.tram_speed = 0;
|
||||
|
||||
td.grf = nullptr;
|
||||
|
||||
|
@ -286,6 +289,13 @@ public:
|
|||
line_nr++;
|
||||
}
|
||||
|
||||
/* Road type name */
|
||||
if (td.roadtype != STR_NULL) {
|
||||
SetDParam(0, td.roadtype);
|
||||
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_ROAD_TYPE, lastof(this->landinfo_data[line_nr]));
|
||||
line_nr++;
|
||||
}
|
||||
|
||||
/* Road speed limit */
|
||||
if (td.road_speed != 0) {
|
||||
SetDParam(0, td.road_speed);
|
||||
|
@ -293,6 +303,20 @@ public:
|
|||
line_nr++;
|
||||
}
|
||||
|
||||
/* Tram type name */
|
||||
if (td.tramtype != STR_NULL) {
|
||||
SetDParam(0, td.tramtype);
|
||||
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_TYPE, lastof(this->landinfo_data[line_nr]));
|
||||
line_nr++;
|
||||
}
|
||||
|
||||
/* Tram speed limit */
|
||||
if (td.tram_speed != 0) {
|
||||
SetDParam(0, td.tram_speed);
|
||||
GetString(this->landinfo_data[line_nr], STR_LANG_AREA_INFORMATION_TRAM_SPEED_LIMIT, lastof(this->landinfo_data[line_nr]));
|
||||
line_nr++;
|
||||
}
|
||||
|
||||
/* NewGRF name */
|
||||
if (td.grf != nullptr) {
|
||||
SetDParamStr(0, td.grf);
|
||||
|
|
372
src/newgrf.cpp
372
src/newgrf.cpp
|
@ -49,6 +49,7 @@
|
|||
#include "vehicle_func.h"
|
||||
#include "language.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "road.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/build_industry.h"
|
||||
|
@ -309,6 +310,7 @@ struct GRFTempEngineData {
|
|||
uint16 cargo_allowed;
|
||||
uint16 cargo_disallowed;
|
||||
RailTypeLabel railtypelabel;
|
||||
uint8 roadtramtype;
|
||||
const GRFFile *defaultcargo_grf; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
|
||||
Refittability refittability; ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
|
||||
bool prop27_set; ///< Did the NewGRF set property 27 (misc flags)?
|
||||
|
@ -1345,6 +1347,12 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
|
|||
RoadVehicleInfo *rvi = &e->u.road;
|
||||
|
||||
switch (prop) {
|
||||
case 0x05: // Road/tram type
|
||||
/* RoadTypeLabel is looked up later after the engine's road/tram
|
||||
* flag is set, however 0 means the value has not been set. */
|
||||
_gted[e->index].roadtramtype = buf->ReadByte() + 1;
|
||||
break;
|
||||
|
||||
case 0x08: // Speed (1 unit is 0.5 kmh)
|
||||
rvi->max_speed = buf->ReadByte();
|
||||
break;
|
||||
|
@ -2615,6 +2623,12 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By
|
|||
case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
|
||||
|
||||
case 0x16: // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->roadtype_list, "Road type");
|
||||
|
||||
case 0x17: // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->tramtype_list, "Tram type");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -2830,6 +2844,12 @@ static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, B
|
|||
case 0x12: // Rail type translation table; loading during both reservation and activation stage (in case it is selected depending on defined railtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->railtype_list, "Rail type");
|
||||
|
||||
case 0x16: // Road type translation table; loading during both reservation and activation stage (in case it is selected depending on defined roadtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->roadtype_list, "Road type");
|
||||
|
||||
case 0x17: // Tram type translation table; loading during both reservation and activation stage (in case it is selected depending on defined tramtypes)
|
||||
return LoadTranslationTable(gvid, numinfo, buf, _cur.grffile->tramtype_list, "Tram type");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4368,6 +4388,228 @@ static ChangeInfoResult RailTypeReserveInfo(uint id, int numinfo, int prop, Byte
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define properties for roadtypes
|
||||
* @param id ID of the roadtype.
|
||||
* @param numinfo Number of subsequent IDs to change the property for.
|
||||
* @param prop The property to change.
|
||||
* @param buf The property value.
|
||||
* @return ChangeInfoResult.
|
||||
*/
|
||||
static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader *buf, RoadTramType rtt)
|
||||
{
|
||||
ChangeInfoResult ret = CIR_SUCCESS;
|
||||
|
||||
extern RoadTypeInfo _roadtypes[ROADTYPE_END];
|
||||
RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
|
||||
|
||||
if (id + numinfo > ROADTYPE_END) {
|
||||
grfmsg(1, "RoadTypeChangeInfo: Road type %u is invalid, max %u, ignoring", id + numinfo, ROADTYPE_END);
|
||||
return CIR_INVALID_ID;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numinfo; i++) {
|
||||
RoadType rt = type_map[id + i];
|
||||
if (rt == INVALID_ROADTYPE) return CIR_INVALID_ID;
|
||||
|
||||
RoadTypeInfo *rti = &_roadtypes[rt];
|
||||
|
||||
switch (prop) {
|
||||
case 0x08: // Label of road type
|
||||
/* Skipped here as this is loaded during reservation stage. */
|
||||
buf->ReadDWord();
|
||||
break;
|
||||
|
||||
case 0x09: { // Toolbar caption of roadtype (sets name as well for backwards compatibility for grf ver < 8)
|
||||
uint16 str = buf->ReadWord();
|
||||
AddStringForMapping(str, &rti->strings.toolbar_caption);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0A: // Menu text of roadtype
|
||||
AddStringForMapping(buf->ReadWord(), &rti->strings.menu_text);
|
||||
break;
|
||||
|
||||
case 0x0B: // Build window caption
|
||||
AddStringForMapping(buf->ReadWord(), &rti->strings.build_caption);
|
||||
break;
|
||||
|
||||
case 0x0C: // Autoreplace text
|
||||
AddStringForMapping(buf->ReadWord(), &rti->strings.replace_text);
|
||||
break;
|
||||
|
||||
case 0x0D: // New engine text
|
||||
AddStringForMapping(buf->ReadWord(), &rti->strings.new_engine);
|
||||
break;
|
||||
|
||||
case 0x0F: // Powered roadtype list
|
||||
case 0x18: // Roadtype list required for date introduction
|
||||
case 0x19: { // Introduced roadtype list
|
||||
/* Road type compatibility bits are added to the existing bits
|
||||
* to allow multiple GRFs to modify compatibility with the
|
||||
* default road types. */
|
||||
int n = buf->ReadByte();
|
||||
for (int j = 0; j != n; j++) {
|
||||
RoadTypeLabel label = buf->ReadDWord();
|
||||
RoadType rt = GetRoadTypeByLabel(BSWAP32(label), false);
|
||||
if (rt != INVALID_ROADTYPE) {
|
||||
switch (prop) {
|
||||
case 0x0F: SetBit(rti->powered_roadtypes, rt); break;
|
||||
case 0x18: SetBit(rti->introduction_required_roadtypes, rt); break;
|
||||
case 0x19: SetBit(rti->introduces_roadtypes, rt); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x10: // Road Type flags
|
||||
rti->flags = (RoadTypeFlags)buf->ReadByte();
|
||||
break;
|
||||
|
||||
case 0x13: // Construction cost factor
|
||||
rti->cost_multiplier = buf->ReadWord();
|
||||
break;
|
||||
|
||||
case 0x14: // Speed limit
|
||||
rti->max_speed = buf->ReadWord();
|
||||
break;
|
||||
|
||||
case 0x16: // Map colour
|
||||
rti->map_colour = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case 0x17: // Introduction date
|
||||
rti->introduction_date = buf->ReadDWord();
|
||||
break;
|
||||
|
||||
case 0x1A: // Sort order
|
||||
rti->sorting_order = buf->ReadByte();
|
||||
break;
|
||||
|
||||
case 0x1B: // Name of roadtype
|
||||
AddStringForMapping(buf->ReadWord(), &rti->strings.name);
|
||||
break;
|
||||
|
||||
case 0x1C: // Maintenance cost factor
|
||||
rti->maintenance_multiplier = buf->ReadWord();
|
||||
break;
|
||||
|
||||
case 0x1D: // Alternate road type label list
|
||||
/* Skipped here as this is loaded during reservation stage. */
|
||||
for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = CIR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
|
||||
{
|
||||
return RoadTypeChangeInfo(id, numinfo, prop, buf, RTT_ROAD);
|
||||
}
|
||||
|
||||
static ChangeInfoResult TramTypeChangeInfo(uint id, int numinfo, int prop, ByteReader *buf)
|
||||
{
|
||||
return RoadTypeChangeInfo(id, numinfo, prop, buf, RTT_TRAM);
|
||||
}
|
||||
|
||||
|
||||
static ChangeInfoResult RoadTypeReserveInfo(uint id, int numinfo, int prop, ByteReader *buf, RoadTramType rtt)
|
||||
{
|
||||
ChangeInfoResult ret = CIR_SUCCESS;
|
||||
|
||||
extern RoadTypeInfo _roadtypes[ROADTYPE_END];
|
||||
RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
|
||||
|
||||
if (id + numinfo > ROADTYPE_END) {
|
||||
grfmsg(1, "RoadTypeReserveInfo: Road type %u is invalid, max %u, ignoring", id + numinfo, ROADTYPE_END);
|
||||
return CIR_INVALID_ID;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numinfo; i++) {
|
||||
switch (prop) {
|
||||
case 0x08: { // Label of road type
|
||||
RoadTypeLabel rtl = buf->ReadDWord();
|
||||
rtl = BSWAP32(rtl);
|
||||
|
||||
RoadType rt = GetRoadTypeByLabel(rtl, false);
|
||||
if (rt == INVALID_ROADTYPE) {
|
||||
/* Set up new road type */
|
||||
rt = AllocateRoadType(rtl, rtt);
|
||||
} else if (GetRoadTramType(rt) != rtt) {
|
||||
grfmsg(1, "RoadTypeReserveInfo: Road type %u is invalid type (road/tram), ignoring", id + numinfo);
|
||||
return CIR_INVALID_ID;
|
||||
}
|
||||
|
||||
type_map[id + i] = rt;
|
||||
break;
|
||||
}
|
||||
case 0x09: // Toolbar caption of roadtype
|
||||
case 0x0A: // Menu text
|
||||
case 0x0B: // Build window caption
|
||||
case 0x0C: // Autoreplace text
|
||||
case 0x0D: // New loco
|
||||
case 0x13: // Construction cost
|
||||
case 0x14: // Speed limit
|
||||
case 0x1B: // Name of roadtype
|
||||
case 0x1C: // Maintenance cost factor
|
||||
buf->ReadWord();
|
||||
break;
|
||||
|
||||
case 0x1D: // Alternate road type label list
|
||||
if (type_map[id + i] != INVALID_ROADTYPE) {
|
||||
int n = buf->ReadByte();
|
||||
for (int j = 0; j != n; j++) {
|
||||
_roadtypes[type_map[id + i]].alternate_labels.push_back(BSWAP32(buf->ReadDWord()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
grfmsg(1, "RoadTypeReserveInfo: Ignoring property 1D for road type %u because no label was set", id + i);
|
||||
/* FALL THROUGH */
|
||||
|
||||
case 0x0F: // Powered roadtype list
|
||||
case 0x18: // Roadtype list required for date introduction
|
||||
case 0x19: // Introduced roadtype list
|
||||
for (int j = buf->ReadByte(); j != 0; j--) buf->ReadDWord();
|
||||
break;
|
||||
|
||||
case 0x10: // Road Type flags
|
||||
case 0x12: // Station graphic
|
||||
case 0x15: // Acceleration model
|
||||
case 0x16: // Map colour
|
||||
case 0x1A: // Sort order
|
||||
buf->ReadByte();
|
||||
break;
|
||||
|
||||
case 0x17: // Introduction date
|
||||
buf->ReadDWord();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = CIR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ChangeInfoResult RoadTypeReserveInfo(uint id, int numinfo, int prop, ByteReader *buf)
|
||||
{
|
||||
return RoadTypeReserveInfo(id, numinfo, prop, buf, RTT_ROAD);
|
||||
}
|
||||
|
||||
static ChangeInfoResult TramTypeReserveInfo(uint id, int numinfo, int prop, ByteReader *buf)
|
||||
{
|
||||
return RoadTypeReserveInfo(id, numinfo, prop, buf, RTT_TRAM);
|
||||
}
|
||||
|
||||
static ChangeInfoResult AirportTilesChangeInfo(uint airtid, int numinfo, int prop, ByteReader *buf)
|
||||
{
|
||||
ChangeInfoResult ret = CIR_SUCCESS;
|
||||
|
@ -4520,6 +4762,8 @@ static void FeatureChangeInfo(ByteReader *buf)
|
|||
/* GSF_OBJECTS */ ObjectChangeInfo,
|
||||
/* GSF_RAILTYPES */ RailTypeChangeInfo,
|
||||
/* GSF_AIRPORTTILES */ AirportTilesChangeInfo,
|
||||
/* GSF_ROADTYPES */ RoadTypeChangeInfo,
|
||||
/* GSF_TRAMTYPES */ TramTypeChangeInfo,
|
||||
};
|
||||
|
||||
uint8 feature = buf->ReadByte();
|
||||
|
@ -4593,7 +4837,7 @@ static void ReserveChangeInfo(ByteReader *buf)
|
|||
{
|
||||
uint8 feature = buf->ReadByte();
|
||||
|
||||
if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES) return;
|
||||
if (feature != GSF_CARGOES && feature != GSF_GLOBALVAR && feature != GSF_RAILTYPES && feature != GSF_ROADTYPES && feature != GSF_TRAMTYPES) return;
|
||||
|
||||
uint8 numprops = buf->ReadByte();
|
||||
uint8 numinfo = buf->ReadByte();
|
||||
|
@ -4616,6 +4860,14 @@ static void ReserveChangeInfo(ByteReader *buf)
|
|||
case GSF_RAILTYPES:
|
||||
cir = RailTypeReserveInfo(index, numinfo, prop, buf);
|
||||
break;
|
||||
|
||||
case GSF_ROADTYPES:
|
||||
cir = RoadTypeReserveInfo(index, numinfo, prop, buf);
|
||||
break;
|
||||
|
||||
case GSF_TRAMTYPES:
|
||||
cir = TramTypeReserveInfo(index, numinfo, prop, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
if (HandleChangeInfoResult("ReserveChangeInfo", cir, feature, prop)) return;
|
||||
|
@ -4928,6 +5180,8 @@ static void NewSpriteGroup(ByteReader *buf)
|
|||
case GSF_CARGOES:
|
||||
case GSF_AIRPORTS:
|
||||
case GSF_RAILTYPES:
|
||||
case GSF_ROADTYPES:
|
||||
case GSF_TRAMTYPES:
|
||||
{
|
||||
byte num_loaded = type;
|
||||
byte num_loading = buf->ReadByte();
|
||||
|
@ -5505,6 +5759,39 @@ static void RailTypeMapSpriteGroup(ByteReader *buf, uint8 idcount)
|
|||
buf->ReadWord();
|
||||
}
|
||||
|
||||
static void RoadTypeMapSpriteGroup(ByteReader *buf, uint8 idcount, RoadTramType rtt)
|
||||
{
|
||||
RoadType *type_map = (rtt == RTT_TRAM) ? _cur.grffile->tramtype_map : _cur.grffile->roadtype_map;
|
||||
|
||||
uint8 *roadtypes = AllocaM(uint8, idcount);
|
||||
for (uint i = 0; i < idcount; i++) {
|
||||
uint8 id = buf->ReadByte();
|
||||
roadtypes[i] = id < ROADTYPE_END ? type_map[id] : INVALID_ROADTYPE;
|
||||
}
|
||||
|
||||
uint8 cidcount = buf->ReadByte();
|
||||
for (uint c = 0; c < cidcount; c++) {
|
||||
uint8 ctype = buf->ReadByte();
|
||||
uint16 groupid = buf->ReadWord();
|
||||
if (!IsValidGroupID(groupid, "RoadTypeMapSpriteGroup")) continue;
|
||||
|
||||
if (ctype >= ROTSG_END) continue;
|
||||
|
||||
extern RoadTypeInfo _roadtypes[ROADTYPE_END];
|
||||
for (uint i = 0; i < idcount; i++) {
|
||||
if (roadtypes[i] != INVALID_ROADTYPE) {
|
||||
RoadTypeInfo *rti = &_roadtypes[roadtypes[i]];
|
||||
|
||||
rti->grffile[ctype] = _cur.grffile;
|
||||
rti->group[ctype] = _cur.spritegroups[groupid];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Roadtypes do not use the default group. */
|
||||
buf->ReadWord();
|
||||
}
|
||||
|
||||
static void AirportMapSpriteGroup(ByteReader *buf, uint8 idcount)
|
||||
{
|
||||
uint8 *airports = AllocaM(uint8, idcount);
|
||||
|
@ -5655,6 +5942,14 @@ static void FeatureMapSpriteGroup(ByteReader *buf)
|
|||
RailTypeMapSpriteGroup(buf, idcount);
|
||||
break;
|
||||
|
||||
case GSF_ROADTYPES:
|
||||
RoadTypeMapSpriteGroup(buf, idcount, RTT_ROAD);
|
||||
break;
|
||||
|
||||
case GSF_TRAMTYPES:
|
||||
RoadTypeMapSpriteGroup(buf, idcount, RTT_TRAM);
|
||||
break;
|
||||
|
||||
case GSF_AIRPORTTILES:
|
||||
AirportTileMapSpriteGroup(buf, idcount);
|
||||
return;
|
||||
|
@ -5917,13 +6212,20 @@ static void GraphicsNew(ByteReader *buf)
|
|||
/* Load <num> sprites starting from <replace>, then skip <skip_num> sprites. */
|
||||
grfmsg(2, "GraphicsNew: Replacing sprites %d to %d of %s (type 0x%02X) at SpriteID 0x%04X", offset, offset + num - 1, action5_type->name, type, replace);
|
||||
|
||||
if (type == 0x0D) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_5;
|
||||
|
||||
if (type == 0x0B) {
|
||||
static const SpriteID depot_with_track_offset = SPR_TRAMWAY_DEPOT_WITH_TRACK - SPR_TRAMWAY_BASE;
|
||||
static const SpriteID depot_no_track_offset = SPR_TRAMWAY_DEPOT_NO_TRACK - SPR_TRAMWAY_BASE;
|
||||
if (offset <= depot_with_track_offset && offset + num > depot_with_track_offset) _loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_WITH_TRACK;
|
||||
if (offset <= depot_no_track_offset && offset + num > depot_no_track_offset) _loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_NO_TRACK;
|
||||
}
|
||||
|
||||
for (; num > 0; num--) {
|
||||
_cur.nfo_line++;
|
||||
LoadNextSprite(replace == 0 ? _cur.spriteid++ : replace++, _cur.file_index, _cur.nfo_line, _cur.grf_container_ver);
|
||||
}
|
||||
|
||||
if (type == 0x0D) _loaded_newgrf_features.shore = SHORE_REPLACE_ACTION_5;
|
||||
|
||||
_cur.skip_sprites = skip_num;
|
||||
}
|
||||
|
||||
|
@ -6349,6 +6651,14 @@ static void SkipIf(ByteReader *buf)
|
|||
break;
|
||||
case 0x0E: result = GetRailTypeByLabel(BSWAP32(cond_val)) != INVALID_RAILTYPE;
|
||||
break;
|
||||
case 0x0F: result = GetRoadTypeByLabel(BSWAP32(cond_val)) == INVALID_ROADTYPE;
|
||||
break;
|
||||
case 0x10: result = GetRoadTypeByLabel(BSWAP32(cond_val)) != INVALID_ROADTYPE;
|
||||
break;
|
||||
case 0x11: result = GetRoadTypeByLabel(BSWAP32(cond_val)) == INVALID_ROADTYPE;
|
||||
break;
|
||||
case 0x12: result = GetRoadTypeByLabel(BSWAP32(cond_val)) != INVALID_ROADTYPE;
|
||||
break;
|
||||
|
||||
default: grfmsg(1, "SkipIf: Unsupported condition type %02X. Ignoring", condtype); return;
|
||||
}
|
||||
|
@ -8269,6 +8579,9 @@ void ResetNewGRFData()
|
|||
/* Reset rail type information */
|
||||
ResetRailTypes();
|
||||
|
||||
/* Copy/reset original road type info data */
|
||||
ResetRoadTypes();
|
||||
|
||||
/* Allocate temporary refit/cargo class data */
|
||||
_gted = CallocT<GRFTempEngineData>(Engine::GetPoolSize());
|
||||
|
||||
|
@ -8337,6 +8650,7 @@ void ResetNewGRFData()
|
|||
_loaded_newgrf_features.has_newhouses = false;
|
||||
_loaded_newgrf_features.has_newindustries = false;
|
||||
_loaded_newgrf_features.shore = SHORE_REPLACE_NONE;
|
||||
_loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_NONE;
|
||||
|
||||
/* Clear all GRF overrides */
|
||||
_grf_id_overrides.clear();
|
||||
|
@ -8424,6 +8738,14 @@ GRFFile::GRFFile(const GRFConfig *config)
|
|||
this->railtype_map[2] = RAILTYPE_MONO;
|
||||
this->railtype_map[3] = RAILTYPE_MAGLEV;
|
||||
|
||||
/* Initialise road type map with default road types */
|
||||
memset(this->roadtype_map, INVALID_ROADTYPE, sizeof(this->roadtype_map));
|
||||
this->roadtype_map[0] = ROADTYPE_ROAD;
|
||||
|
||||
/* Initialise tram type map with default tram types */
|
||||
memset(this->tramtype_map, INVALID_ROADTYPE, sizeof(this->tramtype_map));
|
||||
this->tramtype_map[0] = ROADTYPE_TRAM;
|
||||
|
||||
/* Copy the initial parameter list
|
||||
* 'Uninitialised' parameters are zeroed as that is their default value when dynamically creating them. */
|
||||
assert_compile(lengthof(this->param) == lengthof(config->param) && lengthof(this->param) == 0x80);
|
||||
|
@ -9193,6 +9515,21 @@ static void ActivateOldShore()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replocate the old tram depot sprites to the new position, if no new ones were loaded.
|
||||
*/
|
||||
static void ActivateOldTramDepot()
|
||||
{
|
||||
if (_loaded_newgrf_features.tram == TRAMWAY_REPLACE_DEPOT_WITH_TRACK) {
|
||||
DupSprite(SPR_ROAD_DEPOT + 0, SPR_TRAMWAY_DEPOT_NO_TRACK + 0); // use road depot graphics for "no tracks"
|
||||
DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 1, SPR_TRAMWAY_DEPOT_NO_TRACK + 1);
|
||||
DupSprite(SPR_ROAD_DEPOT + 2, SPR_TRAMWAY_DEPOT_NO_TRACK + 2); // use road depot graphics for "no tracks"
|
||||
DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 3, SPR_TRAMWAY_DEPOT_NO_TRACK + 3);
|
||||
DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 4, SPR_TRAMWAY_DEPOT_NO_TRACK + 4);
|
||||
DupSprite(SPR_TRAMWAY_DEPOT_WITH_TRACK + 5, SPR_TRAMWAY_DEPOT_NO_TRACK + 5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether price base multipliers of grfs shall apply globally or only to the grf specifying them
|
||||
*/
|
||||
|
@ -9371,8 +9708,12 @@ static void AfterLoadGRFs()
|
|||
/* Load old shore sprites in new position, if they were replaced by ActionA */
|
||||
ActivateOldShore();
|
||||
|
||||
/* Load old tram depot sprites in new position, if no new ones are present */
|
||||
ActivateOldTramDepot();
|
||||
|
||||
/* Set up custom rail types */
|
||||
InitRailTypes();
|
||||
InitRoadTypes();
|
||||
|
||||
Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
|
@ -9380,6 +9721,31 @@ static void AfterLoadGRFs()
|
|||
/* Set RV maximum speed from the mph/0.8 unit value */
|
||||
e->u.road.max_speed = _gted[e->index].rv_max_speed * 4;
|
||||
}
|
||||
|
||||
RoadTramType rtt = HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? RTT_TRAM : RTT_ROAD;
|
||||
|
||||
const GRFFile *file = e->GetGRF();
|
||||
if (file == nullptr || _gted[e->index].roadtramtype == 0) {
|
||||
e->u.road.roadtype = (rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove +1 offset. */
|
||||
_gted[e->index].roadtramtype--;
|
||||
|
||||
const std::vector<RoadTypeLabel> *list = (rtt == RTT_TRAM) ? &file->tramtype_list : &file->roadtype_list;
|
||||
if (_gted[e->index].roadtramtype < list->size())
|
||||
{
|
||||
RoadTypeLabel rtl = (*list)[_gted[e->index].roadtramtype];
|
||||
RoadType rt = GetRoadTypeByLabel(rtl);
|
||||
if (rt != INVALID_ROADTYPE && GetRoadTramType(rt) == rtt) {
|
||||
e->u.road.roadtype = rt;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Road type is not available, so disable this engine */
|
||||
e->info.climates = 0;
|
||||
}
|
||||
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
|
||||
|
|
16
src/newgrf.h
16
src/newgrf.h
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "cargotype.h"
|
||||
#include "rail_type.h"
|
||||
#include "road_type.h"
|
||||
#include "fileio_type.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "core/alloc_type.hpp"
|
||||
|
@ -83,6 +84,8 @@ enum GrfSpecFeature {
|
|||
GSF_OBJECTS,
|
||||
GSF_RAILTYPES,
|
||||
GSF_AIRPORTTILES,
|
||||
GSF_ROADTYPES,
|
||||
GSF_TRAMTYPES,
|
||||
GSF_END,
|
||||
|
||||
GSF_FAKE_TOWNS = GSF_END, ///< Fake town GrfSpecFeature for NewGRF debugging (parent scope)
|
||||
|
@ -128,6 +131,12 @@ struct GRFFile : ZeroedMemoryAllocator {
|
|||
std::vector<RailTypeLabel> railtype_list; ///< Railtype translation table
|
||||
RailType railtype_map[RAILTYPE_END];
|
||||
|
||||
std::vector<RoadTypeLabel> roadtype_list; ///< Roadtype translation table (road)
|
||||
RoadType roadtype_map[ROADTYPE_END];
|
||||
|
||||
std::vector<RoadTypeLabel> tramtype_list; ///, Roadtype translation table (tram)
|
||||
RoadType tramtype_map[ROADTYPE_END];
|
||||
|
||||
CanalProperties canal_local_properties[CF_END]; ///< Canal properties as set by this NewGRF
|
||||
|
||||
struct LanguageMap *language_map; ///< Mappings related to the languages.
|
||||
|
@ -158,12 +167,19 @@ enum ShoreReplacement {
|
|||
SHORE_REPLACE_ONLY_NEW, ///< Only corner-shores were loaded by Action5 (openttd(w/d).grf only).
|
||||
};
|
||||
|
||||
enum TramReplacement {
|
||||
TRAMWAY_REPLACE_DEPOT_NONE, ///< No tram depot graphics were loaded.
|
||||
TRAMWAY_REPLACE_DEPOT_WITH_TRACK, ///< Electrified depot graphics with tram track were loaded.
|
||||
TRAMWAY_REPLACE_DEPOT_NO_TRACK, ///< Electrified depot graphics without tram track were loaded.
|
||||
};
|
||||
|
||||
struct GRFLoadedFeatures {
|
||||
bool has_2CC; ///< Set if any vehicle is loaded which uses 2cc (two company colours).
|
||||
uint64 used_liveries; ///< Bitmask of #LiveryScheme used by the defined engines.
|
||||
bool has_newhouses; ///< Set if there are any newhouses loaded.
|
||||
bool has_newindustries; ///< Set if there are any newindustries loaded.
|
||||
ShoreReplacement shore; ///< In which way shore sprites were replaced.
|
||||
TramReplacement tram; ///< In which way tram depots were replaced.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "station_base.h"
|
||||
#include "company_base.h"
|
||||
#include "newgrf_railtype.h"
|
||||
#include "newgrf_roadtype.h"
|
||||
#include "ship.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
@ -606,11 +607,21 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object,
|
|||
case 0x48: return v->GetEngine()->flags; // Vehicle Type Info
|
||||
case 0x49: return v->build_year;
|
||||
|
||||
case 0x4A: {
|
||||
if (v->type != VEH_TRAIN) return 0;
|
||||
RailType rt = GetTileRailType(v->tile);
|
||||
return (HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) | GetReverseRailTypeTranslation(rt, object->ro.grffile);
|
||||
}
|
||||
case 0x4A:
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: {
|
||||
RailType rt = GetTileRailType(v->tile);
|
||||
return (HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) | GetReverseRailTypeTranslation(rt, object->ro.grffile);
|
||||
}
|
||||
|
||||
case VEH_ROAD: {
|
||||
RoadType rt = GetRoadType(v->tile, GetRoadTramType(RoadVehicle::From(v)->roadtype));
|
||||
return 0x100 | GetReverseRoadTypeTranslation(rt, object->ro.grffile);
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
case 0x4B: // Long date of last service
|
||||
return v->date_of_last_service;
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file newgrf_roadtype.cpp NewGRF handling of road types. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "debug.h"
|
||||
#include "newgrf_roadtype.h"
|
||||
#include "date_func.h"
|
||||
#include "depot_base.h"
|
||||
#include "town.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
/* virtual */ uint32 RoadTypeScopeResolver::GetRandomBits() const
|
||||
{
|
||||
uint tmp = CountBits(this->tile + (TileX(this->tile) + TileY(this->tile)) * TILE_SIZE);
|
||||
return GB(tmp, 0, 2);
|
||||
}
|
||||
|
||||
/* virtual */ uint32 RoadTypeScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
|
||||
{
|
||||
if (this->tile == INVALID_TILE) {
|
||||
switch (variable) {
|
||||
case 0x40: return 0;
|
||||
case 0x41: return 0;
|
||||
case 0x42: return 0;
|
||||
case 0x43: return _date;
|
||||
case 0x44: return HZB_TOWN_EDGE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (variable) {
|
||||
case 0x40: return GetTerrainType(this->tile, this->context);
|
||||
case 0x41: return 0;
|
||||
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
|
||||
case 0x43:
|
||||
if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date;
|
||||
return _date;
|
||||
case 0x44: {
|
||||
const Town *t = nullptr;
|
||||
if (IsRoadDepotTile(this->tile)) {
|
||||
t = Depot::GetByTile(this->tile)->town;
|
||||
} else if (IsTileType(this->tile, MP_ROAD)) {
|
||||
t = ClosestTownFromTile(this->tile, UINT_MAX);
|
||||
}
|
||||
return t != nullptr ? GetTownRadiusGroup(t, this->tile) : HZB_TOWN_EDGE;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(grf, 1, "Unhandled road type tile variable 0x%X", variable);
|
||||
|
||||
*available = false;
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
/* virtual */ const SpriteGroup *RoadTypeResolverObject::ResolveReal(const RealSpriteGroup *group) const
|
||||
{
|
||||
if (group->num_loading > 0) return group->loading[0];
|
||||
if (group->num_loaded > 0) return group->loaded[0];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of the roadtype scope resolvers.
|
||||
* @param ro Surrounding resolver.
|
||||
* @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead.
|
||||
* @param context Are we resolving sprites for the upper halftile, or on a bridge?
|
||||
*/
|
||||
RoadTypeScopeResolver::RoadTypeScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context) : ScopeResolver(ro)
|
||||
{
|
||||
this->tile = tile;
|
||||
this->context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolver object for road types.
|
||||
* @param rti Roadtype. nullptr in NewGRF Inspect window.
|
||||
* @param tile %Tile containing the track. For track on a bridge this is the southern bridgehead.
|
||||
* @param context Are we resolving sprites for the upper halftile, or on a bridge?
|
||||
* @param rtsg Roadpart of interest
|
||||
* @param param1 Extra parameter (first parameter of the callback, except roadtypes do not have callbacks).
|
||||
* @param param2 Extra parameter (second parameter of the callback, except roadtypes do not have callbacks).
|
||||
*/
|
||||
RoadTypeResolverObject::RoadTypeResolverObject(const RoadTypeInfo *rti, TileIndex tile, TileContext context, RoadTypeSpriteGroup rtsg, uint32 param1, uint32 param2)
|
||||
: ResolverObject(rti != nullptr ? rti->grffile[rtsg] : nullptr, CBID_NO_CALLBACK, param1, param2), roadtype_scope(*this, tile, context)
|
||||
{
|
||||
this->root_spritegroup = rti != nullptr ? rti->group[rtsg] : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sprite to draw for the given tile.
|
||||
* @param rti The road type data (spec).
|
||||
* @param tile The tile to get the sprite for.
|
||||
* @param rtsg The type of sprite to draw.
|
||||
* @param content Where are we drawing the tile?
|
||||
* @param [out] num_results If not nullptr, return the number of sprites in the spriteset.
|
||||
* @return The sprite to draw.
|
||||
*/
|
||||
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context, uint *num_results)
|
||||
{
|
||||
assert(rtsg < ROTSG_END);
|
||||
|
||||
if (rti->group[rtsg] == nullptr) return 0;
|
||||
|
||||
RoadTypeResolverObject object(rti, tile, context, rtsg);
|
||||
const SpriteGroup *group = object.Resolve();
|
||||
if (group == nullptr || group->GetNumResults() == 0) return 0;
|
||||
|
||||
if (num_results) *num_results = group->GetNumResults();
|
||||
|
||||
return group->GetResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a reverse roadtype lookup to get the GRF internal ID.
|
||||
* @param roadtype The global (OpenTTD) roadtype.
|
||||
* @param grffile The GRF to do the lookup for.
|
||||
* @return the GRF internal ID.
|
||||
*/
|
||||
uint8 GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile)
|
||||
{
|
||||
/* No road type table present, return road type as-is */
|
||||
if (grffile == nullptr) return roadtype;
|
||||
|
||||
const std::vector<RoadTypeLabel> *list = RoadTypeIsRoad(roadtype) ? &grffile->roadtype_list : &grffile->tramtype_list;
|
||||
if (list->size() == 0) return roadtype;
|
||||
|
||||
/* Look for a matching road type label in the table */
|
||||
RoadTypeLabel label = GetRoadTypeInfo(roadtype)->label;
|
||||
|
||||
int index = find_index(*list, label);
|
||||
if (index >= 0) return index;
|
||||
|
||||
/* If not found, return as invalid */
|
||||
return 0xFF;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file newgrf_roadtype.h NewGRF handling of road types. */
|
||||
|
||||
#ifndef NEWGRF_ROADTYPE_H
|
||||
#define NEWGRF_ROADTYPE_H
|
||||
|
||||
#include "road.h"
|
||||
#include "newgrf_commons.h"
|
||||
#include "newgrf_spritegroup.h"
|
||||
|
||||
/** Resolver for the railtype scope. */
|
||||
struct RoadTypeScopeResolver : public ScopeResolver {
|
||||
TileIndex tile; ///< Tracktile. For track on a bridge this is the southern bridgehead.
|
||||
TileContext context; ///< Are we resolving sprites for the upper halftile, or on a bridge?
|
||||
|
||||
RoadTypeScopeResolver(ResolverObject &ro, TileIndex tile, TileContext context);
|
||||
|
||||
/* virtual */ uint32 GetRandomBits() const;
|
||||
/* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
|
||||
};
|
||||
|
||||
/** Resolver object for road types. */
|
||||
struct RoadTypeResolverObject : public ResolverObject {
|
||||
RoadTypeScopeResolver roadtype_scope; ///< Resolver for the roadtype scope.
|
||||
|
||||
RoadTypeResolverObject(const RoadTypeInfo *rti, TileIndex tile, TileContext context, RoadTypeSpriteGroup rtsg, uint32 param1 = 0, uint32 param2 = 0);
|
||||
|
||||
/* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
|
||||
{
|
||||
switch (scope) {
|
||||
case VSG_SCOPE_SELF: return &this->roadtype_scope;
|
||||
default: return ResolverObject::GetScope(scope, relative);
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
|
||||
};
|
||||
|
||||
SpriteID GetCustomRoadSprite(const RoadTypeInfo *rti, TileIndex tile, RoadTypeSpriteGroup rtsg, TileContext context = TCX_NORMAL, uint *num_results = nullptr);
|
||||
|
||||
uint8 GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile);
|
||||
|
||||
#endif /* NEWGRF_ROADTYPE_H */
|
|
@ -53,6 +53,7 @@
|
|||
#include "engine_func.h"
|
||||
#include "core/random_func.hpp"
|
||||
#include "rail_gui.h"
|
||||
#include "road_gui.h"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "hotkeys.h"
|
||||
#include "newgrf.h"
|
||||
|
@ -949,6 +950,7 @@ static void MakeNewGameDone()
|
|||
SetLocalCompany(COMPANY_FIRST);
|
||||
|
||||
InitializeRailGUI();
|
||||
InitializeRoadGUI();
|
||||
|
||||
/* We are the server, we start a new company (not dedicated),
|
||||
* so set the default password *if* needed. */
|
||||
|
|
|
@ -32,7 +32,7 @@ struct CFollowTrackT
|
|||
enum ErrorCode {
|
||||
EC_NONE,
|
||||
EC_OWNER,
|
||||
EC_RAIL_TYPE,
|
||||
EC_RAIL_ROAD_TYPE,
|
||||
EC_90DEG,
|
||||
EC_NO_WAY,
|
||||
EC_RESERVED,
|
||||
|
@ -60,6 +60,7 @@ struct CFollowTrackT
|
|||
|
||||
inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES, CPerformanceTimer *pPerf = nullptr)
|
||||
{
|
||||
assert(IsRailTT());
|
||||
m_veh = nullptr;
|
||||
Init(o, railtype_override, pPerf);
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ struct CFollowTrackT
|
|||
inline static TransportType TT() { return Ttr_type_; }
|
||||
inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
|
||||
inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
|
||||
inline bool IsTram() { return IsRoadTT() && HasBit(RoadVehicle::From(m_veh)->compatible_roadtypes, ROADTYPE_TRAM); }
|
||||
inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(m_veh)->roadtype); }
|
||||
inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
|
||||
inline static bool Allow90degTurns() { return T90deg_turns_allowed_; }
|
||||
inline static bool DoTrackMasking() { return Tmask_reserved_tracks; }
|
||||
|
@ -103,7 +104,7 @@ struct CFollowTrackT
|
|||
assert(IsTram()); // this function shouldn't be called in other cases
|
||||
|
||||
if (IsNormalRoadTile(tile)) {
|
||||
RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
|
||||
RoadBits rb = GetRoadBits(tile, RTT_TRAM);
|
||||
switch (rb) {
|
||||
case ROAD_NW: return DIAGDIR_NW;
|
||||
case ROAD_SW: return DIAGDIR_SW;
|
||||
|
@ -126,7 +127,7 @@ struct CFollowTrackT
|
|||
m_err = EC_NONE;
|
||||
assert(
|
||||
((TrackStatusToTrackdirBits(
|
||||
GetTileTrackStatus(m_old_tile, TT(), (IsRoadTT() && m_veh != nullptr) ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0)
|
||||
GetTileTrackStatus(m_old_tile, TT(), (IsRoadTT() && m_veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0)
|
||||
) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
|
||||
(IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR) // Disable the assertion for single tram bits
|
||||
);
|
||||
|
@ -151,7 +152,7 @@ struct CFollowTrackT
|
|||
if (IsRoadTT() && !IsTram() && TryReverse()) return true;
|
||||
|
||||
/* CanEnterNewTile already set a reason.
|
||||
* Do NOT overwrite it (important for example for EC_RAIL_TYPE).
|
||||
* Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
|
||||
* Only set a reason if CanEnterNewTile was not called */
|
||||
if (m_new_td_bits == TRACKDIR_BIT_NONE) m_err = EC_NO_WAY;
|
||||
|
||||
|
@ -241,7 +242,7 @@ protected:
|
|||
if (IsRailTT() && IsPlainRailTile(m_new_tile)) {
|
||||
m_new_td_bits = (TrackdirBits)(GetTrackBits(m_new_tile) * 0x101);
|
||||
} else {
|
||||
m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(m_new_tile, TT(), IsRoadTT() ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0));
|
||||
m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(m_new_tile, TT(), IsRoadTT() ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0));
|
||||
|
||||
if (IsTram() && m_new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
/* GetTileTrackStatus() returns 0 for single tram bits.
|
||||
|
@ -350,7 +351,18 @@ protected:
|
|||
RailType rail_type = GetTileRailType(m_new_tile);
|
||||
if (!HasBit(m_railtypes, rail_type)) {
|
||||
/* incompatible rail type */
|
||||
m_err = EC_RAIL_TYPE;
|
||||
m_err = EC_RAIL_ROAD_TYPE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* road transport is possible only on compatible road types */
|
||||
if (IsRoadTT()) {
|
||||
const RoadVehicle *v = RoadVehicle::From(m_veh);
|
||||
RoadType roadtype = GetRoadType(m_new_tile, GetRoadTramType(v->roadtype));
|
||||
if (!HasBit(v->compatible_roadtypes, roadtype)) {
|
||||
/* incompatible road type */
|
||||
m_err = EC_RAIL_ROAD_TYPE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ struct AyStarUserData {
|
|||
TransportType type;
|
||||
RailTypes railtypes;
|
||||
RoadTypes roadtypes;
|
||||
uint subtype;
|
||||
};
|
||||
|
||||
/** Indices into AyStarNode.userdata[] */
|
||||
|
@ -719,7 +720,7 @@ static DiagDirection GetDepotDirection(TileIndex tile, TransportType type)
|
|||
static DiagDirection GetSingleTramBit(TileIndex tile)
|
||||
{
|
||||
if (IsNormalRoadTile(tile)) {
|
||||
RoadBits rb = GetRoadBits(tile, ROADTYPE_TRAM);
|
||||
RoadBits rb = GetRoadBits(tile, RTT_TRAM);
|
||||
switch (rb) {
|
||||
case ROAD_NW: return DIAGDIR_NW;
|
||||
case ROAD_SW: return DIAGDIR_SW;
|
||||
|
@ -747,7 +748,7 @@ static DiagDirection GetTileSingleEntry(TileIndex tile, TransportType type, uint
|
|||
|
||||
if (type == TRANSPORT_ROAD) {
|
||||
if (IsStandardRoadStopTile(tile)) return GetRoadStopDir(tile);
|
||||
if (HasBit(subtype, ROADTYPE_TRAM)) return GetSingleTramBit(tile);
|
||||
if ((RoadTramType)subtype == RTT_TRAM) return GetSingleTramBit(tile);
|
||||
}
|
||||
|
||||
return INVALID_DIAGDIR;
|
||||
|
@ -785,13 +786,24 @@ static bool CanEnterTile(TileIndex tile, DiagDirection dir, AyStarUserData *user
|
|||
if (!CanEnterTileOwnerCheck(user->owner, tile, dir)) return false;
|
||||
|
||||
/* check correct rail type (mono, maglev, etc) */
|
||||
if (user->type == TRANSPORT_RAIL) {
|
||||
RailType rail_type = GetTileRailType(tile);
|
||||
if (!HasBit(user->railtypes, rail_type)) return false;
|
||||
switch (user->type) {
|
||||
case TRANSPORT_RAIL: {
|
||||
RailType rail_type = GetTileRailType(tile);
|
||||
if (!HasBit(user->railtypes, rail_type)) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSPORT_ROAD: {
|
||||
RoadType road_type = GetRoadType(tile, (RoadTramType)user->subtype);
|
||||
if (!HasBit(user->roadtypes, road_type)) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* Depots, standard roadstops and single tram bits can only be entered from one direction */
|
||||
DiagDirection single_entry = GetTileSingleEntry(tile, user->type, user->roadtypes);
|
||||
DiagDirection single_entry = GetTileSingleEntry(tile, user->type, user->subtype);
|
||||
if (single_entry != INVALID_DIAGDIR && single_entry != ReverseDiagDir(dir)) return false;
|
||||
|
||||
return true;
|
||||
|
@ -813,7 +825,7 @@ static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, TileIndex src_t
|
|||
{
|
||||
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));
|
||||
|
||||
if (trackdirbits == TRACKDIR_BIT_NONE && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) {
|
||||
if (trackdirbits == TRACKDIR_BIT_NONE && type == TRANSPORT_ROAD && (RoadTramType)subtype == RTT_TRAM) {
|
||||
/* GetTileTrackStatus() returns 0 for single tram bits.
|
||||
* As we cannot change it there (easily) without breaking something, change it here */
|
||||
switch (GetSingleTramBit(dst_tile)) {
|
||||
|
@ -863,7 +875,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
|||
|
||||
/* Information about the vehicle: TransportType (road/rail/water) and SubType (compatible rail/road types) */
|
||||
TransportType type = user->type;
|
||||
uint subtype = user->roadtypes;
|
||||
uint subtype = user->subtype;
|
||||
|
||||
/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */
|
||||
aystar->num_neighbours = 0;
|
||||
|
@ -894,11 +906,11 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
|||
/* We leave src_tile in src_exitdir and reach dst_tile */
|
||||
dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(src_exitdir));
|
||||
|
||||
if (dst_tile != INVALID_TILE && !CanEnterTile(dst_tile, src_exitdir, user)) dst_tile = INVALID_TILE;
|
||||
if (dst_tile != INVALID_TILE && IsNormalRoadTile(dst_tile) && !CanEnterTile(dst_tile, src_exitdir, user)) dst_tile = INVALID_TILE;
|
||||
|
||||
if (dst_tile == INVALID_TILE) {
|
||||
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
|
||||
if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
|
||||
if (type != TRANSPORT_ROAD || (RoadTramType)subtype == RTT_TRAM) return;
|
||||
|
||||
dst_tile = src_tile;
|
||||
src_trackdir = ReverseTrackdir(src_trackdir);
|
||||
|
@ -908,7 +920,7 @@ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current)
|
|||
|
||||
if (trackdirbits == TRACKDIR_BIT_NONE) {
|
||||
/* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */
|
||||
if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return;
|
||||
if (type != TRANSPORT_ROAD || (RoadTramType)subtype == RTT_TRAM) return;
|
||||
|
||||
dst_tile = src_tile;
|
||||
src_trackdir = ReverseTrackdir(src_trackdir);
|
||||
|
@ -1120,7 +1132,7 @@ FindDepotData NPFRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_penal
|
|||
{
|
||||
Trackdir trackdir = v->GetVehicleTrackdir();
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes, GetRoadTramType(v->roadtype) };
|
||||
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, INVALID_TILE, INVALID_TRACKDIR, false, nullptr, &user, 0, max_penalty);
|
||||
|
||||
if (ftd.best_bird_dist != 0) return FindDepotData();
|
||||
|
@ -1140,7 +1152,7 @@ Trackdir NPFRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDir
|
|||
NPFFillWithOrderData(&fstd, v);
|
||||
Trackdir trackdir = DiagDirToDiagTrackdir(enterdir);
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_ROAD, RAILTYPES_NONE, v->compatible_roadtypes, GetRoadTramType(v->roadtype) };
|
||||
NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, &user);
|
||||
|
||||
assert(ftd.best_trackdir != INVALID_TRACKDIR);
|
||||
|
@ -1163,7 +1175,7 @@ Track NPFShipChooseTrack(const Ship *v, bool &path_found)
|
|||
|
||||
NPFFillWithOrderData(&fstd, v);
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
|
||||
NPFFoundTargetData ftd = NPFRouteToStationOrTile(v->tile, trackdir, true, &fstd, &user);
|
||||
|
||||
assert(ftd.best_trackdir != INVALID_TRACKDIR);
|
||||
|
@ -1188,7 +1200,7 @@ bool NPFShipCheckReverse(const Ship *v)
|
|||
assert(trackdir != INVALID_TRACKDIR);
|
||||
assert(trackdir_rev != INVALID_TRACKDIR);
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_WATER, RAILTYPES_NONE, ROADTYPES_NONE, 0 };
|
||||
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, &user);
|
||||
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
|
||||
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
|
||||
|
@ -1206,7 +1218,7 @@ FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty)
|
|||
fstd.reserve_path = false;
|
||||
|
||||
assert(trackdir != INVALID_TRACKDIR);
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
|
||||
NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, &user, NPF_INFINITE_PENALTY, max_penalty);
|
||||
if (ftd.best_bird_dist != 0) return FindDepotData();
|
||||
|
||||
|
@ -1235,7 +1247,7 @@ bool NPFTrainFindNearestSafeTile(const Train *v, TileIndex tile, Trackdir trackd
|
|||
|
||||
/* perform a breadth first search. Target is nullptr,
|
||||
* since we are just looking for any safe tile...*/
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, railtypes, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, railtypes, ROADTYPES_NONE, 0 };
|
||||
return NPFRouteInternal(&start1, true, nullptr, false, &fstd, NPFFindSafeTile, NPFCalcZero, &user, 0, true).res_okay;
|
||||
}
|
||||
|
||||
|
@ -1252,7 +1264,7 @@ bool NPFTrainCheckReverse(const Train *v)
|
|||
assert(trackdir != INVALID_TRACKDIR);
|
||||
assert(trackdir_rev != INVALID_TRACKDIR);
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
|
||||
ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, &user);
|
||||
/* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */
|
||||
return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE);
|
||||
|
@ -1266,7 +1278,7 @@ Track NPFTrainChooseTrack(const Train *v, bool &path_found, bool reserve_track,
|
|||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
assert(IsValidTrackdir(origin.trackdir));
|
||||
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE };
|
||||
AyStarUserData user = { v->owner, TRANSPORT_RAIL, v->compatible_railtypes, ROADTYPES_NONE, 0 };
|
||||
NPFFoundTargetData ftd = NPFRouteToStationOrTile(origin.tile, origin.trackdir, true, &fstd, &user);
|
||||
|
||||
if (target != nullptr) {
|
||||
|
|
|
@ -496,7 +496,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
if (!tf_local.Follow(cur.tile, cur.td)) {
|
||||
assert(tf_local.m_err != TrackFollower::EC_NONE);
|
||||
/* Can't move to the next tile (EOL?). */
|
||||
if (tf_local.m_err == TrackFollower::EC_RAIL_TYPE) {
|
||||
if (tf_local.m_err == TrackFollower::EC_RAIL_ROAD_TYPE) {
|
||||
end_segment_reason |= ESRB_RAIL_TYPE;
|
||||
} else {
|
||||
end_segment_reason |= ESRB_DEAD_END;
|
||||
|
|
|
@ -249,7 +249,7 @@ public:
|
|||
} else {
|
||||
m_dest_station = INVALID_STATION;
|
||||
m_destTile = v->dest_tile;
|
||||
m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, v->compatible_roadtypes));
|
||||
m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +367,7 @@ public:
|
|||
/* our source tile will be the next vehicle tile (should be the given one) */
|
||||
TileIndex src_tile = tile;
|
||||
/* get available trackdirs on the start tile */
|
||||
TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes));
|
||||
TrackdirBits src_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
|
||||
/* select reachable trackdirs only */
|
||||
src_trackdirs &= DiagdirReachesTrackdirs(enterdir);
|
||||
|
||||
|
@ -449,7 +449,7 @@ public:
|
|||
/* set origin (tile, trackdir) */
|
||||
TileIndex src_tile = v->tile;
|
||||
Trackdir src_td = v->GetVehicleTrackdir();
|
||||
if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->compatible_roadtypes)), src_td)) {
|
||||
if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, this->IsTram() ? RTT_TRAM : RTT_ROAD)), src_td)) {
|
||||
/* sometimes the roadveh is not on the road (it resides on non-existing track)
|
||||
* how should we handle that situation? */
|
||||
return false;
|
||||
|
@ -529,7 +529,7 @@ FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_dist
|
|||
{
|
||||
TileIndex tile = v->tile;
|
||||
Trackdir trackdir = v->GetVehicleTrackdir();
|
||||
if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes)), trackdir)) {
|
||||
if (!HasTrackdir(TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype))), trackdir)) {
|
||||
return FindDepotData();
|
||||
}
|
||||
|
||||
|
|
|
@ -512,41 +512,48 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
|||
|
||||
if (GetDisallowedRoadDirections(tile) != DRD_NONE) return_cmd_error(STR_ERROR_CROSSING_ON_ONEWAY_ROAD);
|
||||
|
||||
if (RailNoLevelCrossings(railtype)) return_cmd_error(STR_ERROR_CROSSING_DISALLOWED);
|
||||
if (RailNoLevelCrossings(railtype)) return_cmd_error(STR_ERROR_CROSSING_DISALLOWED_RAIL);
|
||||
|
||||
RoadTypes roadtypes = GetRoadTypes(tile);
|
||||
RoadBits road = GetRoadBits(tile, ROADTYPE_ROAD);
|
||||
RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
|
||||
RoadType roadtype_road = GetRoadTypeRoad(tile);
|
||||
RoadType roadtype_tram = GetRoadTypeTram(tile);
|
||||
|
||||
if (roadtype_road != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_road)) return_cmd_error(STR_ERROR_CROSSING_DISALLOWED_ROAD);
|
||||
if (roadtype_tram != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_tram)) return_cmd_error(STR_ERROR_CROSSING_DISALLOWED_ROAD);
|
||||
|
||||
RoadBits road = GetRoadBits(tile, RTT_ROAD);
|
||||
RoadBits tram = GetRoadBits(tile, RTT_TRAM);
|
||||
if ((track == TRACK_X && ((road | tram) & ROAD_X) == 0) ||
|
||||
(track == TRACK_Y && ((road | tram) & ROAD_Y) == 0)) {
|
||||
Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
|
||||
Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
|
||||
Owner road_owner = GetRoadOwner(tile, RTT_ROAD);
|
||||
Owner tram_owner = GetRoadOwner(tile, RTT_TRAM);
|
||||
/* Disallow breaking end-of-line of someone else
|
||||
* so trams can still reverse on this tile. */
|
||||
if (Company::IsValidID(tram_owner) && HasExactlyOneBit(tram)) {
|
||||
CommandCost ret = CheckOwnership(tram_owner);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
/* Crossings must always have a road... */
|
||||
uint num_new_road_pieces = 2 - CountBits(road);
|
||||
if (road == ROAD_NONE) road_owner = _current_company;
|
||||
roadtypes |= ROADTYPES_ROAD;
|
||||
/* ...but tram is not required. */
|
||||
uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0;
|
||||
|
||||
cost.AddCost((num_new_road_pieces + num_new_tram_pieces) * _price[PR_BUILD_ROAD]);
|
||||
uint num_new_road_pieces = (road != ROAD_NONE) ? 2 - CountBits(road) : 0;
|
||||
if (num_new_road_pieces > 0) {
|
||||
cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road));
|
||||
}
|
||||
|
||||
uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0;
|
||||
if (num_new_tram_pieces > 0) {
|
||||
cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram));
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile));
|
||||
MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile));
|
||||
UpdateLevelCrossing(tile, false);
|
||||
Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR;
|
||||
DirtyCompanyInfrastructureWindows(_current_company);
|
||||
if (num_new_road_pieces > 0 && Company::IsValidID(road_owner)) {
|
||||
Company::Get(road_owner)->infrastructure.road[ROADTYPE_ROAD] += num_new_road_pieces;
|
||||
Company::Get(road_owner)->infrastructure.road[roadtype_road] += num_new_road_pieces;
|
||||
DirtyCompanyInfrastructureWindows(road_owner);
|
||||
}
|
||||
if (num_new_tram_pieces > 0 && Company::IsValidID(tram_owner)) {
|
||||
Company::Get(tram_owner)->infrastructure.road[ROADTYPE_TRAM] += num_new_tram_pieces;
|
||||
Company::Get(tram_owner)->infrastructure.road[roadtype_tram] += num_new_tram_pieces;
|
||||
DirtyCompanyInfrastructureWindows(tram_owner);
|
||||
}
|
||||
}
|
||||
|
@ -644,10 +651,11 @@ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
|||
v = GetTrainForReservation(tile, track);
|
||||
if (v != nullptr) FreeTrainTrackReservation(v);
|
||||
}
|
||||
|
||||
owner = GetTileOwner(tile);
|
||||
Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR;
|
||||
DirtyCompanyInfrastructureWindows(owner);
|
||||
MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM));
|
||||
MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypeRoad(tile), GetRoadTypeTram(tile), GetTownIndex(tile), GetRoadOwner(tile, RTT_ROAD), GetRoadOwner(tile, RTT_TRAM));
|
||||
DeleteNewGRFInspectWindow(GSF_RAILTYPES, tile);
|
||||
}
|
||||
break;
|
||||
|
@ -1579,7 +1587,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||
case MP_ROAD:
|
||||
if (!IsLevelCrossing(tile)) continue;
|
||||
if (RailNoLevelCrossings(totype)) {
|
||||
error.MakeError(STR_ERROR_CROSSING_DISALLOWED);
|
||||
error.MakeError(STR_ERROR_CROSSING_DISALLOWED_RAIL);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -2042,5 +2042,11 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
|
|||
item->SetParam(1, rti->max_speed);
|
||||
list.emplace_back(item);
|
||||
}
|
||||
|
||||
if (list.size() == 0) {
|
||||
/* Empty dropdowns are not allowed */
|
||||
list.emplace_back(new DropDownListStringItem(STR_NONE, INVALID_RAILTYPE, true));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
226
src/road.cpp
226
src/road.cpp
|
@ -19,6 +19,9 @@
|
|||
#include "engine_base.h"
|
||||
#include "date_func.h"
|
||||
#include "landscape.h"
|
||||
#include "road.h"
|
||||
#include "road_func.h"
|
||||
#include "roadveh.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -72,7 +75,7 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
|
|||
/* Always connective */
|
||||
connective = true;
|
||||
} else {
|
||||
const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM);
|
||||
const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, RTT_ROAD) | GetAnyRoadBits(neighbor_tile, RTT_TRAM);
|
||||
|
||||
/* Accept only connective tiles */
|
||||
connective = (neighbor_rb & mirrored_rb) != ROAD_NONE;
|
||||
|
@ -102,53 +105,236 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
|
|||
}
|
||||
|
||||
/**
|
||||
* Finds out, whether given company has all given RoadTypes available
|
||||
* Finds out, whether given company has a given RoadType available for construction.
|
||||
* @param company ID of company
|
||||
* @param rts RoadTypes to test
|
||||
* @return true if company has all requested RoadTypes available
|
||||
* @param roadtypet RoadType to test
|
||||
* @return true if company has the requested RoadType available
|
||||
*/
|
||||
bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts)
|
||||
bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype)
|
||||
{
|
||||
RoadTypes avail_roadtypes;
|
||||
|
||||
if (company == OWNER_DEITY || company == OWNER_TOWN || _game_mode == GM_EDITOR || _generating_world) {
|
||||
avail_roadtypes = ROADTYPES_ROAD;
|
||||
return true; // TODO: should there be a proper check?
|
||||
} else {
|
||||
Company *c = Company::GetIfValid(company);
|
||||
const Company *c = Company::GetIfValid(company);
|
||||
if (c == nullptr) return false;
|
||||
avail_roadtypes = (RoadTypes)c->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody
|
||||
return HasBit(c->avail_roadtypes & ~_roadtypes_hidden_mask, roadtype);
|
||||
}
|
||||
return (rts & ~avail_roadtypes) == 0;
|
||||
}
|
||||
|
||||
static RoadTypes GetMaskForRoadTramType(RoadTramType rtt)
|
||||
{
|
||||
return rtt == RTT_TRAM ? _roadtypes_type : ~_roadtypes_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if any buildable RoadType is available for a company.
|
||||
* @param company the company in question
|
||||
* @return true if company has any RoadTypes available
|
||||
*/
|
||||
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
|
||||
{
|
||||
return (Company::Get(company)->avail_roadtypes & ~_roadtypes_hidden_mask & GetMaskForRoadTramType(rtt)) != ROADTYPES_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate functions for rail building.
|
||||
* @param rt road type to check.
|
||||
* @param roadtype road type to check.
|
||||
* @return true if the current company may build the road.
|
||||
*/
|
||||
bool ValParamRoadType(const RoadType rt)
|
||||
bool ValParamRoadType(RoadType roadtype)
|
||||
{
|
||||
return HasRoadTypesAvail(_current_company, RoadTypeToRoadTypes(rt));
|
||||
return roadtype != INVALID_ROADTYPE && HasRoadTypeAvail(_current_company, roadtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the road types that are to be introduced at the given date.
|
||||
* @param rt Roadtype
|
||||
* @param current The currently available roadtypes.
|
||||
* @param date The date for the introduction comparisons.
|
||||
* @return The road types that should be available when date
|
||||
* introduced road types are taken into account as well.
|
||||
*/
|
||||
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date)
|
||||
{
|
||||
RoadTypes rts = current;
|
||||
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
/* Unused road type. */
|
||||
if (rti->label == 0) continue;
|
||||
|
||||
/* Not date introduced. */
|
||||
if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
|
||||
|
||||
/* Not yet introduced at this date. */
|
||||
if (rti->introduction_date > date) continue;
|
||||
|
||||
/* Have we introduced all required roadtypes? */
|
||||
RoadTypes required = rti->introduction_required_roadtypes;
|
||||
if ((rts & required) != required) continue;
|
||||
|
||||
rts |= rti->introduces_roadtypes;
|
||||
}
|
||||
|
||||
/* When we added roadtypes we need to run this method again; the added
|
||||
* roadtypes might enable more rail types to become introduced. */
|
||||
return rts == current ? rts : AddDateIntroducedRoadTypes(rts, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the road types the given company can build.
|
||||
* @param company the company to get the roadtypes for.
|
||||
* @param company the company to get the road types for.
|
||||
* @param introduces If true, include road types introduced by other road types
|
||||
* @return the road types.
|
||||
*/
|
||||
RoadTypes GetCompanyRoadtypes(CompanyID company)
|
||||
RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
|
||||
{
|
||||
RoadTypes rt = ROADTYPES_NONE;
|
||||
RoadTypes rts = ROADTYPES_NONE;
|
||||
|
||||
Engine *e;
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
const EngineInfo *ei = &e->info;
|
||||
|
||||
if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
|
||||
(HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
|
||||
SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
|
||||
const RoadVehicleInfo *rvi = &e->u.road;
|
||||
assert(rvi->roadtype < ROADTYPE_END);
|
||||
if (introduces) {
|
||||
rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
|
||||
} else {
|
||||
SetBit(rts, rvi->roadtype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rt;
|
||||
if (introduces) return AddDateIntroducedRoadTypes(rts, _date);
|
||||
return rts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of road types, regardless of company availability.
|
||||
* @param introduces If true, include road types introduced by other road types
|
||||
* @return the road types.
|
||||
*/
|
||||
RoadTypes GetRoadTypes(bool introduces)
|
||||
{
|
||||
RoadTypes rts = ROADTYPES_NONE;
|
||||
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
const EngineInfo *ei = &e->info;
|
||||
if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) continue;
|
||||
|
||||
const RoadVehicleInfo *rvi = &e->u.road;
|
||||
assert(rvi->roadtype < ROADTYPE_END);
|
||||
if (introduces) {
|
||||
rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
|
||||
} else {
|
||||
SetBit(rts, rvi->roadtype);
|
||||
}
|
||||
}
|
||||
|
||||
if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DAY);
|
||||
return rts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the road type for a given label.
|
||||
* @param label the roadtype label.
|
||||
* @param allow_alternate_labels Search in the alternate label lists as well.
|
||||
* @return the roadtype.
|
||||
*/
|
||||
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
|
||||
{
|
||||
/* Loop through each road type until the label is found */
|
||||
for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(r);
|
||||
if (rti->label == label) return r;
|
||||
}
|
||||
|
||||
if (allow_alternate_labels) {
|
||||
/* Test if any road type defines the label as an alternate. */
|
||||
for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(r);
|
||||
if (std::find(rti->alternate_labels.begin(), rti->alternate_labels.end(), label) != rti->alternate_labels.end()) return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* No matching label was found, so it is invalid */
|
||||
return INVALID_ROADTYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the available RoadSubTypes for the provided RoadType
|
||||
* If the given company is valid then will be returned a list of the available sub types at the current date, while passing
|
||||
* a deity company will make all the sub types available
|
||||
* @param rt the RoadType to filter
|
||||
* @param c the company ID to check the roadtype against
|
||||
* @param any_date whether to return only currently introduced roadtypes or also future ones
|
||||
* @returns the existing RoadSubTypes
|
||||
*/
|
||||
RoadTypes ExistingRoadTypes(CompanyID c)
|
||||
{
|
||||
/* Check only players which can actually own vehicles, editor and gamescripts are considered deities */
|
||||
if (c < OWNER_END) {
|
||||
const Company *company = Company::GetIfValid(c);
|
||||
if (company != nullptr) return company->avail_roadtypes;
|
||||
}
|
||||
|
||||
RoadTypes known_roadtypes = ROADTYPES_NONE;
|
||||
|
||||
/* Find used roadtypes */
|
||||
Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
/* Check if the roadtype can be used in the current climate */
|
||||
if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
|
||||
|
||||
/* Check whether available for all potential companies */
|
||||
if (e->company_avail != (CompanyMask)-1) continue;
|
||||
|
||||
known_roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
|
||||
}
|
||||
|
||||
/* Get the date introduced roadtypes as well. */
|
||||
known_roadtypes = AddDateIntroducedRoadTypes(known_roadtypes, MAX_DAY);
|
||||
|
||||
return known_roadtypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we can build infrastructure for the given RoadType. This to disable building stations etc. when
|
||||
* you are not allowed/able to have the RoadType yet.
|
||||
* @param roadtype the roadtype to check this for
|
||||
* @param company the company id to check this for
|
||||
* @param any_date to check only existing vehicles or if it is possible to build them in the future
|
||||
* @return true if there is any reason why you may build the infrastructure for the given roadtype
|
||||
*/
|
||||
bool CanBuildRoadTypeInfrastructure(RoadType roadtype, CompanyID company)
|
||||
{
|
||||
if (_game_mode != GM_EDITOR && !Company::IsValidID(company)) return false;
|
||||
if (!_settings_client.gui.disable_unsuitable_building) return true;
|
||||
if (!HasAnyRoadTypesAvail(company, GetRoadTramType(roadtype))) return false;
|
||||
|
||||
RoadTypes roadtypes = ExistingRoadTypes(company);
|
||||
|
||||
/* Check if the filtered roadtypes does have the roadtype we are checking for
|
||||
* and if we can build new ones */
|
||||
if (_settings_game.vehicle.max_roadveh > 0 && HasBit(roadtypes, roadtype)) {
|
||||
/* Can we actually build the vehicle type? */
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
if (!HasBit(e->company_avail, company)) continue;
|
||||
if (HasPowerOnRoad(e->u.road.roadtype, roadtype) || HasPowerOnRoad(roadtype, e->u.road.roadtype)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* We should be able to build infrastructure when we have the actual vehicle type */
|
||||
const Vehicle *v;
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->type == VEH_ROAD && (company == OWNER_DEITY || v->owner == company) &&
|
||||
HasBit(roadtypes, RoadVehicle::From(v)->roadtype) && HasPowerOnRoad(RoadVehicle::From(v)->roadtype, roadtype)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file road.h Road specific functions. */
|
||||
|
||||
#ifndef ROAD_H
|
||||
#define ROAD_H
|
||||
|
||||
#include "road_type.h"
|
||||
#include "gfx_type.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "strings_type.h"
|
||||
#include "date_type.h"
|
||||
#include "core/enum_type.hpp"
|
||||
#include "newgrf.h"
|
||||
#include "economy_func.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
enum RoadTramType : bool {
|
||||
RTT_ROAD,
|
||||
RTT_TRAM,
|
||||
};
|
||||
|
||||
enum RoadTramTypes : uint8 {
|
||||
RTTB_ROAD = 1 << RTT_ROAD,
|
||||
RTTB_TRAM = 1 << RTT_TRAM,
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadTramTypes)
|
||||
|
||||
#define FOR_ALL_ROADTRAMTYPES(x) for (RoadTramType x : { RTT_ROAD, RTT_TRAM })
|
||||
|
||||
/** Roadtype flags. Starts with RO instead of R because R is used for rails */
|
||||
enum RoadTypeFlags {
|
||||
ROTF_CATENARY = 0, ///< Bit number for adding catenary
|
||||
ROTF_NO_LEVEL_CROSSING, ///< Bit number for disabling level crossing
|
||||
ROTF_NO_HOUSES, ///< Bit number for setting this roadtype as not house friendly
|
||||
ROTF_HIDDEN, ///< Bit number for hidden from construction.
|
||||
ROTF_TOWN_BUILD, ///< Bit number for allowing towns to build this roadtype.
|
||||
|
||||
ROTFB_NONE = 0, ///< All flags cleared.
|
||||
ROTFB_CATENARY = 1 << ROTF_CATENARY, ///< Value for drawing a catenary.
|
||||
ROTFB_NO_LEVEL_CROSSING = 1 << ROTF_NO_LEVEL_CROSSING, ///< Value for disabling a level crossing.
|
||||
ROTFB_NO_HOUSES = 1 << ROTF_NO_HOUSES, ///< Value for for setting this roadtype as not house friendly.
|
||||
ROTFB_HIDDEN = 1 << ROTF_HIDDEN, ///< Value for hidden from construction.
|
||||
ROTFB_TOWN_BUILD = 1 << ROTF_TOWN_BUILD, ///< Value for allowing towns to build this roadtype.
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadTypeFlags)
|
||||
|
||||
struct SpriteGroup;
|
||||
|
||||
/** Sprite groups for a roadtype. */
|
||||
enum RoadTypeSpriteGroup {
|
||||
ROTSG_CURSORS, ///< Optional: Cursor and toolbar icon images
|
||||
ROTSG_OVERLAY, ///< Optional: Images for overlaying track
|
||||
ROTSG_GROUND, ///< Required: Main group of ground images
|
||||
ROTSG_reserved1, ///< Placeholder, if we need specific tunnel sprites.
|
||||
ROTSG_CATENARY_FRONT, ///< Optional: Catenary front
|
||||
ROTSG_CATENARY_BACK, ///< Optional: Catenary back
|
||||
ROTSG_BRIDGE, ///< Required: Bridge surface images
|
||||
ROTSG_reserved2, ///< Placeholder, if we need specific level crossing sprites.
|
||||
ROTSG_DEPOT, ///< Optional: Depot images
|
||||
ROTSG_reserved3, ///< Placeholder, if we add road fences (for highways).
|
||||
ROTSG_ROADSTOP, ///< Required: Drive-in stop surface
|
||||
ROTSG_END,
|
||||
};
|
||||
|
||||
/** List of road type labels. */
|
||||
typedef std::vector<RoadTypeLabel> RoadTypeLabelList;
|
||||
|
||||
class RoadTypeInfo {
|
||||
public:
|
||||
/**
|
||||
* struct containing the sprites for the road GUI. @note only sprites referred to
|
||||
* directly in the code are listed
|
||||
*/
|
||||
struct {
|
||||
SpriteID build_x_road; ///< button for building single rail in X direction
|
||||
SpriteID build_y_road; ///< button for building single rail in Y direction
|
||||
SpriteID auto_road; ///< button for the autoroad construction
|
||||
SpriteID build_depot; ///< button for building depots
|
||||
SpriteID build_tunnel; ///< button for building a tunnel
|
||||
SpriteID convert_road; ///< button for converting road types
|
||||
} gui_sprites;
|
||||
|
||||
struct {
|
||||
CursorID road_swne; ///< Cursor for building rail in X direction
|
||||
CursorID road_nwse; ///< Cursor for building rail in Y direction
|
||||
CursorID autoroad; ///< Cursor for autorail tool
|
||||
CursorID depot; ///< Cursor for building a depot
|
||||
CursorID tunnel; ///< Cursor for building a tunnel
|
||||
SpriteID convert_road; ///< Cursor for converting road types
|
||||
} cursor; ///< Cursors associated with the road type.
|
||||
|
||||
struct {
|
||||
StringID name; ///< Name of this rail type.
|
||||
StringID toolbar_caption; ///< Caption in the construction toolbar GUI for this rail type.
|
||||
StringID menu_text; ///< Name of this rail type in the main toolbar dropdown.
|
||||
StringID build_caption; ///< Caption of the build vehicle GUI for this rail type.
|
||||
StringID replace_text; ///< Text used in the autoreplace GUI.
|
||||
StringID new_engine; ///< Name of an engine for this type of road in the engine preview GUI.
|
||||
|
||||
StringID err_build_road; ///< Building a normal piece of road
|
||||
StringID err_remove_road; ///< Removing a normal piece of road
|
||||
StringID err_depot; ///< Building a depot
|
||||
StringID err_build_station[2]; ///< Building a bus or truck station
|
||||
StringID err_remove_station[2]; ///< Removing of a bus or truck station
|
||||
StringID err_convert_road; ///< Converting a road type
|
||||
|
||||
StringID picker_title[2]; ///< Title for the station picker for bus or truck stations
|
||||
StringID picker_tooltip[2]; ///< Tooltip for the station picker for bus or truck stations
|
||||
} strings; ///< Strings associated with the rail type.
|
||||
|
||||
/** bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power */
|
||||
RoadTypes powered_roadtypes;
|
||||
|
||||
/**
|
||||
* Bit mask of road type flags
|
||||
*/
|
||||
RoadTypeFlags flags;
|
||||
|
||||
/**
|
||||
* Cost multiplier for building this road type
|
||||
*/
|
||||
uint16 cost_multiplier;
|
||||
|
||||
/**
|
||||
* Cost multiplier for maintenance of this road type
|
||||
*/
|
||||
uint16 maintenance_multiplier;
|
||||
|
||||
/**
|
||||
* Maximum speed for vehicles travelling on this road type
|
||||
*/
|
||||
uint16 max_speed;
|
||||
|
||||
/**
|
||||
* Unique 32 bit road type identifier
|
||||
*/
|
||||
RoadTypeLabel label;
|
||||
|
||||
/**
|
||||
* Road type labels this type provides in addition to the main label.
|
||||
*/
|
||||
RoadTypeLabelList alternate_labels;
|
||||
|
||||
/**
|
||||
* Colour on mini-map
|
||||
*/
|
||||
byte map_colour;
|
||||
|
||||
/**
|
||||
* Introduction date.
|
||||
* When #INVALID_DATE or a vehicle using this roadtype gets introduced earlier,
|
||||
* the vehicle's introduction date will be used instead for this roadtype.
|
||||
* The introduction at this date is furthermore limited by the
|
||||
* #introduction_required_types.
|
||||
*/
|
||||
Date introduction_date;
|
||||
|
||||
/**
|
||||
* Bitmask of roadtypes that are required for this roadtype to be introduced
|
||||
* at a given #introduction_date.
|
||||
*/
|
||||
RoadTypes introduction_required_roadtypes;
|
||||
|
||||
/**
|
||||
* Bitmask of which other roadtypes are introduced when this roadtype is introduced.
|
||||
*/
|
||||
RoadTypes introduces_roadtypes;
|
||||
|
||||
/**
|
||||
* The sorting order of this roadtype for the toolbar dropdown.
|
||||
*/
|
||||
byte sorting_order;
|
||||
|
||||
/**
|
||||
* NewGRF providing the Action3 for the roadtype. nullptr if not available.
|
||||
*/
|
||||
const GRFFile *grffile[ROTSG_END];
|
||||
|
||||
/**
|
||||
* Sprite groups for resolving sprites
|
||||
*/
|
||||
const SpriteGroup *group[ROTSG_END];
|
||||
|
||||
inline bool UsesOverlay() const
|
||||
{
|
||||
return this->group[ROTSG_GROUND] != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
extern RoadTypes _roadtypes_type;
|
||||
|
||||
static inline bool RoadTypeIsRoad(RoadType roadtype)
|
||||
{
|
||||
return !HasBit(_roadtypes_type, roadtype);
|
||||
}
|
||||
|
||||
static inline bool RoadTypeIsTram(RoadType roadtype)
|
||||
{
|
||||
return HasBit(_roadtypes_type, roadtype);
|
||||
}
|
||||
|
||||
static inline RoadTramType GetRoadTramType(RoadType roadtype)
|
||||
{
|
||||
return RoadTypeIsTram(roadtype) ? RTT_TRAM : RTT_ROAD;
|
||||
}
|
||||
|
||||
static inline RoadTramType OtherRoadTramType(RoadTramType rtt)
|
||||
{
|
||||
return rtt == RTT_ROAD ? RTT_TRAM : RTT_ROAD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the Roadtype information for a given roadtype
|
||||
* @param roadtype the road type which the information is requested for
|
||||
* @return The pointer to the RoadTypeInfo
|
||||
*/
|
||||
static inline const RoadTypeInfo *GetRoadTypeInfo(RoadType roadtype)
|
||||
{
|
||||
extern RoadTypeInfo _roadtypes[ROADTYPE_END];
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
return &_roadtypes[roadtype];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an engine of the given RoadType got power on a tile with a given
|
||||
* RoadType. This would normally just be an equality check, but for electrified
|
||||
* roads (which also support non-electric vehicles).
|
||||
* @return Whether the engine got power on this tile.
|
||||
* @param enginetype The RoadType of the engine we are considering.
|
||||
* @param tiletype The RoadType of the tile we are considering.
|
||||
*/
|
||||
static inline bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype)
|
||||
{
|
||||
return HasBit(GetRoadTypeInfo(enginetype)->powered_roadtypes, tiletype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cost of building the specified roadtype.
|
||||
* @param roadtype The roadtype being built.
|
||||
* @return The cost multiplier.
|
||||
*/
|
||||
static inline Money RoadBuildCost(RoadType roadtype)
|
||||
{
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
return (_price[PR_BUILD_ROAD] * GetRoadTypeInfo(roadtype)->cost_multiplier) >> 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cost of clearing the specified roadtype.
|
||||
* @param roadtype The roadtype being removed.
|
||||
* @return The cost.
|
||||
*/
|
||||
static inline Money RoadClearCost(RoadType roadtype)
|
||||
{
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
|
||||
/* Flat fee for removing road. */
|
||||
if (RoadTypeIsRoad(roadtype)) return _price[PR_CLEAR_ROAD];
|
||||
|
||||
/* Clearing tram earns a little money, but also incurs the standard clear road cost,
|
||||
* so no profit can be made. */
|
||||
return _price[PR_CLEAR_ROAD] - RoadBuildCost(roadtype) * 3 / 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the cost of road conversion
|
||||
* @param from The roadtype we are converting from
|
||||
* @param to The roadtype we are converting to
|
||||
* @return Cost per RoadBit
|
||||
*/
|
||||
static inline Money RoadConvertCost(RoadType from, RoadType to)
|
||||
{
|
||||
/* Don't apply convert costs when converting to the same roadtype (ex. building a roadstop over existing road) */
|
||||
if (from == to) return (Money)0;
|
||||
|
||||
/* Same cost as removing and then building. */
|
||||
return RoadBuildCost(to) + RoadClearCost(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if road disallows level crossings
|
||||
* @param roadtype The roadtype we are testing
|
||||
* @return True iff the roadtype disallows level crossings
|
||||
*/
|
||||
static inline bool RoadNoLevelCrossing(RoadType roadtype)
|
||||
{
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
return HasBit(GetRoadTypeInfo(roadtype)->flags, ROTF_NO_LEVEL_CROSSING);
|
||||
}
|
||||
|
||||
RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels = true);
|
||||
|
||||
void ResetRoadTypes();
|
||||
void InitRoadTypes();
|
||||
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt);
|
||||
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt);
|
||||
|
||||
extern std::vector<RoadType> _sorted_roadtypes;
|
||||
extern RoadTypes _roadtypes_hidden_mask;
|
||||
|
||||
/**
|
||||
* Loop header for iterating over roadtypes, sorted by sortorder.
|
||||
* @param var Roadtype.
|
||||
*/
|
||||
#define FOR_ALL_SORTED_ROADTYPES(var) for (uint8 index = 0; index < _sorted_roadtypes.size() && (var = _sorted_roadtypes[index], true) ; index++)
|
||||
|
||||
#endif /* ROAD_H */
|
1147
src/road_cmd.cpp
1147
src/road_cmd.cpp
File diff suppressed because it is too large
Load Diff
|
@ -13,29 +13,9 @@
|
|||
#define ROAD_FUNC_H
|
||||
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include "road_type.h"
|
||||
#include "road.h"
|
||||
#include "economy_func.h"
|
||||
|
||||
/**
|
||||
* Iterate through each set RoadType in a RoadTypes value.
|
||||
* For more informations see FOR_EACH_SET_BIT_EX.
|
||||
*
|
||||
* @param var Loop index variable that stores fallowing set road type. Must be of type RoadType.
|
||||
* @param road_types The value to iterate through (any expression).
|
||||
*
|
||||
* @see FOR_EACH_SET_BIT_EX
|
||||
*/
|
||||
#define FOR_EACH_SET_ROADTYPE(var, road_types) FOR_EACH_SET_BIT_EX(RoadType, var, RoadTypes, road_types)
|
||||
|
||||
/**
|
||||
* Whether the given roadtype is valid.
|
||||
* @param rt the roadtype to check for validness
|
||||
* @return true if and only if valid
|
||||
*/
|
||||
static inline bool IsValidRoadType(RoadType rt)
|
||||
{
|
||||
return rt == ROADTYPE_ROAD || rt == ROADTYPE_TRAM;
|
||||
}
|
||||
#include "transparency.h"
|
||||
|
||||
/**
|
||||
* Whether the given roadtype is valid.
|
||||
|
@ -47,32 +27,6 @@ static inline bool IsValidRoadBits(RoadBits r)
|
|||
return r < ROAD_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a RoadType to the corresponding RoadTypes value
|
||||
*
|
||||
* @param rt the roadtype to get the roadtypes from
|
||||
* @return the roadtypes with the given roadtype
|
||||
*/
|
||||
static inline RoadTypes RoadTypeToRoadTypes(RoadType rt)
|
||||
{
|
||||
assert(IsValidRoadType(rt));
|
||||
return (RoadTypes)(1 << rt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RoadTypes which are not present in the given RoadTypes
|
||||
*
|
||||
* This function returns the complement of a given RoadTypes.
|
||||
*
|
||||
* @param r The given RoadTypes
|
||||
* @return The complement of the given RoadTypes
|
||||
*/
|
||||
static inline RoadTypes ComplementRoadTypes(RoadTypes r)
|
||||
{
|
||||
return (RoadTypes)(ROADTYPES_ALL ^ r);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the complement of a RoadBits value
|
||||
*
|
||||
|
@ -167,18 +121,44 @@ static inline RoadBits AxisToRoadBits(Axis a)
|
|||
* Calculates the maintenance cost of a number of road bits.
|
||||
* @param roadtype Road type to get the cost for.
|
||||
* @param num Number of road bits.
|
||||
* @param total_num Total number of road bits of all road/tram-types.
|
||||
* @return Total cost.
|
||||
*/
|
||||
static inline Money RoadMaintenanceCost(RoadType roadtype, uint32 num)
|
||||
static inline Money RoadMaintenanceCost(RoadType roadtype, uint32 num, uint32 total_num)
|
||||
{
|
||||
assert(IsValidRoadType(roadtype));
|
||||
return (_price[PR_INFRASTRUCTURE_ROAD] * (roadtype == ROADTYPE_TRAM ? 3 : 2) * num * (1 + IntSqrt(num))) >> 9; // 2 bits fraction for the multiplier and 7 bits scaling.
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
return (_price[PR_INFRASTRUCTURE_ROAD] * GetRoadTypeInfo(roadtype)->maintenance_multiplier * num * (1 + IntSqrt(total_num))) >> 12;
|
||||
}
|
||||
|
||||
bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts);
|
||||
bool ValParamRoadType(const RoadType rt);
|
||||
RoadTypes GetCompanyRoadtypes(const CompanyID company);
|
||||
/**
|
||||
* Test if a road type has catenary
|
||||
* @param roadtype Road type to test
|
||||
*/
|
||||
static inline bool HasRoadCatenary(RoadType roadtype)
|
||||
{
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
return HasBit(GetRoadTypeInfo(roadtype)->flags, ROTF_CATENARY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if we should draw road catenary
|
||||
* @param roadtype Road type to test
|
||||
*/
|
||||
static inline bool HasRoadCatenaryDrawn(RoadType roadtype)
|
||||
{
|
||||
return HasRoadCatenary(roadtype) && !IsInvisibilitySet(TO_CATENARY);
|
||||
}
|
||||
|
||||
bool HasRoadTypeAvail(CompanyID company, RoadType roadtype);
|
||||
bool ValParamRoadType(RoadType roadtype);
|
||||
RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces = true);
|
||||
RoadTypes GetRoadTypes(bool introduces);
|
||||
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date);
|
||||
|
||||
void UpdateLevelCrossing(TileIndex tile, bool sound = true);
|
||||
void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count);
|
||||
|
||||
struct TileInfo;
|
||||
void DrawRoadOverlays(const TileInfo *ti, PaletteID pal, const RoadTypeInfo *road_rti, const RoadTypeInfo *tram_rit, uint road_offset, uint tram_offset);
|
||||
|
||||
#endif /* ROAD_FUNC_H */
|
||||
|
|
488
src/road_gui.cpp
488
src/road_gui.cpp
|
@ -29,6 +29,10 @@
|
|||
#include "hotkeys.h"
|
||||
#include "road_gui.h"
|
||||
#include "zoom_func.h"
|
||||
#include "engine_base.h"
|
||||
#include "strings_func.h"
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "date_func.h"
|
||||
|
||||
#include "widgets/road_widget.h"
|
||||
|
||||
|
@ -110,52 +114,6 @@ void CcBuildRoadTunnel(const CommandCost &result, TileIndex start_tile, uint32 p
|
|||
}
|
||||
}
|
||||
|
||||
/** Structure holding information per roadtype for several functions */
|
||||
struct RoadTypeInfo {
|
||||
StringID err_build_road; ///< Building a normal piece of road
|
||||
StringID err_remove_road; ///< Removing a normal piece of road
|
||||
StringID err_depot; ///< Building a depot
|
||||
StringID err_build_station[2]; ///< Building a bus or truck station
|
||||
StringID err_remove_station[2]; ///< Removing of a bus or truck station
|
||||
|
||||
StringID picker_title[2]; ///< Title for the station picker for bus or truck stations
|
||||
StringID picker_tooltip[2]; ///< Tooltip for the station picker for bus or truck stations
|
||||
|
||||
SpriteID cursor_nesw; ///< Cursor for building NE and SW bits
|
||||
SpriteID cursor_nwse; ///< Cursor for building NW and SE bits
|
||||
SpriteID cursor_autoroad; ///< Cursor for building autoroad
|
||||
};
|
||||
|
||||
/** What errors/cursors must be shown for several types of roads */
|
||||
static const RoadTypeInfo _road_type_infos[] = {
|
||||
{
|
||||
STR_ERROR_CAN_T_BUILD_ROAD_HERE,
|
||||
STR_ERROR_CAN_T_REMOVE_ROAD_FROM,
|
||||
STR_ERROR_CAN_T_BUILD_ROAD_DEPOT,
|
||||
{ STR_ERROR_CAN_T_BUILD_BUS_STATION, STR_ERROR_CAN_T_BUILD_TRUCK_STATION },
|
||||
{ STR_ERROR_CAN_T_REMOVE_BUS_STATION, STR_ERROR_CAN_T_REMOVE_TRUCK_STATION },
|
||||
{ STR_STATION_BUILD_BUS_ORIENTATION, STR_STATION_BUILD_TRUCK_ORIENTATION },
|
||||
{ STR_STATION_BUILD_BUS_ORIENTATION_TOOLTIP, STR_STATION_BUILD_TRUCK_ORIENTATION_TOOLTIP },
|
||||
|
||||
SPR_CURSOR_ROAD_NESW,
|
||||
SPR_CURSOR_ROAD_NWSE,
|
||||
SPR_CURSOR_AUTOROAD,
|
||||
},
|
||||
{
|
||||
STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE,
|
||||
STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM,
|
||||
STR_ERROR_CAN_T_BUILD_TRAM_DEPOT,
|
||||
{ STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION, STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION },
|
||||
{ STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION, STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION },
|
||||
{ STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION, STR_STATION_BUILD_CARGO_TRAM_ORIENTATION },
|
||||
{ STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION_TOOLTIP, STR_STATION_BUILD_CARGO_TRAM_ORIENTATION_TOOLTIP },
|
||||
|
||||
SPR_CURSOR_TRAMWAY_NESW,
|
||||
SPR_CURSOR_TRAMWAY_NWSE,
|
||||
SPR_CURSOR_AUTOTRAM,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* If required, connects a new structure to an existing road or tram by building the missing roadbit.
|
||||
* @param tile Tile containing the structure to connect.
|
||||
|
@ -166,7 +124,7 @@ void ConnectRoadToStructure(TileIndex tile, DiagDirection direction)
|
|||
tile += TileOffsByDiagDir(direction);
|
||||
/* if there is a roadpiece just outside of the station entrance, build a connecting route */
|
||||
if (IsNormalRoadTile(tile)) {
|
||||
if (GetRoadBits(tile, _cur_roadtype) != ROAD_NONE) {
|
||||
if (GetRoadBits(tile, GetRoadTramType(_cur_roadtype)) != ROAD_NONE) {
|
||||
DoCommandP(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, CMD_BUILD_ROAD);
|
||||
}
|
||||
}
|
||||
|
@ -190,9 +148,10 @@ void CcRoadDepot(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2
|
|||
* bit 8..15: Length of the road stop.
|
||||
* @param p2 bit 0: 0 For bus stops, 1 for truck stops.
|
||||
* bit 1: 0 For normal stops, 1 for drive-through.
|
||||
* bit 2..3: The roadtypes.
|
||||
* bit 5: Allow stations directly adjacent to other stations.
|
||||
* bit 6..7: Entrance direction (#DiagDirection).
|
||||
* bit 2: Allow stations directly adjacent to other stations.
|
||||
* bit 3..4: Entrance direction (#DiagDirection) for normal stops.
|
||||
* bit 3: #Axis of the road for drive-through stops.
|
||||
* bit 5..9: The roadtype.
|
||||
* bit 16..31: Station ID to join (NEW_STATION if build new one).
|
||||
* @see CmdBuildRoadStop
|
||||
*/
|
||||
|
@ -200,7 +159,7 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
|||
{
|
||||
if (result.Failed()) return;
|
||||
|
||||
DiagDirection dir = (DiagDirection)GB(p2, 6, 2);
|
||||
DiagDirection dir = (DiagDirection)GB(p2, 3, 2);
|
||||
if (_settings_client.sound.confirm) SndPlayTileFx(SND_1F_SPLAT_OTHER, tile);
|
||||
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||
TileArea roadstop_area(tile, GB(p1, 0, 8), GB(p1, 8, 8));
|
||||
|
@ -216,8 +175,8 @@ void CcRoadStop(const CommandCost &result, TileIndex tile, uint32 p1, uint32 p2)
|
|||
* @param start_tile First tile of the area.
|
||||
* @param end_tile Last tile of the area.
|
||||
* @param p2 bit 0: 0 For bus stops, 1 for truck stops.
|
||||
* bit 2..3: The roadtypes.
|
||||
* bit 5: Allow stations directly adjacent to other stations.
|
||||
* bit 2: Allow stations directly adjacent to other stations.
|
||||
* bit 5..10: The roadtypes.
|
||||
* @param cmd Command to use.
|
||||
* @see CcRoadStop()
|
||||
*/
|
||||
|
@ -230,7 +189,7 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u
|
|||
SetBit(p2, 1); // It's a drive-through stop.
|
||||
ddir -= DIAGDIR_END; // Adjust picker result to actual direction.
|
||||
}
|
||||
p2 |= ddir << 6; // Set the DiagDirecion into p2 bits 6 and 7.
|
||||
p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.
|
||||
|
||||
TileArea ta(start_tile, end_tile);
|
||||
CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop, "" };
|
||||
|
@ -309,15 +268,20 @@ static bool RoadToolbar_CtrlChanged(Window *w)
|
|||
|
||||
/** Road toolbar window handler. */
|
||||
struct BuildRoadToolbarWindow : Window {
|
||||
int last_started_action; ///< Last started user action.
|
||||
RoadType roadtype; ///< Road type to build.
|
||||
const RoadTypeInfo *rti; ///< Informations about current road type
|
||||
int last_started_action; ///< Last started user action.
|
||||
|
||||
BuildRoadToolbarWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||
{
|
||||
this->Initialize(_cur_roadtype);
|
||||
this->InitNested(window_number);
|
||||
this->SetWidgetsDisabledState(true,
|
||||
WID_ROT_REMOVE,
|
||||
WID_ROT_ONE_WAY,
|
||||
WIDGET_LIST_END);
|
||||
this->SetupRoadToolbar();
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, true);
|
||||
|
||||
if (RoadTypeIsRoad(this->roadtype)) {
|
||||
this->SetWidgetDisabledState(WID_ROT_ONE_WAY, true);
|
||||
}
|
||||
|
||||
this->OnInvalidateData();
|
||||
this->last_started_action = WIDGET_LIST_END;
|
||||
|
@ -340,7 +304,8 @@ struct BuildRoadToolbarWindow : Window {
|
|||
{
|
||||
if (!gui_scope) return;
|
||||
|
||||
bool can_build = CanBuildVehicleInfrastructure(VEH_ROAD);
|
||||
if (_game_mode != GM_EDITOR && !CanBuildVehicleInfrastructure(VEH_ROAD, GetRoadTramType(this->roadtype))) delete this;
|
||||
bool can_build = _game_mode != GM_EDITOR;
|
||||
this->SetWidgetsDisabledState(!can_build,
|
||||
WID_ROT_DEPOT,
|
||||
WID_ROT_BUS_STATION,
|
||||
|
@ -353,6 +318,53 @@ struct BuildRoadToolbarWindow : Window {
|
|||
}
|
||||
}
|
||||
|
||||
void Initialize(RoadType roadtype)
|
||||
{
|
||||
assert(roadtype < ROADTYPE_END);
|
||||
this->roadtype = roadtype;
|
||||
this->rti = GetRoadTypeInfo(this->roadtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the road toolbar for roadtype given
|
||||
* @param roadtype the roadtype to display
|
||||
*/
|
||||
void SetupRoadToolbar()
|
||||
{
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_ROAD_X)->widget_data = rti->gui_sprites.build_x_road;
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_ROAD_Y)->widget_data = rti->gui_sprites.build_y_road;
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_AUTOROAD)->widget_data = rti->gui_sprites.auto_road;
|
||||
if (_game_mode != GM_EDITOR) {
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_DEPOT)->widget_data = rti->gui_sprites.build_depot;
|
||||
}
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_CONVERT_ROAD)->widget_data = rti->gui_sprites.convert_road;
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_BUILD_TUNNEL)->widget_data = rti->gui_sprites.build_tunnel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to another road type.
|
||||
* @param roadtype New road type.
|
||||
*/
|
||||
void ModifyRoadType(RoadType roadtype)
|
||||
{
|
||||
this->Initialize(roadtype);
|
||||
this->SetupRoadToolbar();
|
||||
this->ReInit();
|
||||
}
|
||||
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
if (widget == WID_ROT_CAPTION) {
|
||||
if (this->rti->max_speed > 0) {
|
||||
SetDParam(0, STR_TOOLBAR_RAILTYPE_VELOCITY);
|
||||
SetDParam(1, this->rti->strings.toolbar_caption);
|
||||
SetDParam(2, this->rti->max_speed / 2);
|
||||
} else {
|
||||
SetDParam(0, this->rti->strings.toolbar_caption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the remove button lowered state of the road toolbar
|
||||
*
|
||||
|
@ -365,8 +377,11 @@ struct BuildRoadToolbarWindow : Window {
|
|||
* Both are only valid if they are able to apply as options. */
|
||||
switch (clicked_widget) {
|
||||
case WID_ROT_REMOVE:
|
||||
this->RaiseWidget(WID_ROT_ONE_WAY);
|
||||
this->SetWidgetDirty(WID_ROT_ONE_WAY);
|
||||
if (RoadTypeIsRoad(this->roadtype)) {
|
||||
this->RaiseWidget(WID_ROT_ONE_WAY);
|
||||
this->SetWidgetDirty(WID_ROT_ONE_WAY);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case WID_ROT_ONE_WAY:
|
||||
|
@ -376,30 +391,30 @@ struct BuildRoadToolbarWindow : Window {
|
|||
|
||||
case WID_ROT_BUS_STATION:
|
||||
case WID_ROT_TRUCK_STATION:
|
||||
this->DisableWidget(WID_ROT_ONE_WAY);
|
||||
if (RoadTypeIsRoad(this->roadtype)) this->DisableWidget(WID_ROT_ONE_WAY);
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, !this->IsWidgetLowered(clicked_widget));
|
||||
break;
|
||||
|
||||
case WID_ROT_ROAD_X:
|
||||
case WID_ROT_ROAD_Y:
|
||||
case WID_ROT_AUTOROAD:
|
||||
this->SetWidgetsDisabledState(!this->IsWidgetLowered(clicked_widget),
|
||||
WID_ROT_REMOVE,
|
||||
WID_ROT_ONE_WAY,
|
||||
WIDGET_LIST_END);
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, !this->IsWidgetLowered(clicked_widget));
|
||||
if (RoadTypeIsRoad(this->roadtype)) {
|
||||
this->SetWidgetDisabledState(WID_ROT_ONE_WAY, !this->IsWidgetLowered(clicked_widget));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* When any other buttons than road/station, raise and
|
||||
* disable the removal button */
|
||||
this->SetWidgetsDisabledState(true,
|
||||
WID_ROT_REMOVE,
|
||||
WID_ROT_ONE_WAY,
|
||||
WIDGET_LIST_END);
|
||||
this->SetWidgetsLoweredState(false,
|
||||
WID_ROT_REMOVE,
|
||||
WID_ROT_ONE_WAY,
|
||||
WIDGET_LIST_END);
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, true);
|
||||
this->SetWidgetLoweredState(WID_ROT_REMOVE, false);
|
||||
|
||||
if (RoadTypeIsRoad(this->roadtype)) {
|
||||
this->SetWidgetDisabledState(WID_ROT_ONE_WAY, true);
|
||||
this->SetWidgetLoweredState(WID_ROT_ONE_WAY, false);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -410,17 +425,17 @@ struct BuildRoadToolbarWindow : Window {
|
|||
_one_way_button_clicked = false;
|
||||
switch (widget) {
|
||||
case WID_ROT_ROAD_X:
|
||||
HandlePlacePushButton(this, WID_ROT_ROAD_X, _road_type_infos[_cur_roadtype].cursor_nwse, HT_RECT);
|
||||
HandlePlacePushButton(this, WID_ROT_ROAD_X, this->rti->cursor.road_nwse, HT_RECT);
|
||||
this->last_started_action = widget;
|
||||
break;
|
||||
|
||||
case WID_ROT_ROAD_Y:
|
||||
HandlePlacePushButton(this, WID_ROT_ROAD_Y, _road_type_infos[_cur_roadtype].cursor_nesw, HT_RECT);
|
||||
HandlePlacePushButton(this, WID_ROT_ROAD_Y, this->rti->cursor.road_swne, HT_RECT);
|
||||
this->last_started_action = widget;
|
||||
break;
|
||||
|
||||
case WID_ROT_AUTOROAD:
|
||||
HandlePlacePushButton(this, WID_ROT_AUTOROAD, _road_type_infos[_cur_roadtype].cursor_autoroad, HT_RECT);
|
||||
HandlePlacePushButton(this, WID_ROT_AUTOROAD, this->rti->cursor.autoroad, HT_RECT);
|
||||
this->last_started_action = widget;
|
||||
break;
|
||||
|
||||
|
@ -430,15 +445,15 @@ struct BuildRoadToolbarWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_ROT_DEPOT:
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
|
||||
if (HandlePlacePushButton(this, WID_ROT_DEPOT, SPR_CURSOR_ROAD_DEPOT, HT_RECT)) {
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, GetRoadTramType(this->roadtype))) return;
|
||||
if (HandlePlacePushButton(this, WID_ROT_DEPOT, this->rti->cursor.depot, HT_RECT)) {
|
||||
ShowRoadDepotPicker(this);
|
||||
this->last_started_action = widget;
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_ROT_BUS_STATION:
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, GetRoadTramType(this->roadtype))) return;
|
||||
if (HandlePlacePushButton(this, WID_ROT_BUS_STATION, SPR_CURSOR_BUS_STATION, HT_RECT)) {
|
||||
ShowRVStationPicker(this, ROADSTOP_BUS);
|
||||
this->last_started_action = widget;
|
||||
|
@ -446,7 +461,7 @@ struct BuildRoadToolbarWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_ROT_TRUCK_STATION:
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD)) return;
|
||||
if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, GetRoadTramType(this->roadtype))) return;
|
||||
if (HandlePlacePushButton(this, WID_ROT_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, HT_RECT)) {
|
||||
ShowRVStationPicker(this, ROADSTOP_TRUCK);
|
||||
this->last_started_action = widget;
|
||||
|
@ -466,7 +481,7 @@ struct BuildRoadToolbarWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_ROT_BUILD_TUNNEL:
|
||||
HandlePlacePushButton(this, WID_ROT_BUILD_TUNNEL, SPR_CURSOR_ROAD_TUNNEL, HT_SPECIAL);
|
||||
HandlePlacePushButton(this, WID_ROT_BUILD_TUNNEL, this->rti->cursor.tunnel, HT_SPECIAL);
|
||||
this->last_started_action = widget;
|
||||
break;
|
||||
|
||||
|
@ -478,6 +493,11 @@ struct BuildRoadToolbarWindow : Window {
|
|||
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||
break;
|
||||
|
||||
case WID_ROT_CONVERT_ROAD:
|
||||
HandlePlacePushButton(this, WID_ROT_CONVERT_ROAD, this->rti->cursor.convert_road, HT_RECT);
|
||||
this->last_started_action = widget;
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
this->UpdateOptionWidgetStatus((RoadToolbarWidgets)widget);
|
||||
|
@ -493,7 +513,7 @@ struct BuildRoadToolbarWindow : Window {
|
|||
void OnPlaceObject(Point pt, TileIndex tile) override
|
||||
{
|
||||
_remove_button_clicked = this->IsWidgetLowered(WID_ROT_REMOVE);
|
||||
_one_way_button_clicked = this->IsWidgetLowered(WID_ROT_ONE_WAY);
|
||||
_one_way_button_clicked = RoadTypeIsRoad(this->roadtype) ? this->IsWidgetLowered(WID_ROT_ONE_WAY) : false;
|
||||
switch (this->last_started_action) {
|
||||
case WID_ROT_ROAD_X:
|
||||
_place_road_flag = RF_DIR_X;
|
||||
|
@ -520,7 +540,7 @@ struct BuildRoadToolbarWindow : Window {
|
|||
|
||||
case WID_ROT_DEPOT:
|
||||
DoCommandP(tile, _cur_roadtype << 2 | _road_depot_orientation, 0,
|
||||
CMD_BUILD_ROAD_DEPOT | CMD_MSG(_road_type_infos[_cur_roadtype].err_depot), CcRoadDepot);
|
||||
CMD_BUILD_ROAD_DEPOT | CMD_MSG(this->rti->strings.err_depot), CcRoadDepot);
|
||||
break;
|
||||
|
||||
case WID_ROT_BUS_STATION:
|
||||
|
@ -536,10 +556,14 @@ struct BuildRoadToolbarWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_ROT_BUILD_TUNNEL:
|
||||
DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0,
|
||||
DoCommandP(tile, _cur_roadtype | (TRANSPORT_ROAD << 8), 0,
|
||||
CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel);
|
||||
break;
|
||||
|
||||
case WID_ROT_CONVERT_ROAD:
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_CONVERT_ROAD);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
@ -549,12 +573,13 @@ struct BuildRoadToolbarWindow : Window {
|
|||
if (_game_mode != GM_EDITOR && (this->IsWidgetLowered(WID_ROT_BUS_STATION) || this->IsWidgetLowered(WID_ROT_TRUCK_STATION))) SetViewportCatchmentStation(nullptr, true);
|
||||
|
||||
this->RaiseButtons();
|
||||
this->SetWidgetsDisabledState(true,
|
||||
WID_ROT_REMOVE,
|
||||
WID_ROT_ONE_WAY,
|
||||
WIDGET_LIST_END);
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, true);
|
||||
this->SetWidgetDirty(WID_ROT_REMOVE);
|
||||
this->SetWidgetDirty(WID_ROT_ONE_WAY);
|
||||
|
||||
if (RoadTypeIsRoad(this->roadtype)) {
|
||||
this->SetWidgetDisabledState(WID_ROT_ONE_WAY, true);
|
||||
this->SetWidgetDirty(WID_ROT_ONE_WAY);
|
||||
}
|
||||
|
||||
DeleteWindowById(WC_BUS_STATION, TRANSPORT_ROAD);
|
||||
DeleteWindowById(WC_TRUCK_STATION, TRANSPORT_ROAD);
|
||||
|
@ -613,7 +638,7 @@ struct BuildRoadToolbarWindow : Window {
|
|||
default: NOT_REACHED();
|
||||
case DDSP_BUILD_BRIDGE:
|
||||
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||
ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, RoadTypeToRoadTypes(_cur_roadtype));
|
||||
ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, _cur_roadtype);
|
||||
break;
|
||||
|
||||
case DDSP_DEMOLISH_AREA:
|
||||
|
@ -627,12 +652,16 @@ struct BuildRoadToolbarWindow : Window {
|
|||
* Use the first three bits (0x07) if dir == Y
|
||||
* else use the last 2 bits (X dir has
|
||||
* not the 3rd bit set) */
|
||||
|
||||
/* Even if _cur_roadtype_id is a uint8 we only use 5 bits so
|
||||
* we could ignore the last 3 bits and reuse them for other
|
||||
* flags */
|
||||
_place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
|
||||
|
||||
DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 5),
|
||||
DoCommandP(start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 10),
|
||||
_remove_button_clicked ?
|
||||
CMD_REMOVE_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_road) :
|
||||
CMD_BUILD_LONG_ROAD | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_road), CcPlaySound_SPLAT_OTHER);
|
||||
CMD_REMOVE_LONG_ROAD | CMD_MSG(this->rti->strings.err_remove_road) :
|
||||
CMD_BUILD_LONG_ROAD | CMD_MSG(this->rti->strings.err_build_road), CcPlaySound_SPLAT_OTHER);
|
||||
break;
|
||||
|
||||
case DDSP_BUILD_BUSSTOP:
|
||||
|
@ -640,9 +669,9 @@ struct BuildRoadToolbarWindow : Window {
|
|||
if (this->IsWidgetLowered(WID_ROT_BUS_STATION)) {
|
||||
if (_remove_button_clicked) {
|
||||
TileArea ta(start_tile, end_tile);
|
||||
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_BUS]), CcPlaySound_SPLAT_OTHER);
|
||||
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_BUS, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_BUS]), CcPlaySound_SPLAT_OTHER);
|
||||
} else {
|
||||
PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_BUS]));
|
||||
PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_BUS, CMD_BUILD_ROAD_STOP | CMD_MSG(this->rti->strings.err_build_station[ROADSTOP_BUS]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -652,19 +681,23 @@ struct BuildRoadToolbarWindow : Window {
|
|||
if (this->IsWidgetLowered(WID_ROT_TRUCK_STATION)) {
|
||||
if (_remove_button_clicked) {
|
||||
TileArea ta(start_tile, end_tile);
|
||||
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_SPLAT_OTHER);
|
||||
DoCommandP(ta.tile, ta.w | ta.h << 8, (_ctrl_pressed << 1) | ROADSTOP_TRUCK, CMD_REMOVE_ROAD_STOP | CMD_MSG(this->rti->strings.err_remove_station[ROADSTOP_TRUCK]), CcPlaySound_SPLAT_OTHER);
|
||||
} else {
|
||||
PlaceRoadStop(start_tile, end_tile, (_ctrl_pressed << 5) | RoadTypeToRoadTypes(_cur_roadtype) << 2 | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(_road_type_infos[_cur_roadtype].err_build_station[ROADSTOP_TRUCK]));
|
||||
PlaceRoadStop(start_tile, end_tile, _cur_roadtype << 5 | (_ctrl_pressed << 2) | ROADSTOP_TRUCK, CMD_BUILD_ROAD_STOP | CMD_MSG(this->rti->strings.err_build_station[ROADSTOP_TRUCK]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DDSP_CONVERT_ROAD:
|
||||
DoCommandP(end_tile, start_tile, _cur_roadtype, CMD_CONVERT_ROAD | CMD_MSG(rti->strings.err_convert_road), CcPlaySound_SPLAT_OTHER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlacePresize(Point pt, TileIndex tile) override
|
||||
{
|
||||
DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
DoCommand(tile, _cur_roadtype | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL);
|
||||
VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
|
||||
}
|
||||
|
||||
|
@ -674,36 +707,38 @@ struct BuildRoadToolbarWindow : Window {
|
|||
return ES_NOT_HANDLED;
|
||||
}
|
||||
|
||||
static HotkeyList hotkeys;
|
||||
static HotkeyList road_hotkeys;
|
||||
static HotkeyList tram_hotkeys;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for global hotkeys of the BuildRoadToolbarWindow.
|
||||
* @param hotkey Hotkey
|
||||
* @param last_build Last build road type
|
||||
* @return ES_HANDLED if hotkey was accepted.
|
||||
*/
|
||||
static EventState RoadToolbarGlobalHotkeys(int hotkey)
|
||||
static EventState RoadTramToolbarGlobalHotkeys(int hotkey, RoadType last_build)
|
||||
{
|
||||
Window *w = nullptr;
|
||||
switch (_game_mode) {
|
||||
case GM_NORMAL: {
|
||||
extern RoadType _last_built_roadtype;
|
||||
w = ShowBuildRoadToolbar(_last_built_roadtype);
|
||||
break;
|
||||
}
|
||||
|
||||
case GM_EDITOR:
|
||||
w = ShowBuildRoadScenToolbar();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Window *w = (_game_mode == GM_NORMAL) ? ShowBuildRoadToolbar(last_build) : ShowBuildRoadScenToolbar(last_build);
|
||||
if (w == nullptr) return ES_NOT_HANDLED;
|
||||
return w->OnHotkey(hotkey);
|
||||
}
|
||||
|
||||
static EventState RoadToolbarGlobalHotkeys(int hotkey)
|
||||
{
|
||||
if (_game_mode == GM_NORMAL && !CanBuildVehicleInfrastructure(VEH_ROAD, RTT_ROAD)) return ES_NOT_HANDLED;
|
||||
|
||||
extern RoadType _last_built_roadtype;
|
||||
return RoadTramToolbarGlobalHotkeys(hotkey, _last_built_roadtype);
|
||||
}
|
||||
|
||||
static EventState TramToolbarGlobalHotkeys(int hotkey)
|
||||
{
|
||||
if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_ROAD, RTT_TRAM)) return ES_NOT_HANDLED;
|
||||
extern RoadType _last_built_tramtype;
|
||||
return RoadTramToolbarGlobalHotkeys(hotkey, _last_built_tramtype);
|
||||
}
|
||||
|
||||
static Hotkey roadtoolbar_hotkeys[] = {
|
||||
Hotkey('1', "build_x", WID_ROT_ROAD_X),
|
||||
Hotkey('2', "build_y", WID_ROT_ROAD_Y),
|
||||
|
@ -716,15 +751,32 @@ static Hotkey roadtoolbar_hotkeys[] = {
|
|||
Hotkey('B', "bridge", WID_ROT_BUILD_BRIDGE),
|
||||
Hotkey('T', "tunnel", WID_ROT_BUILD_TUNNEL),
|
||||
Hotkey('R', "remove", WID_ROT_REMOVE),
|
||||
Hotkey('C', "convert", WID_ROT_CONVERT_ROAD),
|
||||
HOTKEY_LIST_END
|
||||
};
|
||||
HotkeyList BuildRoadToolbarWindow::hotkeys("roadtoolbar", roadtoolbar_hotkeys, RoadToolbarGlobalHotkeys);
|
||||
HotkeyList BuildRoadToolbarWindow::road_hotkeys("roadtoolbar", roadtoolbar_hotkeys, RoadToolbarGlobalHotkeys);
|
||||
|
||||
static Hotkey tramtoolbar_hotkeys[] = {
|
||||
Hotkey('1', "build_x", WID_ROT_ROAD_X),
|
||||
Hotkey('2', "build_y", WID_ROT_ROAD_Y),
|
||||
Hotkey('3', "autoroad", WID_ROT_AUTOROAD),
|
||||
Hotkey('4', "demolish", WID_ROT_DEMOLISH),
|
||||
Hotkey('5', "depot", WID_ROT_DEPOT),
|
||||
Hotkey('6', "bus_station", WID_ROT_BUS_STATION),
|
||||
Hotkey('7', "truck_station", WID_ROT_TRUCK_STATION),
|
||||
Hotkey('B', "bridge", WID_ROT_BUILD_BRIDGE),
|
||||
Hotkey('T', "tunnel", WID_ROT_BUILD_TUNNEL),
|
||||
Hotkey('R', "remove", WID_ROT_REMOVE),
|
||||
Hotkey('C', "convert", WID_ROT_CONVERT_ROAD),
|
||||
HOTKEY_LIST_END
|
||||
};
|
||||
HotkeyList BuildRoadToolbarWindow::tram_hotkeys("tramtoolbar", tramtoolbar_hotkeys, TramToolbarGlobalHotkeys);
|
||||
|
||||
|
||||
static const NWidgetPart _nested_build_road_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
|
@ -751,6 +803,8 @@ static const NWidgetPart _nested_build_road_widgets[] = {
|
|||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_CONVERT_ROAD),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_CONVERT_ROAD, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
|
@ -759,13 +813,13 @@ static WindowDesc _build_road_desc(
|
|||
WC_BUILD_TOOLBAR, WC_NONE,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_build_road_widgets, lengthof(_nested_build_road_widgets),
|
||||
&BuildRoadToolbarWindow::hotkeys
|
||||
&BuildRoadToolbarWindow::road_hotkeys
|
||||
);
|
||||
|
||||
static const NWidgetPart _nested_build_tramway_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
|
@ -784,13 +838,14 @@ static const NWidgetPart _nested_build_tramway_widgets[] = {
|
|||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_TRUCK_STATION),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRUCK_BAY, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION),
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
|
||||
NWidget(WWT_EMPTY, COLOUR_DARK_GREEN, WID_ROT_ONE_WAY), SetMinimalSize(0, 0),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_BRIDGE),
|
||||
SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_TUNNEL),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_CONVERT_ROAD),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_CONVERT_ROAD, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
|
@ -799,7 +854,7 @@ static WindowDesc _build_tramway_desc(
|
|||
WC_BUILD_TOOLBAR, WC_NONE,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_build_tramway_widgets, lengthof(_nested_build_tramway_widgets),
|
||||
&BuildRoadToolbarWindow::hotkeys
|
||||
&BuildRoadToolbarWindow::tram_hotkeys
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -812,16 +867,18 @@ static WindowDesc _build_tramway_desc(
|
|||
Window *ShowBuildRoadToolbar(RoadType roadtype)
|
||||
{
|
||||
if (!Company::IsValidID(_local_company)) return nullptr;
|
||||
_cur_roadtype = roadtype;
|
||||
if (!ValParamRoadType(roadtype)) return nullptr;
|
||||
|
||||
DeleteWindowByClass(WC_BUILD_TOOLBAR);
|
||||
return AllocateWindowDescFront<BuildRoadToolbarWindow>(roadtype == ROADTYPE_ROAD ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
|
||||
_cur_roadtype = roadtype;
|
||||
|
||||
return AllocateWindowDescFront<BuildRoadToolbarWindow>(RoadTypeIsRoad(_cur_roadtype) ? &_build_road_desc : &_build_tramway_desc, TRANSPORT_ROAD);
|
||||
}
|
||||
|
||||
static const NWidgetPart _nested_build_road_scen_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
|
@ -842,6 +899,8 @@ static const NWidgetPart _nested_build_road_scen_widgets[] = {
|
|||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_TUNNEL),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_ROAD),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_CONVERT_ROAD),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_CONVERT_ROAD, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
|
@ -850,17 +909,54 @@ static WindowDesc _build_road_scen_desc(
|
|||
WC_SCEN_BUILD_TOOLBAR, WC_NONE,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_build_road_scen_widgets, lengthof(_nested_build_road_scen_widgets),
|
||||
&BuildRoadToolbarWindow::hotkeys
|
||||
&BuildRoadToolbarWindow::road_hotkeys
|
||||
);
|
||||
|
||||
static const NWidgetPart _nested_build_tramway_scen_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
|
||||
NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetDataTip(STR_WHITE_STRING, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_X),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_X_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_ROAD_Y),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_TRAMWAY_Y_DIR, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_SECTION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_AUTOROAD),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_AUTOTRAM, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEMOLISH),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN, -1), SetMinimalSize(0, 22), SetFill(1, 1), EndContainer(),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_BRIDGE),
|
||||
SetFill(0, 1), SetMinimalSize(43, 22), SetDataTip(SPR_IMG_BRIDGE, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_BRIDGE),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_TUNNEL),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_TUNNEL, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAMWAY_TUNNEL),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_REMOVE),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_REMOVE, STR_ROAD_TOOLBAR_TOOLTIP_TOGGLE_BUILD_REMOVE_FOR_TRAMWAYS),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_CONVERT_ROAD),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_CONVERT_ROAD, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
static WindowDesc _build_tramway_scen_desc(
|
||||
WDP_AUTO, "toolbar_tram_scen", 0, 0,
|
||||
WC_SCEN_BUILD_TOOLBAR, WC_NONE,
|
||||
WDF_CONSTRUCTION,
|
||||
_nested_build_tramway_scen_widgets, lengthof(_nested_build_tramway_scen_widgets),
|
||||
&BuildRoadToolbarWindow::tram_hotkeys
|
||||
);
|
||||
|
||||
/**
|
||||
* Show the road building toolbar in the scenario editor.
|
||||
* @return The just opened toolbar, or \c nullptr if the toolbar was already open.
|
||||
*/
|
||||
Window *ShowBuildRoadScenToolbar()
|
||||
Window *ShowBuildRoadScenToolbar(RoadType roadtype)
|
||||
{
|
||||
_cur_roadtype = ROADTYPE_ROAD;
|
||||
return AllocateWindowDescFront<BuildRoadToolbarWindow>(&_build_road_scen_desc, TRANSPORT_ROAD);
|
||||
DeleteWindowById(WC_SCEN_BUILD_TOOLBAR, TRANSPORT_ROAD);
|
||||
_cur_roadtype = roadtype;
|
||||
|
||||
return AllocateWindowDescFront<BuildRoadToolbarWindow>(RoadTypeIsRoad(_cur_roadtype) ? &_build_road_scen_desc : &_build_tramway_scen_desc, TRANSPORT_ROAD);
|
||||
}
|
||||
|
||||
struct BuildRoadDepotWindow : public PickerWindowBase {
|
||||
|
@ -869,7 +965,7 @@ struct BuildRoadDepotWindow : public PickerWindowBase {
|
|||
this->CreateNestedTree();
|
||||
|
||||
this->LowerWidget(_road_depot_orientation + WID_BROD_DEPOT_NE);
|
||||
if ( _cur_roadtype == ROADTYPE_TRAM) {
|
||||
if (RoadTypeIsTram(_cur_roadtype)) {
|
||||
this->GetWidget<NWidgetCore>(WID_BROD_CAPTION)->widget_data = STR_BUILD_DEPOT_TRAM_ORIENTATION_CAPTION;
|
||||
for (int i = WID_BROD_DEPOT_NE; i <= WID_BROD_DEPOT_NW; i++) this->GetWidget<NWidgetCore>(i)->tool_tip = STR_BUILD_DEPOT_TRAM_ORIENTATION_SELECT_TOOLTIP;
|
||||
}
|
||||
|
@ -960,13 +1056,14 @@ struct BuildRoadStationWindow : public PickerWindowBase {
|
|||
this->CreateNestedTree();
|
||||
|
||||
/* Trams don't have non-drivethrough stations */
|
||||
if (_cur_roadtype == ROADTYPE_TRAM && _road_station_picker_orientation < DIAGDIR_END) {
|
||||
if (RoadTypeIsTram(_cur_roadtype) && _road_station_picker_orientation < DIAGDIR_END) {
|
||||
_road_station_picker_orientation = DIAGDIR_END;
|
||||
}
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(_cur_roadtype);
|
||||
this->GetWidget<NWidgetCore>(WID_BROS_CAPTION)->widget_data = rti->strings.picker_title[rs];
|
||||
|
||||
this->GetWidget<NWidgetCore>(WID_BROS_CAPTION)->widget_data = _road_type_infos[_cur_roadtype].picker_title[rs];
|
||||
for (uint i = (_cur_roadtype == ROADTYPE_TRAM ? WID_BROS_STATION_X : WID_BROS_STATION_NE); i < WID_BROS_LT_OFF; i++) {
|
||||
this->GetWidget<NWidgetCore>(i)->tool_tip = _road_type_infos[_cur_roadtype].picker_tooltip[rs];
|
||||
for (uint i = RoadTypeIsTram(_cur_roadtype) ? WID_BROS_STATION_X : WID_BROS_STATION_NE; i < WID_BROS_LT_OFF; i++) {
|
||||
this->GetWidget<NWidgetCore>(i)->tool_tip = rti->strings.picker_tooltip[rs];
|
||||
}
|
||||
|
||||
this->LowerWidget(_road_station_picker_orientation + WID_BROS_STATION_NE);
|
||||
|
@ -1022,7 +1119,7 @@ struct BuildRoadStationWindow : public PickerWindowBase {
|
|||
if (!IsInsideMM(widget, WID_BROS_STATION_NE, WID_BROS_STATION_Y + 1)) return;
|
||||
|
||||
StationType st = (this->window_class == WC_BUS_STATION) ? STATION_BUS : STATION_TRUCK;
|
||||
StationPickerDrawSprite(r.left + 1 + ScaleGUITrad(31), r.bottom - ScaleGUITrad(31), st, INVALID_RAILTYPE, widget < WID_BROS_STATION_X ? ROADTYPE_ROAD : _cur_roadtype, widget - WID_BROS_STATION_NE);
|
||||
StationPickerDrawSprite(r.left + 1 + ScaleGUITrad(31), r.bottom - ScaleGUITrad(31), st, INVALID_RAILTYPE, _cur_roadtype, widget - WID_BROS_STATION_NE);
|
||||
}
|
||||
|
||||
void OnClick(Point pt, int widget, int click_count) override
|
||||
|
@ -1149,7 +1246,7 @@ static WindowDesc _tram_station_picker_desc(
|
|||
|
||||
static void ShowRVStationPicker(Window *parent, RoadStopType rs)
|
||||
{
|
||||
new BuildRoadStationWindow(_cur_roadtype == ROADTYPE_ROAD ? &_road_station_picker_desc : &_tram_station_picker_desc, parent, rs);
|
||||
new BuildRoadStationWindow(RoadTypeIsRoad(_cur_roadtype) ? &_road_station_picker_desc : &_tram_station_picker_desc, parent, rs);
|
||||
}
|
||||
|
||||
void InitializeRoadGui()
|
||||
|
@ -1157,3 +1254,118 @@ void InitializeRoadGui()
|
|||
_road_depot_orientation = DIAGDIR_NW;
|
||||
_road_station_picker_orientation = DIAGDIR_NW;
|
||||
}
|
||||
|
||||
/**
|
||||
* I really don't know why rail_gui.cpp has this too, shouldn't be included in the other one?
|
||||
*/
|
||||
void InitializeRoadGUI()
|
||||
{
|
||||
BuildRoadToolbarWindow *w = dynamic_cast<BuildRoadToolbarWindow *>(FindWindowById(WC_BUILD_TOOLBAR, TRANSPORT_ROAD));
|
||||
if (w != nullptr) w->ModifyRoadType(_cur_roadtype);
|
||||
}
|
||||
|
||||
DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, bool all_option)
|
||||
{
|
||||
RoadTypes used_roadtypes;
|
||||
RoadTypes avail_roadtypes;
|
||||
|
||||
const Company *c = Company::Get(_local_company);
|
||||
|
||||
/* Find the used roadtypes. */
|
||||
if (for_replacement) {
|
||||
avail_roadtypes = GetCompanyRoadTypes(c->index, false);
|
||||
used_roadtypes = GetRoadTypes(false);
|
||||
} else {
|
||||
avail_roadtypes = c->avail_roadtypes;
|
||||
used_roadtypes = GetRoadTypes(true);
|
||||
}
|
||||
|
||||
/* Filter listed road types */
|
||||
if (!HasBit(rtts, RTT_ROAD)) used_roadtypes &= _roadtypes_type;
|
||||
if (!HasBit(rtts, RTT_TRAM)) used_roadtypes &= ~_roadtypes_type;
|
||||
|
||||
DropDownList list;
|
||||
|
||||
if (all_option) {
|
||||
list.emplace_back(new DropDownListStringItem(STR_REPLACE_ALL_ROADTYPE, INVALID_ROADTYPE, false));
|
||||
}
|
||||
|
||||
Dimension d = { 0, 0 };
|
||||
RoadType rt;
|
||||
/* Get largest icon size, to ensure text is aligned on each menu item. */
|
||||
if (!for_replacement) {
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (!HasBit(used_roadtypes, rt)) continue;
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_road));
|
||||
}
|
||||
}
|
||||
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
/* If it's not used ever, don't show it to the user. */
|
||||
if (!HasBit(used_roadtypes, rt)) continue;
|
||||
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
|
||||
DropDownListParamStringItem *item;
|
||||
if (for_replacement) {
|
||||
item = new DropDownListParamStringItem(rti->strings.replace_text, rt, !HasBit(avail_roadtypes, rt));
|
||||
} else {
|
||||
StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
|
||||
DropDownListIconItem *iconitem = new DropDownListIconItem(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
|
||||
iconitem->SetDimension(d);
|
||||
item = iconitem;
|
||||
}
|
||||
item->SetParam(0, rti->strings.menu_text);
|
||||
item->SetParam(1, rti->max_speed / 2);
|
||||
list.emplace_back(item);
|
||||
}
|
||||
|
||||
if (list.size() == 0) {
|
||||
/* Empty dropdowns are not allowed */
|
||||
list.emplace_back(new DropDownListStringItem(STR_NONE, INVALID_ROADTYPE, true));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts)
|
||||
{
|
||||
RoadTypes avail_roadtypes = GetRoadTypes(false);
|
||||
avail_roadtypes = AddDateIntroducedRoadTypes(avail_roadtypes, _date);
|
||||
RoadTypes used_roadtypes = GetRoadTypes(true);
|
||||
|
||||
/* Filter listed road types */
|
||||
if (!HasBit(rtts, RTT_ROAD)) used_roadtypes &= _roadtypes_type;
|
||||
if (!HasBit(rtts, RTT_TRAM)) used_roadtypes &= ~_roadtypes_type;
|
||||
|
||||
DropDownList list;
|
||||
|
||||
/* If it's not used ever, don't show it to the user. */
|
||||
Dimension d = { 0, 0 };
|
||||
RoadType rt;
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (!HasBit(used_roadtypes, rt)) continue;
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
d = maxdim(d, GetSpriteSize(rti->gui_sprites.build_x_road));
|
||||
}
|
||||
FOR_ALL_SORTED_ROADTYPES(rt) {
|
||||
if (!HasBit(used_roadtypes, rt)) continue;
|
||||
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
|
||||
StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
|
||||
DropDownListIconItem *item = new DropDownListIconItem(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
|
||||
item->SetDimension(d);
|
||||
item->SetParam(0, rti->strings.menu_text);
|
||||
item->SetParam(1, rti->max_speed);
|
||||
list.emplace_back(item);
|
||||
}
|
||||
|
||||
if (list.size() == 0) {
|
||||
/* Empty dropdowns are not allowed */
|
||||
list.emplace_back(new DropDownListStringItem(STR_NONE, -1, true));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,13 @@
|
|||
#include "road_type.h"
|
||||
#include "tile_type.h"
|
||||
#include "direction_type.h"
|
||||
#include "widgets/dropdown_type.h"
|
||||
|
||||
struct Window *ShowBuildRoadToolbar(RoadType roadtype);
|
||||
struct Window *ShowBuildRoadScenToolbar();
|
||||
struct Window *ShowBuildRoadScenToolbar(RoadType roadtype);
|
||||
void ConnectRoadToStructure(TileIndex tile, DiagDirection direction);
|
||||
DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement = false, bool all_option = false);
|
||||
DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts);
|
||||
void InitializeRoadGUI();
|
||||
|
||||
#endif /* ROAD_GUI_H */
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb);
|
||||
|
||||
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadType rt, DoCommandFlag flags, bool town_check = true);
|
||||
CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlag flags, bool town_check = true);
|
||||
|
||||
void DrawRoadCatenary(const TileInfo *ti, RoadBits tram);
|
||||
void DrawRoadCatenary(const TileInfo *ti);
|
||||
|
||||
#endif /* ROAD_INTERNAL_H */
|
||||
|
|
|
@ -32,15 +32,15 @@
|
|||
* @param straight_tunnel_bridge_entrance whether to return straight road bits for tunnels/bridges.
|
||||
* @return the road bits of the given tile
|
||||
*/
|
||||
RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge_entrance)
|
||||
RoadBits GetAnyRoadBits(TileIndex tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance)
|
||||
{
|
||||
if (!HasTileRoadType(tile, rt)) return ROAD_NONE;
|
||||
if (!MayHaveRoad(tile) || !HasTileRoadType(tile, rtt)) return ROAD_NONE;
|
||||
|
||||
switch (GetTileType(tile)) {
|
||||
case MP_ROAD:
|
||||
switch (GetRoadTileType(tile)) {
|
||||
default:
|
||||
case ROAD_TILE_NORMAL: return GetRoadBits(tile, rt);
|
||||
case ROAD_TILE_NORMAL: return GetRoadBits(tile, rtt);
|
||||
case ROAD_TILE_CROSSING: return GetCrossingRoadBits(tile);
|
||||
case ROAD_TILE_DEPOT: return DiagDirToRoadBits(GetRoadDepotDirection(tile));
|
||||
}
|
||||
|
|
263
src/road_map.h
263
src/road_map.h
|
@ -26,6 +26,24 @@ enum RoadTileType {
|
|||
ROAD_TILE_DEPOT, ///< Depot (one entrance)
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a tile can have road/tram types.
|
||||
* @param t Tile to query.
|
||||
* @return true if tile can be queried about road/tram types.
|
||||
*/
|
||||
static inline bool MayHaveRoad(TileIndex t)
|
||||
{
|
||||
switch (GetTileType(t)) {
|
||||
case MP_ROAD:
|
||||
case MP_STATION:
|
||||
case MP_TUNNELBRIDGE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the road tile.
|
||||
* @param t Tile to query.
|
||||
|
@ -108,26 +126,11 @@ static inline bool IsRoadDepotTile(TileIndex t)
|
|||
* @pre IsNormalRoad(t)
|
||||
* @return The present road bits for the road type.
|
||||
*/
|
||||
static inline RoadBits GetRoadBits(TileIndex t, RoadType rt)
|
||||
static inline RoadBits GetRoadBits(TileIndex t, RoadTramType rtt)
|
||||
{
|
||||
assert(IsNormalRoad(t));
|
||||
switch (rt) {
|
||||
default: NOT_REACHED();
|
||||
case ROADTYPE_ROAD: return (RoadBits)GB(_m[t].m5, 0, 4);
|
||||
case ROADTYPE_TRAM: return (RoadBits)GB(_m[t].m3, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all RoadBits set on a tile except from the given RoadType
|
||||
*
|
||||
* @param t The tile from which we want to get the RoadBits
|
||||
* @param rt The RoadType which we exclude from the querry
|
||||
* @return all set RoadBits of the tile which are not from the given RoadType
|
||||
*/
|
||||
static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt)
|
||||
{
|
||||
return GetRoadBits(t, rt == ROADTYPE_ROAD ? ROADTYPE_TRAM : ROADTYPE_ROAD);
|
||||
if (rtt == RTT_TRAM) return (RoadBits)GB(_m[t].m3, 0, 4);
|
||||
return (RoadBits)GB(_m[t].m5, 0, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,7 +141,7 @@ static inline RoadBits GetOtherRoadBits(TileIndex t, RoadType rt)
|
|||
*/
|
||||
static inline RoadBits GetAllRoadBits(TileIndex tile)
|
||||
{
|
||||
return GetRoadBits(tile, ROADTYPE_ROAD) | GetRoadBits(tile, ROADTYPE_TRAM);
|
||||
return GetRoadBits(tile, RTT_ROAD) | GetRoadBits(tile, RTT_TRAM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,96 +151,125 @@ static inline RoadBits GetAllRoadBits(TileIndex tile)
|
|||
* @param rt Road type.
|
||||
* @pre IsNormalRoad(t)
|
||||
*/
|
||||
static inline void SetRoadBits(TileIndex t, RoadBits r, RoadType rt)
|
||||
static inline void SetRoadBits(TileIndex t, RoadBits r, RoadTramType rtt)
|
||||
{
|
||||
assert(IsNormalRoad(t)); // XXX incomplete
|
||||
switch (rt) {
|
||||
default: NOT_REACHED();
|
||||
case ROADTYPE_ROAD: SB(_m[t].m5, 0, 4, r); break;
|
||||
case ROADTYPE_TRAM: SB(_m[t].m3, 0, 4, r); break;
|
||||
if (rtt == RTT_TRAM) {
|
||||
SB(_m[t].m3, 0, 4, r);
|
||||
} else {
|
||||
SB(_m[t].m5, 0, 4, r);
|
||||
}
|
||||
}
|
||||
|
||||
static inline RoadType GetRoadTypeRoad(TileIndex t)
|
||||
{
|
||||
assert(MayHaveRoad(t));
|
||||
return (RoadType)GB(_m[t].m4, 0, 6);
|
||||
}
|
||||
|
||||
static inline RoadType GetRoadTypeTram(TileIndex t)
|
||||
{
|
||||
assert(MayHaveRoad(t));
|
||||
return (RoadType)GB(_me[t].m8, 6, 6);
|
||||
}
|
||||
|
||||
static inline RoadType GetRoadType(TileIndex t, RoadTramType rtt)
|
||||
{
|
||||
return (rtt == RTT_TRAM) ? GetRoadTypeTram(t) : GetRoadTypeRoad(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the present road types of a tile.
|
||||
* @param t The tile to query.
|
||||
* @return Present road types.
|
||||
*/
|
||||
static inline RoadTypes GetRoadTypes(TileIndex t)
|
||||
static inline RoadTypes GetPresentRoadTypes(TileIndex t)
|
||||
{
|
||||
return (RoadTypes)GB(_me[t].m7, 6, 2);
|
||||
RoadTypes result = ROADTYPES_NONE;
|
||||
if (MayHaveRoad(t)) {
|
||||
if (GetRoadTypeRoad(t) != INVALID_ROADTYPE) SetBit(result, GetRoadTypeRoad(t));
|
||||
if (GetRoadTypeTram(t) != INVALID_ROADTYPE) SetBit(result, GetRoadTypeTram(t));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool HasRoadTypeRoad(TileIndex t)
|
||||
{
|
||||
return GetRoadTypeRoad(t) != INVALID_ROADTYPE;
|
||||
}
|
||||
|
||||
static inline bool HasRoadTypeTram(TileIndex t)
|
||||
{
|
||||
return GetRoadTypeTram(t) != INVALID_ROADTYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the present road types of a tile.
|
||||
* @param t The tile to change.
|
||||
* @param rt The new road types.
|
||||
*/
|
||||
static inline void SetRoadTypes(TileIndex t, RoadTypes rt)
|
||||
{
|
||||
assert(IsTileType(t, MP_ROAD) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
|
||||
SB(_me[t].m7, 6, 2, rt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tile has a specific road type.
|
||||
* Check if a tile has a road or a tram road type.
|
||||
* @param t The tile to check.
|
||||
* @param rt Road type to check.
|
||||
* @param tram True to check tram, false to check road.
|
||||
* @return True if the tile has the specified road type.
|
||||
*/
|
||||
static inline bool HasTileRoadType(TileIndex t, RoadType rt)
|
||||
static inline bool HasTileRoadType(TileIndex t, RoadTramType rtt)
|
||||
{
|
||||
return HasBit(GetRoadTypes(t), rt);
|
||||
return GetRoadType(t, rtt) != INVALID_ROADTYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tile has one of the specified road types.
|
||||
* @param t The tile to check.
|
||||
* @param rts Allowed road types.
|
||||
* @return True if the tile has one of the specified road types.
|
||||
*/
|
||||
static inline bool HasTileAnyRoadType(TileIndex t, RoadTypes rts)
|
||||
{
|
||||
if (!MayHaveRoad(t)) return false;
|
||||
return (GetPresentRoadTypes(t) & rts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner of a specific road type.
|
||||
* @param t The tile to query.
|
||||
* @param rt The road type to get the owner of.
|
||||
* @param rtt RoadTramType.
|
||||
* @return Owner of the given road type.
|
||||
*/
|
||||
static inline Owner GetRoadOwner(TileIndex t, RoadType rt)
|
||||
static inline Owner GetRoadOwner(TileIndex t, RoadTramType rtt)
|
||||
{
|
||||
assert(IsTileType(t, MP_ROAD) || IsTileType(t, MP_STATION) || IsTileType(t, MP_TUNNELBRIDGE));
|
||||
switch (rt) {
|
||||
default: NOT_REACHED();
|
||||
case ROADTYPE_ROAD: return (Owner)GB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5);
|
||||
case ROADTYPE_TRAM: {
|
||||
/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
|
||||
* to OWNER_TOWN makes it use one bit less */
|
||||
Owner o = (Owner)GB(_m[t].m3, 4, 4);
|
||||
return o == OWNER_TOWN ? OWNER_NONE : o;
|
||||
}
|
||||
}
|
||||
assert(MayHaveRoad(t));
|
||||
if (rtt == RTT_ROAD) return (Owner)GB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5);
|
||||
|
||||
/* Trams don't need OWNER_TOWN, and remapping OWNER_NONE
|
||||
* to OWNER_TOWN makes it use one bit less */
|
||||
Owner o = (Owner)GB(_m[t].m3, 4, 4);
|
||||
return o == OWNER_TOWN ? OWNER_NONE : o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the owner of a specific road type.
|
||||
* @param t The tile to change.
|
||||
* @param rt The road type to change the owner of.
|
||||
* @param rtt RoadTramType.
|
||||
* @param o New owner of the given road type.
|
||||
*/
|
||||
static inline void SetRoadOwner(TileIndex t, RoadType rt, Owner o)
|
||||
static inline void SetRoadOwner(TileIndex t, RoadTramType rtt, Owner o)
|
||||
{
|
||||
switch (rt) {
|
||||
default: NOT_REACHED();
|
||||
case ROADTYPE_ROAD: SB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5, o); break;
|
||||
case ROADTYPE_TRAM: SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o); break;
|
||||
if (rtt == RTT_ROAD) {
|
||||
SB(IsNormalRoadTile(t) ? _m[t].m1 : _me[t].m7, 0, 5, o);
|
||||
} else {
|
||||
SB(_m[t].m3, 4, 4, o == OWNER_NONE ? OWNER_TOWN : o);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a specific road type is owned by an owner.
|
||||
* @param t The tile to query.
|
||||
* @param rt The road type to compare the owner of.
|
||||
* @param tram True to check tram, false to check road.
|
||||
* @param o Owner to compare with.
|
||||
* @pre HasTileRoadType(t, rt)
|
||||
* @return True if the road type is owned by the given owner.
|
||||
*/
|
||||
static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o)
|
||||
static inline bool IsRoadOwner(TileIndex t, RoadTramType rtt, Owner o)
|
||||
{
|
||||
assert(HasTileRoadType(t, rt));
|
||||
return (GetRoadOwner(t, rt) == o);
|
||||
assert(HasTileRoadType(t, rtt));
|
||||
return (GetRoadOwner(t, rtt) == o);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,7 +280,7 @@ static inline bool IsRoadOwner(TileIndex t, RoadType rt, Owner o)
|
|||
*/
|
||||
static inline bool HasTownOwnedRoad(TileIndex t)
|
||||
{
|
||||
return HasTileRoadType(t, ROADTYPE_ROAD) && IsRoadOwner(t, ROADTYPE_ROAD, OWNER_TOWN);
|
||||
return HasTileRoadType(t, RTT_ROAD) && IsRoadOwner(t, RTT_ROAD, OWNER_TOWN);
|
||||
}
|
||||
|
||||
/** Which directions are disallowed ? */
|
||||
|
@ -539,29 +571,80 @@ static inline DiagDirection GetRoadDepotDirection(TileIndex t)
|
|||
}
|
||||
|
||||
|
||||
RoadBits GetAnyRoadBits(TileIndex tile, RoadType rt, bool straight_tunnel_bridge_entrance = false);
|
||||
RoadBits GetAnyRoadBits(TileIndex tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance = false);
|
||||
|
||||
/**
|
||||
* Set the road road type of a tile.
|
||||
* @param t The tile to change.
|
||||
* @param rt The road type to set.
|
||||
*/
|
||||
static inline void SetRoadTypeRoad(TileIndex t, RoadType rt)
|
||||
{
|
||||
assert(MayHaveRoad(t));
|
||||
assert(rt == INVALID_ROADTYPE || RoadTypeIsRoad(rt));
|
||||
SB(_m[t].m4, 0, 6, rt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tram road type of a tile.
|
||||
* @param t The tile to change.
|
||||
* @param rt The road type to set.
|
||||
*/
|
||||
static inline void SetRoadTypeTram(TileIndex t, RoadType rt)
|
||||
{
|
||||
assert(MayHaveRoad(t));
|
||||
assert(rt == INVALID_ROADTYPE || RoadTypeIsTram(rt));
|
||||
SB(_me[t].m8, 6, 6, rt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the road type of a tile.
|
||||
* @param t The tile to change.
|
||||
* @param rtt Set road or tram type.
|
||||
* @param rt The road type to set.
|
||||
*/
|
||||
static inline void SetRoadType(TileIndex t, RoadTramType rtt, RoadType rt)
|
||||
{
|
||||
if (rtt == RTT_TRAM) {
|
||||
SetRoadTypeTram(t, rt);
|
||||
} else {
|
||||
SetRoadTypeRoad(t, rt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the present road types of a tile.
|
||||
* @param t The tile to change.
|
||||
* @param road_rt The road roadtype to set for the tile.
|
||||
* @param tram_rt The tram roadtype to set for the tile.
|
||||
*/
|
||||
static inline void SetRoadTypes(TileIndex t, RoadType road_rt, RoadType tram_rt)
|
||||
{
|
||||
SetRoadTypeRoad(t, road_rt);
|
||||
SetRoadTypeTram(t, tram_rt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a normal road tile.
|
||||
* @param t Tile to make a normal road.
|
||||
* @param bits Road bits to set for all present road types.
|
||||
* @param rot New present road types.
|
||||
* @param town Town ID if the road is a town-owned road.
|
||||
* @param road New owner of road.
|
||||
* @param tram New owner of tram tracks.
|
||||
* @param t Tile to make a normal road.
|
||||
* @param bits Road bits to set for all present road types.
|
||||
* @param road_rt The road roadtype to set for the tile.
|
||||
* @param tram_rt The tram roadtype to set for the tile.
|
||||
* @param town Town ID if the road is a town-owned road.
|
||||
* @param road New owner of road.
|
||||
* @param tram New owner of tram tracks.
|
||||
*/
|
||||
static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, TownID town, Owner road, Owner tram)
|
||||
static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram)
|
||||
{
|
||||
SetTileType(t, MP_ROAD);
|
||||
SetTileOwner(t, road);
|
||||
_m[t].m2 = town;
|
||||
_m[t].m3 = (HasBit(rot, ROADTYPE_TRAM) ? bits : 0);
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m5 = (HasBit(rot, ROADTYPE_ROAD) ? bits : 0) | ROAD_TILE_NORMAL << 6;
|
||||
_m[t].m3 = (tram_rt != INVALID_ROADTYPE ? bits : 0);
|
||||
_m[t].m5 = (road_rt != INVALID_ROADTYPE ? bits : 0) | ROAD_TILE_NORMAL << 6;
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
_me[t].m7 = rot << 6;
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, tram);
|
||||
_me[t].m7 = 0;
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SetRoadOwner(t, RTT_TRAM, tram);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -572,21 +655,23 @@ static inline void MakeRoadNormal(TileIndex t, RoadBits bits, RoadTypes rot, Tow
|
|||
* @param rail New owner of the rail track.
|
||||
* @param roaddir Axis of the road.
|
||||
* @param rat New rail type.
|
||||
* @param rot New present road types.
|
||||
* @param road_rt The road roadtype to set for the tile.
|
||||
* @param tram_rt The tram roadtype to set for the tile.
|
||||
* @param town Town ID if the road is a town-owned road.
|
||||
*/
|
||||
static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadTypes rot, uint town)
|
||||
static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, uint town)
|
||||
{
|
||||
SetTileType(t, MP_ROAD);
|
||||
SetTileOwner(t, rail);
|
||||
_m[t].m2 = town;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m4 = INVALID_ROADTYPE;
|
||||
_m[t].m5 = ROAD_TILE_CROSSING << 6 | roaddir;
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
_me[t].m7 = rot << 6 | road;
|
||||
_me[t].m8 = rat;
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, tram);
|
||||
_me[t].m7 = road;
|
||||
_me[t].m8 = INVALID_ROADTYPE << 6 | rat;
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SetRoadOwner(t, RTT_TRAM, tram);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -594,7 +679,7 @@ static inline void MakeRoadCrossing(TileIndex t, Owner road, Owner tram, Owner r
|
|||
* @param t Tile to make a level crossing.
|
||||
* @param owner New owner of the depot.
|
||||
* @param did New depot ID.
|
||||
* @param dir Direction of the depot exit.
|
||||
* @param dir Direction of the depot exit.*
|
||||
* @param rt Road type of the depot.
|
||||
*/
|
||||
static inline void MakeRoadDepot(TileIndex t, Owner owner, DepotID did, DiagDirection dir, RoadType rt)
|
||||
|
@ -603,11 +688,13 @@ static inline void MakeRoadDepot(TileIndex t, Owner owner, DepotID did, DiagDire
|
|||
SetTileOwner(t, owner);
|
||||
_m[t].m2 = did;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m4 = 0;
|
||||
_m[t].m4 = INVALID_ROADTYPE;
|
||||
_m[t].m5 = ROAD_TILE_DEPOT << 6 | dir;
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
_me[t].m7 = RoadTypeToRoadTypes(rt) << 6 | owner;
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, owner);
|
||||
_me[t].m7 = owner;
|
||||
_me[t].m8 = INVALID_ROADTYPE << 6;
|
||||
SetRoadType(t, GetRoadTramType(rt), rt);
|
||||
SetRoadOwner(t, RTT_TRAM, owner);
|
||||
}
|
||||
|
||||
#endif /* ROAD_MAP_H */
|
||||
|
|
|
@ -14,36 +14,37 @@
|
|||
|
||||
#include "core/enum_type.hpp"
|
||||
|
||||
typedef uint32 RoadTypeLabel;
|
||||
|
||||
static const RoadTypeLabel ROADTYPE_ROAD_LABEL = 'ROAD';
|
||||
static const RoadTypeLabel ROADTYPE_TRAM_LABEL = 'TRAM';
|
||||
|
||||
/**
|
||||
* The different roadtypes we support
|
||||
*
|
||||
* @note currently only ROADTYPE_ROAD and ROADTYPE_TRAM are supported.
|
||||
*/
|
||||
enum RoadType {
|
||||
ROADTYPE_BEGIN = 0, ///< Used for iterations
|
||||
ROADTYPE_ROAD = 0, ///< Basic road type
|
||||
ROADTYPE_TRAM = 1, ///< Trams
|
||||
ROADTYPE_END, ///< Used for iterations
|
||||
INVALID_ROADTYPE = 0xFF, ///< flag for invalid roadtype
|
||||
ROADTYPE_BEGIN = 0, ///< Used for iterations
|
||||
ROADTYPE_ROAD = 0, ///< Basic road type
|
||||
ROADTYPE_TRAM = 1, ///< Trams
|
||||
ROADTYPE_END = 63, ///< Used for iterations
|
||||
INVALID_ROADTYPE = 63, ///< flag for invalid roadtype
|
||||
};
|
||||
DECLARE_POSTFIX_INCREMENT(RoadType)
|
||||
template <> struct EnumPropsT<RoadType> : MakeEnumPropsT<RoadType, byte, ROADTYPE_BEGIN, ROADTYPE_END, INVALID_ROADTYPE, 2> {};
|
||||
template <> struct EnumPropsT<RoadType> : MakeEnumPropsT<RoadType, byte, ROADTYPE_BEGIN, ROADTYPE_END, INVALID_ROADTYPE, 6> {};
|
||||
|
||||
/**
|
||||
* The different roadtypes we support, but then a bitmask of them
|
||||
* @note currently only roadtypes with ROADTYPE_ROAD and ROADTYPE_TRAM are supported.
|
||||
* The different roadtypes we support, but then a bitmask of them.
|
||||
* @note Must be treated as a uint64 type, narrowing it causes bit membership tests to give wrong results.
|
||||
*/
|
||||
enum RoadTypes : byte {
|
||||
enum RoadTypes : uint64 {
|
||||
ROADTYPES_NONE = 0, ///< No roadtypes
|
||||
ROADTYPES_ROAD = 1 << ROADTYPE_ROAD, ///< Road
|
||||
ROADTYPES_TRAM = 1 << ROADTYPE_TRAM, ///< Trams
|
||||
ROADTYPES_ALL = ROADTYPES_ROAD | ROADTYPES_TRAM, ///< Road + trams
|
||||
ROADTYPES_END, ///< Used for iterations?
|
||||
INVALID_ROADTYPES = 0xFF, ///< Invalid roadtypes
|
||||
INVALID_ROADTYPES = UINT64_MAX, ///< Invalid roadtypes
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadTypes)
|
||||
template <> struct EnumPropsT<RoadTypes> : MakeEnumPropsT<RoadTypes, byte, ROADTYPES_NONE, ROADTYPES_END, INVALID_ROADTYPES, 2> {};
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration for the road parts on a tile.
|
||||
|
|
|
@ -45,7 +45,7 @@ RoadStop *RoadStop::GetNextRoadStop(const RoadVehicle *v) const
|
|||
{
|
||||
for (RoadStop *rs = this->next; rs != nullptr; rs = rs->next) {
|
||||
/* The vehicle cannot go to this roadstop (different roadtype) */
|
||||
if ((GetRoadTypes(rs->xy) & v->compatible_roadtypes) == ROADTYPES_NONE) continue;
|
||||
if (!HasTileAnyRoadType(rs->xy, v->compatible_roadtypes)) continue;
|
||||
/* The vehicle is articulated and can therefore not go to a standard road stop. */
|
||||
if (IsStandardRoadStopTile(rs->xy) && v->HasArticulatedPart()) continue;
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
#include "engine_base.h"
|
||||
#include "cargotype.h"
|
||||
#include "track_func.h"
|
||||
#include "road_type.h"
|
||||
#include "road.h"
|
||||
#include "road_map.h"
|
||||
#include "newgrf_engine.h"
|
||||
#include <deque>
|
||||
|
||||
|
@ -115,8 +116,8 @@ struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
|
|||
uint16 crashed_ctr; ///< Animation counter when the vehicle has crashed. @see RoadVehIsCrashed
|
||||
byte reverse_ctr;
|
||||
|
||||
RoadType roadtype;
|
||||
RoadTypes compatible_roadtypes;
|
||||
RoadType roadtype; //!< Roadtype of this vehicle.
|
||||
RoadTypes compatible_roadtypes; //!< Roadtypes this consist is powered on.
|
||||
|
||||
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
||||
RoadVehicle() : GroundVehicleBase() {}
|
||||
|
@ -244,7 +245,7 @@ protected: // These functions should not be called outside acceleration code.
|
|||
{
|
||||
/* Trams have a slightly greater friction coefficient than trains.
|
||||
* The rest of road vehicles have bigger values. */
|
||||
uint32 coeff = (this->roadtype == ROADTYPE_TRAM) ? 40 : 75;
|
||||
uint32 coeff = RoadTypeIsTram(this->roadtype) ? 40 : 75;
|
||||
/* The friction coefficient increases with speed in a way that
|
||||
* it doubles at 128 km/h, triples at 256 km/h and so on. */
|
||||
return coeff * (128 + this->GetCurrentSpeed()) / 128;
|
||||
|
@ -274,7 +275,7 @@ protected: // These functions should not be called outside acceleration code.
|
|||
*/
|
||||
inline uint16 GetMaxTrackSpeed() const
|
||||
{
|
||||
return 0;
|
||||
return GetRoadTypeInfo(GetRoadType(this->tile, GetRoadTramType(this->roadtype)))->max_speed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -283,7 +284,7 @@ protected: // These functions should not be called outside acceleration code.
|
|||
*/
|
||||
inline bool TileMayHaveSlopedTrack() const
|
||||
{
|
||||
TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, this->compatible_roadtypes);
|
||||
TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, GetRoadTramType(this->roadtype));
|
||||
TrackBits trackbits = TrackStatusToTrackBits(ts);
|
||||
|
||||
return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
|
||||
|
|
|
@ -260,7 +260,10 @@ void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
|
|||
*/
|
||||
CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
|
||||
{
|
||||
if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
|
||||
/* Check that the vehicle can drive on the road in question */
|
||||
RoadType rt = e->u.road.roadtype;
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
if (!HasTileAnyRoadType(tile, rti->powered_roadtypes)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
const RoadVehicleInfo *rvi = &e->u.road;
|
||||
|
@ -304,8 +307,8 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
|
|||
v->random_bits = VehicleRandomBits();
|
||||
v->SetFrontEngine();
|
||||
|
||||
v->roadtype = HasBit(e->info.misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
|
||||
v->compatible_roadtypes = RoadTypeToRoadTypes(v->roadtype);
|
||||
v->roadtype = rt;
|
||||
v->compatible_roadtypes = rti->powered_roadtypes;
|
||||
v->gcache.cached_veh_length = VEHICLE_LENGTH;
|
||||
|
||||
if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
|
||||
|
@ -437,16 +440,16 @@ void RoadVehicle::UpdateDeltaXY()
|
|||
*/
|
||||
inline int RoadVehicle::GetCurrentMaxSpeed() const
|
||||
{
|
||||
int max_speed = this->vcache.cached_max_speed;
|
||||
int max_speed = this->gcache.cached_max_track_speed;
|
||||
|
||||
/* Limit speed to 50% while reversing, 75% in curves. */
|
||||
for (const RoadVehicle *u = this; u != nullptr; u = u->Next()) {
|
||||
if (_settings_game.vehicle.roadveh_acceleration_model == AM_REALISTIC) {
|
||||
if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)this->state)) {
|
||||
max_speed = this->vcache.cached_max_speed / 2;
|
||||
max_speed = this->gcache.cached_max_track_speed / 2;
|
||||
break;
|
||||
} else if ((u->direction & 1) == 0) {
|
||||
max_speed = this->vcache.cached_max_speed * 3 / 4;
|
||||
max_speed = this->gcache.cached_max_track_speed * 3 / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -691,7 +694,7 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
|
|||
st->had_vehicle_of_type |= HVOT_BUS;
|
||||
SetDParam(0, st->index);
|
||||
AddVehicleNewsItem(
|
||||
v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
|
||||
RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_BUS_ARRIVAL : STR_NEWS_FIRST_PASSENGER_TRAM_ARRIVAL,
|
||||
(v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER,
|
||||
v->index,
|
||||
st->index
|
||||
|
@ -705,7 +708,7 @@ static void RoadVehArrivesAt(const RoadVehicle *v, Station *st)
|
|||
st->had_vehicle_of_type |= HVOT_TRUCK;
|
||||
SetDParam(0, st->index);
|
||||
AddVehicleNewsItem(
|
||||
v->roadtype == ROADTYPE_ROAD ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
|
||||
RoadTypeIsRoad(v->roadtype) ? STR_NEWS_FIRST_TRUCK_ARRIVAL : STR_NEWS_FIRST_CARGO_TRAM_ARRIVAL,
|
||||
(v->owner == _local_company) ? NT_ARRIVAL_COMPANY : NT_ARRIVAL_OTHER,
|
||||
v->index,
|
||||
st->index
|
||||
|
@ -783,7 +786,8 @@ static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
|
|||
*/
|
||||
static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
|
||||
{
|
||||
TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, od->v->compatible_roadtypes);
|
||||
if (!HasTileAnyRoadType(od->tile, od->v->compatible_roadtypes)) return true;
|
||||
TrackStatus ts = GetTileTrackStatus(od->tile, TRANSPORT_ROAD, GetRoadTramType(od->v->roadtype));
|
||||
TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
|
||||
TrackdirBits red_signals = TrackStatusToRedSignals(ts); // barred level crossing
|
||||
TrackBits trackbits = TrackdirBitsToTrackBits(trackdirbits);
|
||||
|
@ -803,7 +807,7 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
|||
od.u = u;
|
||||
|
||||
/* Trams can't overtake other trams */
|
||||
if (v->roadtype == ROADTYPE_TRAM) return;
|
||||
if (RoadTypeIsTram(v->roadtype)) return;
|
||||
|
||||
/* Don't overtake in stations */
|
||||
if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
|
||||
|
@ -855,7 +859,7 @@ static void RoadZPosAffectSpeed(RoadVehicle *v, int old_z)
|
|||
v->cur_speed = v->cur_speed * 232 / 256; // slow down by ~10%
|
||||
} else {
|
||||
uint16 spd = v->cur_speed + 2;
|
||||
if (spd <= v->vcache.cached_max_speed) v->cur_speed = spd;
|
||||
if (spd <= v->gcache.cached_max_track_speed) v->cur_speed = spd;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,12 +888,12 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
|
|||
Trackdir best_track;
|
||||
bool path_found = true;
|
||||
|
||||
TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, v->compatible_roadtypes);
|
||||
TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype));
|
||||
TrackdirBits red_signals = TrackStatusToRedSignals(ts); // crossing
|
||||
TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
|
||||
|
||||
if (IsTileType(tile, MP_ROAD)) {
|
||||
if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
|
||||
if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) {
|
||||
/* Road depot owned by another company or with the wrong orientation */
|
||||
trackdirs = TRACKDIR_BIT_NONE;
|
||||
}
|
||||
|
@ -932,10 +936,10 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
|
|||
|
||||
if (v->reverse_ctr != 0) {
|
||||
bool reverse = true;
|
||||
if (v->roadtype == ROADTYPE_TRAM) {
|
||||
if (RoadTypeIsTram(v->roadtype)) {
|
||||
/* Trams may only reverse on a tile if it contains at least the straight
|
||||
* trackbits or when it is a valid turning tile (i.e. one roadbit) */
|
||||
RoadBits rb = GetAnyRoadBits(tile, ROADTYPE_TRAM);
|
||||
RoadBits rb = GetAnyRoadBits(tile, RTT_TRAM);
|
||||
RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir));
|
||||
reverse = ((rb & straight) == straight) ||
|
||||
(rb == DiagDirToRoadBits(enterdir));
|
||||
|
@ -1014,7 +1018,7 @@ static bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
|
|||
v->direction = DiagDirToDir(dir);
|
||||
|
||||
Trackdir tdir = DiagDirToDiagTrackdir(dir);
|
||||
const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
|
||||
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
|
||||
|
||||
int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
|
||||
int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
|
||||
|
@ -1109,7 +1113,7 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
|
|||
};
|
||||
RoadBits required = required_roadbits[dir & 0x07];
|
||||
|
||||
if ((required & GetAnyRoadBits(tile, v->roadtype, true)) == ROAD_NONE) {
|
||||
if ((required & GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true)) == ROAD_NONE) {
|
||||
dir = INVALID_TRACKDIR;
|
||||
}
|
||||
|
||||
|
@ -1120,15 +1124,16 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
|
|||
* Can a tram track build without destruction on the given tile?
|
||||
* @param c the company that would be building the tram tracks
|
||||
* @param t the tile to build on.
|
||||
* @param rt the tram type to build.
|
||||
* @param r the road bits needed.
|
||||
* @return true when a track track can be build on 't'
|
||||
*/
|
||||
static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
|
||||
static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadType rt, RoadBits r)
|
||||
{
|
||||
/* The 'current' company is not necessarily the owner of the vehicle. */
|
||||
Backup<CompanyID> cur_company(_current_company, c, FILE_LINE);
|
||||
|
||||
CommandCost ret = DoCommand(t, ROADTYPE_TRAM << 4 | r, 0, DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
CommandCost ret = DoCommand(t, rt << 4 | r, 0, DC_NO_WATER, CMD_BUILD_ROAD);
|
||||
|
||||
cur_company.Restore();
|
||||
return ret.Succeeded();
|
||||
|
@ -1186,7 +1191,7 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
|||
/* Get move position data for next frame.
|
||||
* For a drive-through road stop use 'straight road' move data.
|
||||
* In this case v->state is masked to give the road stop entry direction. */
|
||||
RoadDriveEntry rd = _road_drive_data[v->roadtype][(
|
||||
RoadDriveEntry rd = _road_drive_data[GetRoadTramType(v->roadtype)][(
|
||||
(HasBit(v->state, RVS_IN_DT_ROAD_STOP) ? v->state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->state) +
|
||||
(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
|
||||
|
||||
|
@ -1196,7 +1201,11 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
|||
|
||||
if (v->IsFrontEngine()) {
|
||||
/* If this is the front engine, look for the right path. */
|
||||
dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
|
||||
if (HasTileAnyRoadType(tile, v->compatible_roadtypes)) {
|
||||
dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
|
||||
} else {
|
||||
dir = _road_reverse_table[(DiagDirection)(rd.x & 3)];
|
||||
}
|
||||
} else {
|
||||
dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
|
||||
}
|
||||
|
@ -1214,7 +1223,7 @@ again:
|
|||
v->overtaking = 0;
|
||||
|
||||
/* Turning around */
|
||||
if (v->roadtype == ROADTYPE_TRAM) {
|
||||
if (RoadTypeIsTram(v->roadtype)) {
|
||||
/* Determine the road bits the tram needs to be able to turn around
|
||||
* using the 'big' corner loop. */
|
||||
RoadBits needed;
|
||||
|
@ -1227,7 +1236,8 @@ again:
|
|||
}
|
||||
if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
|
||||
(v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
|
||||
(needed & GetRoadBits(tile, ROADTYPE_TRAM)) != ROAD_NONE)) {
|
||||
HasTileAnyRoadType(tile, v->compatible_roadtypes) &&
|
||||
(needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
|
||||
/*
|
||||
* Taking the 'big' corner for trams only happens when:
|
||||
* - The previous vehicle in this (articulated) tram chain is
|
||||
|
@ -1238,7 +1248,7 @@ again:
|
|||
* going to cause the tram to split up.
|
||||
* - Or the front of the tram can drive over the next tile.
|
||||
*/
|
||||
} else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, needed) || ((~needed & GetAnyRoadBits(v->tile, ROADTYPE_TRAM, false)) == ROAD_NONE)) {
|
||||
} else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
|
||||
/*
|
||||
* Taking the 'small' corner for trams only happens when:
|
||||
* - We are not the from vehicle of an articulated tram.
|
||||
|
@ -1266,7 +1276,7 @@ again:
|
|||
}
|
||||
|
||||
/* Get position data for first frame on the new tile */
|
||||
const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
|
||||
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(dir + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking];
|
||||
|
||||
int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
|
||||
int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
|
||||
|
@ -1318,9 +1328,18 @@ again:
|
|||
}
|
||||
|
||||
if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
|
||||
TileIndex old_tile = v->tile;
|
||||
|
||||
v->tile = tile;
|
||||
v->state = (byte)dir;
|
||||
v->frame = start_frame;
|
||||
RoadTramType rtt = GetRoadTramType(v->roadtype);
|
||||
if (GetRoadType(old_tile, rtt) != GetRoadType(tile, rtt)) {
|
||||
if (v->IsFrontEngine()) {
|
||||
RoadVehUpdateCache(v);
|
||||
}
|
||||
v->First()->CargoChanged();
|
||||
}
|
||||
}
|
||||
if (new_dir != v->direction) {
|
||||
v->direction = new_dir;
|
||||
|
@ -1338,7 +1357,7 @@ again:
|
|||
Trackdir dir;
|
||||
uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
|
||||
|
||||
if (v->roadtype == ROADTYPE_TRAM && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, ROADTYPE_TRAM, true))) {
|
||||
if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
|
||||
/*
|
||||
* The tram is turning around with one tram 'roadbit'. This means that
|
||||
* it is using the 'big' corner 'drive data'. However, to support the
|
||||
|
@ -1370,7 +1389,7 @@ again:
|
|||
return false;
|
||||
}
|
||||
|
||||
const RoadDriveEntry *rdp = _road_drive_data[v->roadtype][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
|
||||
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + dir];
|
||||
|
||||
int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
|
||||
int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
|
||||
|
@ -1478,7 +1497,7 @@ again:
|
|||
TileIndex next_tile = TileAddByDir(v->tile, v->direction);
|
||||
|
||||
/* Check if next inline bay is free and has compatible road. */
|
||||
if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile) && (GetRoadTypes(next_tile) & v->compatible_roadtypes) != 0) {
|
||||
if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile) && HasTileAnyRoadType(next_tile, v->compatible_roadtypes)) {
|
||||
v->frame++;
|
||||
v->x_pos = x;
|
||||
v->y_pos = y;
|
||||
|
|
|
@ -282,6 +282,12 @@ static void InitializeWindowsAndCaches()
|
|||
(*it)->tile = t->xy;
|
||||
}
|
||||
}
|
||||
RoadVehicle *rv;
|
||||
FOR_ALL_ROADVEHICLES(rv) {
|
||||
if (rv->IsFrontEngine()) {
|
||||
rv->CargoChanged();
|
||||
}
|
||||
}
|
||||
|
||||
RecomputePrices();
|
||||
|
||||
|
@ -461,8 +467,19 @@ static void FixOwnerOfRailTrack(TileIndex t)
|
|||
|
||||
if (IsLevelCrossingTile(t)) {
|
||||
/* else change the crossing to normal road (road vehicles won't care) */
|
||||
MakeRoadNormal(t, GetCrossingRoadBits(t), GetRoadTypes(t), GetTownIndex(t),
|
||||
GetRoadOwner(t, ROADTYPE_ROAD), GetRoadOwner(t, ROADTYPE_TRAM));
|
||||
Owner road = GetRoadOwner(t, RTT_ROAD);
|
||||
Owner tram = GetRoadOwner(t, RTT_TRAM);
|
||||
RoadBits bits = GetCrossingRoadBits(t);
|
||||
bool hasroad = HasBit(_me[t].m7, 6);
|
||||
bool hastram = HasBit(_me[t].m7, 7);
|
||||
|
||||
/* MakeRoadNormal */
|
||||
SetTileType(t, MP_ROAD);
|
||||
SetTileOwner(t, road);
|
||||
_m[t].m3 = (hasroad ? bits : 0);
|
||||
_m[t].m5 = (hastram ? bits : 0) | ROAD_TILE_NORMAL << 6;
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
SetRoadOwner(t, RTT_TRAM, tram);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1052,18 +1069,18 @@ bool AfterLoadGame()
|
|||
break;
|
||||
case ROAD_TILE_DEPOT: break;
|
||||
}
|
||||
SetRoadTypes(t, ROADTYPES_ROAD);
|
||||
SB(_me[t].m7, 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
if (IsRoadStop(t)) SetRoadTypes(t, ROADTYPES_ROAD);
|
||||
if (IsRoadStop(t)) SB(_me[t].m7, 6, 2, 1);
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
/* Middle part of "old" bridges */
|
||||
if (old_bridge && IsBridge(t) && HasBit(_m[t].m5, 6)) break;
|
||||
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
||||
SetRoadTypes(t, ROADTYPES_ROAD);
|
||||
SB(_me[t].m7, 6, 2, 1); // Set pre-NRT road type bits for conversion later.
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1079,7 +1096,7 @@ bool AfterLoadGame()
|
|||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
switch (GetTileType(t)) {
|
||||
case MP_ROAD:
|
||||
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_me[t].m7, 5, 3));
|
||||
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_me[t].m7, 5, 3));
|
||||
SB(_me[t].m7, 5, 1, GB(_m[t].m3, 7, 1)); // snow/desert
|
||||
switch (GetRoadTileType(t)) {
|
||||
default: SlErrorCorrupt("Invalid road tile type");
|
||||
|
@ -1112,7 +1129,7 @@ bool AfterLoadGame()
|
|||
case MP_STATION:
|
||||
if (!IsRoadStop(t)) break;
|
||||
|
||||
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
|
||||
SB(_m[t].m3, 4, 4, _m[t].m1);
|
||||
_m[t].m4 = 0;
|
||||
|
@ -1121,7 +1138,7 @@ bool AfterLoadGame()
|
|||
case MP_TUNNELBRIDGE:
|
||||
if (old_bridge && IsBridge(t) && HasBit(_m[t].m5, 6)) break;
|
||||
if (((old_bridge && IsBridge(t)) ? (TransportType)GB(_m[t].m5, 1, 2) : GetTunnelBridgeTransportType(t)) == TRANSPORT_ROAD) {
|
||||
if (fix_roadtypes) SetRoadTypes(t, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
|
||||
Owner o = GetTileOwner(t);
|
||||
SB(_me[t].m7, 0, 5, o); // road owner
|
||||
|
@ -1191,13 +1208,14 @@ bool AfterLoadGame()
|
|||
} else {
|
||||
TownID town = IsTileOwner(t, OWNER_TOWN) ? ClosestTownFromTile(t, UINT_MAX)->index : 0;
|
||||
|
||||
MakeRoadNormal(
|
||||
t,
|
||||
axis == AXIS_X ? ROAD_Y : ROAD_X,
|
||||
ROADTYPES_ROAD,
|
||||
town,
|
||||
GetTileOwner(t), OWNER_NONE
|
||||
);
|
||||
/* MakeRoadNormal */
|
||||
SetTileType(t, MP_ROAD);
|
||||
_m[t].m2 = town;
|
||||
_m[t].m3 = 0;
|
||||
_m[t].m5 = (axis == AXIS_X ? ROAD_Y : ROAD_X) | ROAD_TILE_NORMAL << 6;
|
||||
SB(_me[t].m6, 2, 4, 0);
|
||||
_me[t].m7 = 1 << 6;
|
||||
SetRoadOwner(t, RTT_TRAM, OWNER_NONE);
|
||||
}
|
||||
} else {
|
||||
if (GB(_m[t].m5, 3, 2) == 0) {
|
||||
|
@ -1252,6 +1270,35 @@ bool AfterLoadGame()
|
|||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_ROAD_TYPES)) {
|
||||
/* Add road subtypes */
|
||||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
bool has_road = false;
|
||||
switch (GetTileType(t)) {
|
||||
case MP_ROAD:
|
||||
has_road = true;
|
||||
break;
|
||||
case MP_STATION:
|
||||
has_road = IsRoadStop(t);
|
||||
break;
|
||||
case MP_TUNNELBRIDGE:
|
||||
has_road = GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_road) {
|
||||
RoadType road_rt = HasBit(_me[t].m7, 6) ? ROADTYPE_ROAD : INVALID_ROADTYPE;
|
||||
RoadType tram_rt = HasBit(_me[t].m7, 7) ? ROADTYPE_TRAM : INVALID_ROADTYPE;
|
||||
|
||||
assert(road_rt != INVALID_ROADTYPE || tram_rt != INVALID_ROADTYPE);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SB(_me[t].m7, 6, 2, 0); // Clear pre-NRT road type bits.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Elrails got added in rev 24 */
|
||||
if (IsSavegameVersionBefore(SLV_24)) {
|
||||
RailType min_rail = RAILTYPE_ELECTRIC;
|
||||
|
@ -1375,7 +1422,7 @@ bool AfterLoadGame()
|
|||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->avail_railtypes = GetCompanyRailtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadtypes(c->index);
|
||||
c->avail_roadtypes = GetCompanyRoadTypes(c->index);
|
||||
}
|
||||
|
||||
if (!IsSavegameVersionBefore(SLV_27)) AfterLoadStations();
|
||||
|
@ -1846,10 +1893,10 @@ bool AfterLoadGame()
|
|||
}
|
||||
} else if (IsTileType(t, MP_ROAD)) {
|
||||
/* works for all RoadTileType */
|
||||
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
/* update even non-existing road types to update tile owner too */
|
||||
Owner o = GetRoadOwner(t, rt);
|
||||
if (o < MAX_COMPANIES && !Company::IsValidID(o)) SetRoadOwner(t, rt, OWNER_NONE);
|
||||
Owner o = GetRoadOwner(t, rtt);
|
||||
if (o < MAX_COMPANIES && !Company::IsValidID(o)) SetRoadOwner(t, rtt, OWNER_NONE);
|
||||
}
|
||||
if (IsLevelCrossing(t)) {
|
||||
if (!Company::IsValidID(GetTileOwner(t))) FixOwnerOfRailTrack(t);
|
||||
|
@ -2662,7 +2709,7 @@ bool AfterLoadGame()
|
|||
|
||||
if (rv->state == RVSB_IN_DEPOT || rv->state == RVSB_WORMHOLE) break;
|
||||
|
||||
TrackStatus ts = GetTileTrackStatus(rv->tile, TRANSPORT_ROAD, rv->compatible_roadtypes);
|
||||
TrackStatus ts = GetTileTrackStatus(rv->tile, TRANSPORT_ROAD, GetRoadTramType(rv->roadtype));
|
||||
TrackBits trackbits = TrackStatusToTrackBits(ts);
|
||||
|
||||
/* Only X/Y tracks can be sloped. */
|
||||
|
@ -2871,8 +2918,8 @@ bool AfterLoadGame()
|
|||
for (TileIndex t = 0; t < map_size; t++) {
|
||||
if (!IsStandardRoadStopTile(t)) continue;
|
||||
Owner o = GetTileOwner(t);
|
||||
SetRoadOwner(t, ROADTYPE_ROAD, o);
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, o);
|
||||
SetRoadOwner(t, RTT_ROAD, o);
|
||||
SetRoadOwner(t, RTT_TRAM, o);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,11 +131,12 @@ void AfterLoadCompanyStats()
|
|||
}
|
||||
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rt));
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt == INVALID_ROADTYPE) continue;
|
||||
c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt));
|
||||
/* A level crossings and depots have two road bits. */
|
||||
if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rt)) : 2;
|
||||
if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -153,9 +154,10 @@ void AfterLoadCompanyStats()
|
|||
case STATION_BUS:
|
||||
case STATION_TRUCK: {
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
c = Company::GetIfValid(GetRoadOwner(tile, rt));
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt == INVALID_ROADTYPE) continue;
|
||||
c = Company::GetIfValid(GetRoadOwner(tile, rtt));
|
||||
if (c != nullptr) c->infrastructure.road[rt] += 2; // A road stop has two road bits.
|
||||
}
|
||||
break;
|
||||
|
@ -210,9 +212,10 @@ void AfterLoadCompanyStats()
|
|||
|
||||
case TRANSPORT_ROAD: {
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
c = Company::GetIfValid(GetRoadOwner(tile, rt));
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt == INVALID_ROADTYPE) continue;
|
||||
c = Company::GetIfValid(GetRoadOwner(tile, rtt));
|
||||
if (c != nullptr) c->infrastructure.road[rt] += len * 2; // A full diagonal road has two road bits.
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -298,6 +298,7 @@ enum SaveLoadVersion : uint16 {
|
|||
SLV_ROADVEH_PATH_CACHE, ///< 211 PR#7261 Add path cache for road vehicles.
|
||||
SLV_REMOVE_OPF, ///< 212 PR#7245 Remove OPF.
|
||||
SLV_TREES_WATER_CLASS, ///< 213 PR#7405 WaterClass update for tree tiles.
|
||||
SLV_ROAD_TYPES, ///< 214 PR#6811 NewGRF road types.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
|
|
@ -410,6 +410,14 @@ void AfterLoadVehicles(bool part_of_load)
|
|||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
if (rv->IsFrontEngine()) {
|
||||
rv->gcache.last_speed = rv->cur_speed; // update displayed road vehicle speed
|
||||
|
||||
rv->roadtype = Engine::Get(rv->engine_type)->u.road.roadtype;
|
||||
rv->compatible_roadtypes = GetRoadTypeInfo(rv->roadtype)->powered_roadtypes;
|
||||
for (RoadVehicle *u = rv; u != nullptr; u = u->Next()) {
|
||||
u->roadtype = rv->roadtype;
|
||||
u->compatible_roadtypes = rv->compatible_roadtypes;
|
||||
}
|
||||
|
||||
RoadVehUpdateCache(rv);
|
||||
if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) {
|
||||
rv->CargoChanged();
|
||||
|
@ -448,13 +456,7 @@ void AfterLoadVehicles(bool part_of_load)
|
|||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
switch (v->type) {
|
||||
case VEH_ROAD: {
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
rv->roadtype = HasBit(EngInfo(v->First()->engine_type)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
|
||||
rv->compatible_roadtypes = RoadTypeToRoadTypes(rv->roadtype);
|
||||
FALLTHROUGH;
|
||||
}
|
||||
|
||||
case VEH_ROAD:
|
||||
case VEH_TRAIN:
|
||||
case VEH_SHIP:
|
||||
v->GetImage(v->direction, EIT_ON_MAP, &v->sprite_seq);
|
||||
|
|
|
@ -56,7 +56,7 @@ void SQAIRail_Register(Squirrel *engine)
|
|||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_ARE_NO_SIGNALS, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_IS_NO_STATION, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED, ScriptRail::ERR_RAILTYPE_DISALLOWS_CROSSING);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED_RAIL, ScriptRail::ERR_RAILTYPE_DISALLOWS_CROSSING);
|
||||
|
||||
ScriptError::RegisterErrorMapString(ScriptRail::ERR_CROSSING_ON_ONEWAY_ROAD, "ERR_CROSSING_ON_ONEWAY_ROAD");
|
||||
ScriptError::RegisterErrorMapString(ScriptRail::ERR_UNSUITABLE_TRACK, "ERR_UNSUITABLE_TRACK");
|
||||
|
|
|
@ -26,6 +26,8 @@ void SQAIRoad_Register(Squirrel *engine)
|
|||
SQAIRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION, "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD, "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING, "ERR_ROADTYPE_DISALLOWS_CROSSING");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ERR_UNSUITABLE_ROAD, "ERR_UNSUITABLE_ROAD");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_ROAD, "ROADTYPE_ROAD");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_TRAM, "ROADTYPE_TRAM");
|
||||
SQAIRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_INVALID, "ROADTYPE_INVALID");
|
||||
|
@ -40,12 +42,19 @@ void SQAIRoad_Register(Squirrel *engine)
|
|||
ScriptError::RegisterErrorMap(STR_ERROR_DRIVE_THROUGH_DIRECTION, ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD, ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION, ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED_ROAD, ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_NO_SUITABLE_ROAD, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_NO_SUITABLE_TRAMWAY, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_INCOMPATIBLE_ROAD, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_WORKS_IN_PROGRESS, "ERR_ROAD_WORKS_IN_PROGRESS");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION, "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD, "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING, "ERR_ROADTYPE_DISALLOWS_CROSSING");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_UNSUITABLE_ROAD, "ERR_UNSUITABLE_ROAD");
|
||||
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetName, "GetName", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetRoadVehicleTypeForCargo, "GetRoadVehicleTypeForCargo", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadTile, "IsRoadTile", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadDepotTile, "IsRoadDepotTile", 2, ".i");
|
||||
|
@ -54,6 +63,9 @@ void SQAIRoad_Register(Squirrel *engine)
|
|||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadTypeAvailable, "IsRoadTypeAvailable", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetCurrentRoadType, "GetCurrentRoadType", 1, ".");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::SetCurrentRoadType, "SetCurrentRoadType", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::RoadVehCanRunOnRoad, "RoadVehCanRunOnRoad", 3, ".ii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::RoadVehHasPowerOnRoad, "RoadVehHasPowerOnRoad", 3, ".ii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::ConvertRoadType, "ConvertRoadType", 4, ".iii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::HasRoadType, "HasRoadType", 3, ".ii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::AreRoadTilesConnected, "AreRoadTilesConnected", 3, ".ii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::CanBuildConnectedRoadParts, "CanBuildConnectedRoadParts", 5, ".iaii");
|
||||
|
@ -74,6 +86,7 @@ void SQAIRoad_Register(Squirrel *engine)
|
|||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::RemoveRoadDepot, "RemoveRoadDepot", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::RemoveRoadStation, "RemoveRoadStation", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetBuildCost, "GetBuildCost", 3, ".ii");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetMaxSpeed, "GetMaxSpeed", 2, ".i");
|
||||
SQAIRoad.DefSQStaticMethod(engine, &ScriptRoad::GetMaintenanceCostFactor, "GetMaintenanceCostFactor", 2, ".i");
|
||||
|
||||
SQAIRoad.PostRegister(engine);
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
* \li AIGroup::GetSecondaryColour
|
||||
* \li AIVehicle::BuildVehicleWithRefit
|
||||
* \li AIVehicle::GetBuildWithRefitCapacity
|
||||
* \li AIRoad::GetName
|
||||
* \li AIRoad::RoadVehCanRunOnRoad
|
||||
* \li AIRoad::RoadVehHasPowerOnRoad
|
||||
* \li AIRoad::ConvertRoadType
|
||||
* \li AIRoad::GetMaxSpeed
|
||||
*
|
||||
* \b 1.9.0
|
||||
*
|
||||
|
@ -46,6 +51,9 @@
|
|||
*
|
||||
* No changes
|
||||
*
|
||||
* API additions:
|
||||
* \li AIRoad::ERR_ROADTYPE_DISALLOWS_CROSSING
|
||||
*
|
||||
* \b 1.7.0 - 1.7.2
|
||||
*
|
||||
* No changes
|
||||
|
|
|
@ -56,7 +56,7 @@ void SQGSRail_Register(Squirrel *engine)
|
|||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_ARE_NO_SIGNALS, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_THERE_IS_NO_STATION, ScriptRail::ERR_UNSUITABLE_TRACK);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED, ScriptRail::ERR_RAILTYPE_DISALLOWS_CROSSING);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED_RAIL, ScriptRail::ERR_RAILTYPE_DISALLOWS_CROSSING);
|
||||
|
||||
ScriptError::RegisterErrorMapString(ScriptRail::ERR_CROSSING_ON_ONEWAY_ROAD, "ERR_CROSSING_ON_ONEWAY_ROAD");
|
||||
ScriptError::RegisterErrorMapString(ScriptRail::ERR_UNSUITABLE_TRACK, "ERR_UNSUITABLE_TRACK");
|
||||
|
|
|
@ -26,6 +26,8 @@ void SQGSRoad_Register(Squirrel *engine)
|
|||
SQGSRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION, "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD, "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING, "ERR_ROADTYPE_DISALLOWS_CROSSING");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ERR_UNSUITABLE_ROAD, "ERR_UNSUITABLE_ROAD");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_ROAD, "ROADTYPE_ROAD");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_TRAM, "ROADTYPE_TRAM");
|
||||
SQGSRoad.DefSQConst(engine, ScriptRoad::ROADTYPE_INVALID, "ROADTYPE_INVALID");
|
||||
|
@ -40,12 +42,19 @@ void SQGSRoad_Register(Squirrel *engine)
|
|||
ScriptError::RegisterErrorMap(STR_ERROR_DRIVE_THROUGH_DIRECTION, ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD, ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION, ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_CROSSING_DISALLOWED_ROAD, ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_NO_SUITABLE_ROAD, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_NO_SUITABLE_TRAMWAY, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
ScriptError::RegisterErrorMap(STR_ERROR_INCOMPATIBLE_ROAD, ScriptRoad::ERR_UNSUITABLE_ROAD);
|
||||
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_WORKS_IN_PROGRESS, "ERR_ROAD_WORKS_IN_PROGRESS");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION, "ERR_ROAD_DRIVE_THROUGH_WRONG_DIRECTION");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD, "ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, "ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_ROADTYPE_DISALLOWS_CROSSING, "ERR_ROADTYPE_DISALLOWS_CROSSING");
|
||||
ScriptError::RegisterErrorMapString(ScriptRoad::ERR_UNSUITABLE_ROAD, "ERR_UNSUITABLE_ROAD");
|
||||
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetName, "GetName", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetRoadVehicleTypeForCargo, "GetRoadVehicleTypeForCargo", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadTile, "IsRoadTile", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadDepotTile, "IsRoadDepotTile", 2, ".i");
|
||||
|
@ -54,6 +63,9 @@ void SQGSRoad_Register(Squirrel *engine)
|
|||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::IsRoadTypeAvailable, "IsRoadTypeAvailable", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetCurrentRoadType, "GetCurrentRoadType", 1, ".");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::SetCurrentRoadType, "SetCurrentRoadType", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::RoadVehCanRunOnRoad, "RoadVehCanRunOnRoad", 3, ".ii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::RoadVehHasPowerOnRoad, "RoadVehHasPowerOnRoad", 3, ".ii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::ConvertRoadType, "ConvertRoadType", 4, ".iii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::HasRoadType, "HasRoadType", 3, ".ii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::AreRoadTilesConnected, "AreRoadTilesConnected", 3, ".ii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::CanBuildConnectedRoadParts, "CanBuildConnectedRoadParts", 5, ".iaii");
|
||||
|
@ -74,6 +86,7 @@ void SQGSRoad_Register(Squirrel *engine)
|
|||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::RemoveRoadDepot, "RemoveRoadDepot", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::RemoveRoadStation, "RemoveRoadStation", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetBuildCost, "GetBuildCost", 3, ".ii");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetMaxSpeed, "GetMaxSpeed", 2, ".i");
|
||||
SQGSRoad.DefSQStaticMethod(engine, &ScriptRoad::GetMaintenanceCostFactor, "GetMaintenanceCostFactor", 2, ".i");
|
||||
|
||||
SQGSRoad.PostRegister(engine);
|
||||
|
|
|
@ -227,8 +227,8 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_START_REPLACE, "WID_RV_START_REPLACE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_INFO_TAB, "WID_RV_INFO_TAB");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_STOP_REPLACE, "WID_RV_STOP_REPLACE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_RAIL_ROAD_TYPE_DROPDOWN, "WID_RV_RAIL_ROAD_TYPE_DROPDOWN");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_ENGINEWAGON_DROPDOWN, "WID_RV_TRAIN_ENGINEWAGON_DROPDOWN");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_RAILTYPE_DROPDOWN, "WID_RV_TRAIN_RAILTYPE_DROPDOWN");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_RV_TRAIN_WAGONREMOVE_TOGGLE, "WID_RV_TRAIN_WAGONREMOVE_TOGGLE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BB_BACKGROUND, "WID_BB_BACKGROUND");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BAFD_QUESTION, "WID_BAFD_QUESTION");
|
||||
|
@ -385,6 +385,8 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_RAIL_COUNT, "WID_CI_RAIL_COUNT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_ROAD_DESC, "WID_CI_ROAD_DESC");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_ROAD_COUNT, "WID_CI_ROAD_COUNT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_TRAM_DESC, "WID_CI_TRAM_DESC");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_TRAM_COUNT, "WID_CI_TRAM_COUNT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_WATER_DESC, "WID_CI_WATER_DESC");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_WATER_COUNT, "WID_CI_WATER_COUNT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_CI_STATION_DESC, "WID_CI_STATION_DESC");
|
||||
|
@ -996,6 +998,7 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BRW_WAYPOINT_MATRIX, "WID_BRW_WAYPOINT_MATRIX");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BRW_WAYPOINT, "WID_BRW_WAYPOINT");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BRW_SCROLL, "WID_BRW_SCROLL");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_CAPTION, "WID_ROT_CAPTION");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_ROAD_X, "WID_ROT_ROAD_X");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_ROAD_Y, "WID_ROT_ROAD_Y");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_AUTOROAD, "WID_ROT_AUTOROAD");
|
||||
|
@ -1007,6 +1010,7 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_BUILD_BRIDGE, "WID_ROT_BUILD_BRIDGE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_BUILD_TUNNEL, "WID_ROT_BUILD_TUNNEL");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_REMOVE, "WID_ROT_REMOVE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_ROT_CONVERT_ROAD, "WID_ROT_CONVERT_ROAD");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BROD_CAPTION, "WID_BROD_CAPTION");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BROD_DEPOT_NE, "WID_BROD_DEPOT_NE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_BROD_DEPOT_SE, "WID_BROD_DEPOT_SE");
|
||||
|
@ -1214,6 +1218,7 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_BUILDING_TOOLS_START, "WID_TN_BUILDING_TOOLS_START");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_RAILS, "WID_TN_RAILS");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_ROADS, "WID_TN_ROADS");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_TRAMS, "WID_TN_TRAMS");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_WATER, "WID_TN_WATER");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_AIR, "WID_TN_AIR");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_LANDSCAPE, "WID_TN_LANDSCAPE");
|
||||
|
@ -1237,6 +1242,7 @@ void SQGSWindow_Register(Squirrel *engine)
|
|||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_TOWN_GENERATE, "WID_TE_TOWN_GENERATE");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_INDUSTRY, "WID_TE_INDUSTRY");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_ROADS, "WID_TE_ROADS");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_TRAMS, "WID_TE_TRAMS");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_WATER, "WID_TE_WATER");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_TREES, "WID_TE_TREES");
|
||||
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_SIGNS, "WID_TE_SIGNS");
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
* API additions:
|
||||
* \li GSVehicle::BuildVehicleWithRefit
|
||||
* \li GSVehicle::GetBuildWithRefitCapacity
|
||||
* \li GSRoad::GetName
|
||||
* \li GSRoad::RoadVehCanRunOnRoad
|
||||
* \li GSRoad::RoadVehHasPowerOnRoad
|
||||
* \li GSRoad::ConvertRoadType
|
||||
* \li GSRoad::GetMaxSpeed
|
||||
*
|
||||
* \b 1.9.0
|
||||
*
|
||||
|
@ -42,6 +47,9 @@
|
|||
*
|
||||
* No changes
|
||||
*
|
||||
* API additions:
|
||||
* \li GSRoad::ERR_ROADTYPE_DISALLOWS_CROSSING
|
||||
*
|
||||
* \b 1.7.0 - 1.7.2
|
||||
*
|
||||
* No changes
|
||||
|
|
|
@ -83,7 +83,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
|
|||
switch (vehicle_type) {
|
||||
case ScriptVehicle::VT_ROAD:
|
||||
type |= (TRANSPORT_ROAD << 15);
|
||||
type |= (::RoadTypeToRoadTypes((::RoadType)ScriptObject::GetRoadType()) << 8);
|
||||
type |= (ScriptRoad::GetCurrentRoadType() << 8);
|
||||
break;
|
||||
case ScriptVehicle::VT_RAIL:
|
||||
type |= (TRANSPORT_RAIL << 15);
|
||||
|
@ -114,7 +114,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
|
|||
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
|
||||
DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
|
||||
|
||||
return ScriptObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, nullptr, &::_DoCommandReturnBuildBridge2);
|
||||
return ScriptObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptRoad::GetCurrentRoadType() << 4), 0, CMD_BUILD_ROAD, nullptr, &::_DoCommandReturnBuildBridge2);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptBridge::_BuildBridgeRoad2()
|
||||
|
@ -126,7 +126,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
|
|||
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
|
||||
DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
|
||||
|
||||
return ScriptObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
|
||||
return ScriptObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptRoad::GetCurrentRoadType() << 4), 0, CMD_BUILD_ROAD);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptBridge::RemoveBridge(TileIndex tile)
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
if (!IsValidEngine(engine_id)) return ScriptRoad::ROADTYPE_INVALID;
|
||||
if (GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return ScriptRoad::ROADTYPE_INVALID;
|
||||
|
||||
return HasBit(::EngInfo(engine_id)->misc_flags, EF_ROAD_TRAM) ? ScriptRoad::ROADTYPE_TRAM : ScriptRoad::ROADTYPE_ROAD;
|
||||
return (ScriptRoad::RoadType)(uint)::RoadVehInfo(engine_id)->roadtype;
|
||||
}
|
||||
|
||||
/* static */ ScriptRail::RailType ScriptEngine::GetRailType(EngineID engine_id)
|
||||
|
|
|
@ -90,7 +90,8 @@
|
|||
company = ScriptCompany::ResolveCompanyID(company);
|
||||
if (company == ScriptCompany::COMPANY_INVALID || (::RoadType)roadtype >= ROADTYPE_END || !_settings_game.economy.infrastructure_maintenance) return 0;
|
||||
|
||||
return ::RoadMaintenanceCost((::RoadType)roadtype, ::Company::Get((::CompanyID)company)->infrastructure.road[roadtype]);
|
||||
const ::Company *c = ::Company::Get((::CompanyID)company);
|
||||
return ::RoadMaintenanceCost((::RoadType)roadtype, c->infrastructure.road[roadtype], RoadTypeIsRoad((::RoadType)roadtype) ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal());
|
||||
}
|
||||
|
||||
/* static */ Money ScriptInfrastructure::GetMonthlyInfrastructureCosts(ScriptCompany::CompanyID company, Infrastructure infra_type)
|
||||
|
@ -114,8 +115,9 @@
|
|||
|
||||
case INFRASTRUCTURE_ROAD: {
|
||||
Money cost;
|
||||
uint32 road_total = c->infrastructure.GetRoadTotal();
|
||||
for (::RoadType rt = ::ROADTYPE_BEGIN; rt != ::ROADTYPE_END; rt++) {
|
||||
cost += RoadMaintenanceCost(rt, c->infrastructure.road[rt]);
|
||||
cost += RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_total);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
ERR_UNSUITABLE_TRACK, // [STR_ERROR_NO_SUITABLE_RAILROAD_TRACK, STR_ERROR_THERE_IS_NO_RAILROAD_TRACK, STR_ERROR_THERE_ARE_NO_SIGNALS, STR_ERROR_THERE_IS_NO_STATION]
|
||||
|
||||
/** This railtype cannot have crossings */
|
||||
ERR_RAILTYPE_DISALLOWS_CROSSING, // [STR_ERROR_CROSSING_DISALLOWED]
|
||||
ERR_RAILTYPE_DISALLOWS_CROSSING, // [STR_ERROR_CROSSING_DISALLOWED_RAIL]
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
return ScriptCargo::HasCargoClass(cargo_type, ScriptCargo::CC_PASSENGERS) ? ROADVEHTYPE_BUS : ROADVEHTYPE_TRUCK;
|
||||
}
|
||||
|
||||
/* static */ char *ScriptRoad::GetName(RoadType road_type)
|
||||
{
|
||||
if (!IsRoadTypeAvailable(road_type)) return nullptr;
|
||||
|
||||
return GetString(GetRoadTypeInfo((::RoadType)road_type)->strings.name);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::IsRoadTile(TileIndex tile)
|
||||
{
|
||||
if (!::IsValidTile(tile)) return false;
|
||||
|
@ -37,7 +44,7 @@
|
|||
if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
|
||||
|
||||
return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT &&
|
||||
(::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
|
||||
HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::IsRoadStationTile(TileIndex tile)
|
||||
|
@ -45,7 +52,7 @@
|
|||
if (!::IsValidTile(tile)) return false;
|
||||
if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
|
||||
|
||||
return ::IsRoadStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
|
||||
return ::IsRoadStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::IsDriveThroughRoadStationTile(TileIndex tile)
|
||||
|
@ -53,12 +60,12 @@
|
|||
if (!::IsValidTile(tile)) return false;
|
||||
if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
|
||||
|
||||
return ::IsDriveThroughStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
|
||||
return ::IsDriveThroughStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::IsRoadTypeAvailable(RoadType road_type)
|
||||
{
|
||||
return ::IsValidRoadType((::RoadType)road_type) && ::HasRoadTypesAvail(ScriptObject::GetCompany(), ::RoadTypeToRoadTypes((::RoadType)road_type));
|
||||
return (::RoadType)road_type < ROADTYPE_END && ::HasRoadTypeAvail(ScriptObject::GetCompany(), (::RoadType)road_type);
|
||||
}
|
||||
|
||||
/* static */ ScriptRoad::RoadType ScriptRoad::GetCurrentRoadType()
|
||||
|
@ -73,11 +80,24 @@
|
|||
ScriptObject::SetRoadType((::RoadType)road_type);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::RoadVehCanRunOnRoad(RoadType engine_road_type, RoadType road_road_type)
|
||||
{
|
||||
return RoadVehHasPowerOnRoad(engine_road_type, road_road_type);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::RoadVehHasPowerOnRoad(RoadType engine_road_type, RoadType road_road_type)
|
||||
{
|
||||
if (!IsRoadTypeAvailable(engine_road_type)) return false;
|
||||
if (!IsRoadTypeAvailable(road_road_type)) return false;
|
||||
|
||||
return ::HasPowerOnRoad((::RoadType)engine_road_type, (::RoadType)road_road_type);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::HasRoadType(TileIndex tile, RoadType road_type)
|
||||
{
|
||||
if (!ScriptMap::IsValidTile(tile)) return false;
|
||||
if (!IsRoadTypeAvailable(road_type)) return false;
|
||||
return ::GetAnyRoadBits(tile, (::RoadType)road_type, false) != ROAD_NONE;
|
||||
return ::GetAnyRoadBits(tile, GetRoadTramType((::RoadType)road_type), false) != ROAD_NONE;
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
|
||||
|
@ -89,8 +109,9 @@
|
|||
/* Tiles not neighbouring */
|
||||
if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
|
||||
|
||||
RoadBits r1 = ::GetAnyRoadBits(t1, ScriptObject::GetRoadType());
|
||||
RoadBits r2 = ::GetAnyRoadBits(t2, ScriptObject::GetRoadType());
|
||||
RoadTramType rtt = GetRoadTramType(ScriptObject::GetRoadType());
|
||||
RoadBits r1 = ::GetAnyRoadBits(t1, rtt); // TODO
|
||||
RoadBits r2 = ::GetAnyRoadBits(t2, rtt); // TODO
|
||||
|
||||
uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
|
||||
uint dir_2 = 2 ^ dir_1;
|
||||
|
@ -100,6 +121,16 @@
|
|||
return HasBit(r1, dir_1) && HasBit(r2, dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::ConvertRoadType(TileIndex start_tile, TileIndex end_tile, RoadType road_type)
|
||||
{
|
||||
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
||||
EnforcePrecondition(false, ::IsValidTile(start_tile));
|
||||
EnforcePrecondition(false, ::IsValidTile(end_tile));
|
||||
EnforcePrecondition(false, IsRoadTypeAvailable(road_type));
|
||||
|
||||
return ScriptObject::DoCommand(start_tile, end_tile, (::RoadType)road_type, CMD_CONVERT_ROAD);
|
||||
}
|
||||
|
||||
/* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */
|
||||
|
||||
/**
|
||||
|
@ -380,7 +411,7 @@ static bool NormaliseTileOffset(int32 *tile)
|
|||
if (::IsNormalRoadTile(tile)) {
|
||||
rb = ::GetAllRoadBits(tile);
|
||||
} else {
|
||||
for (::RoadType rt = ::ROADTYPE_BEGIN; rt < ::ROADTYPE_END; rt++) rb |= ::GetAnyRoadBits(tile, rt);
|
||||
rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM);
|
||||
}
|
||||
for (uint i = 0; i < lengthof(neighbours); i++) {
|
||||
if (HasBit(rb, i)) existing->array[existing->size++] = neighbours[i];
|
||||
|
@ -392,15 +423,15 @@ static bool NormaliseTileOffset(int32 *tile)
|
|||
/**
|
||||
* Check whether one can reach (possibly by building) a road piece the center
|
||||
* of the neighbouring tile. This includes roads and (drive through) stations.
|
||||
* @param rts The road type we want to know reachability for
|
||||
* @param rt The road type we want to know reachability for
|
||||
* @param start_tile The tile to "enter" the neighbouring tile.
|
||||
* @param neighbour The direction to the neighbouring tile to "enter".
|
||||
* @return true if and only if the tile is reachable.
|
||||
*/
|
||||
static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, DiagDirection neighbour)
|
||||
static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagDirection neighbour)
|
||||
{
|
||||
TileIndex neighbour_tile = ::TileAddByDiagDir(start_tile, neighbour);
|
||||
if ((rts & ::GetRoadTypes(neighbour_tile)) == 0) return false;
|
||||
if (!HasBit(::GetPresentRoadTypes(neighbour_tile), rt)) return false;
|
||||
|
||||
switch (::GetTileType(neighbour_tile)) {
|
||||
case MP_ROAD:
|
||||
|
@ -422,13 +453,13 @@ static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, Dia
|
|||
if (!::IsValidTile(tile)) return false;
|
||||
if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
|
||||
|
||||
::RoadTypes rts = ::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType());
|
||||
::RoadType rt = (::RoadType)GetCurrentRoadType();
|
||||
int32 neighbour = 0;
|
||||
|
||||
if (TileX(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NE)) neighbour++;
|
||||
if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SE)) neighbour++;
|
||||
if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SW)) neighbour++;
|
||||
if (TileY(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NW)) neighbour++;
|
||||
if (TileX(tile) > 0 && NeighbourHasReachableRoad(rt, tile, DIAGDIR_NE)) neighbour++;
|
||||
if (NeighbourHasReachableRoad(rt, tile, DIAGDIR_SE)) neighbour++;
|
||||
if (NeighbourHasReachableRoad(rt, tile, DIAGDIR_SW)) neighbour++;
|
||||
if (TileY(tile) > 0 && NeighbourHasReachableRoad(rt, tile, DIAGDIR_NW)) neighbour++;
|
||||
|
||||
return neighbour;
|
||||
}
|
||||
|
@ -460,10 +491,10 @@ static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, Dia
|
|||
EnforcePrecondition(false, ::IsValidTile(start));
|
||||
EnforcePrecondition(false, ::IsValidTile(end));
|
||||
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
|
||||
EnforcePrecondition(false, !one_way || ScriptObject::GetRoadType() == ::ROADTYPE_ROAD);
|
||||
EnforcePrecondition(false, !one_way || RoadTypeIsRoad(ScriptObject::GetRoadType()));
|
||||
EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
|
||||
|
||||
return ScriptObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (((start < end) == !full) ? 1 : 2) | (ScriptObject::GetRoadType() << 3) | ((one_way ? 1 : 0) << 5) | 1 << 6, CMD_BUILD_LONG_ROAD);
|
||||
return ScriptObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (((start < end) == !full) ? 1 : 2) | (ScriptObject::GetRoadType() << 3) | ((one_way ? 1 : 0) << 10) | 1 << 11, CMD_BUILD_LONG_ROAD);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::BuildRoad(TileIndex start, TileIndex end)
|
||||
|
@ -520,11 +551,11 @@ static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, Dia
|
|||
entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
|
||||
}
|
||||
|
||||
uint p2 = station_id == ScriptStation::STATION_JOIN_ADJACENT ? 0 : 32;
|
||||
uint p2 = station_id == ScriptStation::STATION_JOIN_ADJACENT ? 0 : 4;
|
||||
p2 |= drive_through ? 2 : 0;
|
||||
p2 |= road_veh_type == ROADVEHTYPE_TRUCK ? 1 : 0;
|
||||
p2 |= ::RoadTypeToRoadTypes(ScriptObject::GetRoadType()) << 2;
|
||||
p2 |= entrance_dir << 6;
|
||||
p2 |= ScriptObject::GetRoadType() << 5;
|
||||
p2 |= entrance_dir << 3;
|
||||
p2 |= (ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16;
|
||||
return ScriptObject::DoCommand(tile, 1 | 1 << 8, p2, CMD_BUILD_ROAD_STOP);
|
||||
}
|
||||
|
@ -588,7 +619,7 @@ static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, Dia
|
|||
if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return -1;
|
||||
|
||||
switch (build_type) {
|
||||
case BT_ROAD: return ::GetPrice(PR_BUILD_ROAD, 1, nullptr);
|
||||
case BT_ROAD: return ::RoadBuildCost((::RoadType)roadtype);
|
||||
case BT_DEPOT: return ::GetPrice(PR_BUILD_DEPOT_ROAD, 1, nullptr);
|
||||
case BT_BUS_STOP: return ::GetPrice(PR_BUILD_STATION_BUS, 1, nullptr);
|
||||
case BT_TRUCK_STOP: return ::GetPrice(PR_BUILD_STATION_TRUCK, 1, nullptr);
|
||||
|
@ -596,9 +627,16 @@ static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, Dia
|
|||
}
|
||||
}
|
||||
|
||||
/* static */ int32 ScriptRoad::GetMaxSpeed(RoadType road_type)
|
||||
{
|
||||
if (!ScriptRoad::IsRoadTypeAvailable(road_type)) return 0;
|
||||
|
||||
return GetRoadTypeInfo((::RoadType)road_type)->max_speed;
|
||||
}
|
||||
|
||||
/* static */ uint16 ScriptRoad::GetMaintenanceCostFactor(RoadType roadtype)
|
||||
{
|
||||
if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return 0;
|
||||
|
||||
return roadtype == ROADTYPE_TRAM ? 3 : 2;
|
||||
return GetRoadTypeInfo((::RoadType)roadtype)->maintenance_multiplier;
|
||||
}
|
||||
|
|
|
@ -36,16 +36,21 @@ public:
|
|||
/** Drive through roads can't be build on town owned roads */
|
||||
ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD, // [STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD]
|
||||
|
||||
|
||||
/** One way roads can't have junctions */
|
||||
ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS, // [STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION]
|
||||
|
||||
/** This roadtype cannot have crossings */
|
||||
ERR_ROADTYPE_DISALLOWS_CROSSING, // [STR_ERROR_CROSSING_DISALLOWED_ROAD]
|
||||
|
||||
/** No suitable road could be found */
|
||||
ERR_UNSUITABLE_ROAD, // [STR_ERROR_NO_SUITABLE_ROAD, STR_ERROR_NO_SUITABLE_TRAMWAY, STR_ERROR_INCOMPATIBLE_ROAD]
|
||||
};
|
||||
|
||||
/**
|
||||
* Types of road known to the game.
|
||||
*/
|
||||
enum RoadType {
|
||||
/* Note: these values represent part of the in-game RoadType enum */
|
||||
/* Note: these values represent part of the in-game static values */
|
||||
ROADTYPE_ROAD = ::ROADTYPE_ROAD, ///< Build road objects.
|
||||
ROADTYPE_TRAM = ::ROADTYPE_TRAM, ///< Build tram objects.
|
||||
|
||||
|
@ -71,6 +76,14 @@ public:
|
|||
BT_TRUCK_STOP, ///< Build a truck stop
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the name of a road type.
|
||||
* @param road_type The road type to get the name of.
|
||||
* @pre IsRoadTypeAvailable(road_type).
|
||||
* @return The name the road type has.
|
||||
*/
|
||||
static char *GetName(RoadType road_type);
|
||||
|
||||
/**
|
||||
* Determines whether a busstop or a truckstop is needed to transport a certain cargo.
|
||||
* @param cargo_type The cargo to test.
|
||||
|
@ -137,6 +150,41 @@ public:
|
|||
*/
|
||||
static void SetCurrentRoadType(RoadType road_type);
|
||||
|
||||
/**
|
||||
* Check if a road vehicle built for a road type can run on another road type.
|
||||
* @param engine_road_type The road type the road vehicle is built for.
|
||||
* @param track_road_type The road type you want to check.
|
||||
* @pre ScriptRoad::IsRoadTypeAvailable(engine_road_type).
|
||||
* @pre ScriptRoad::IsRoadTypeAvailable(road_road_type).
|
||||
* @return Whether a road vehicle built for 'engine_road_type' can run on 'road_road_type'.
|
||||
*/
|
||||
static bool RoadVehCanRunOnRoad(ScriptRoad::RoadType engine_road_type, ScriptRoad::RoadType road_road_type);
|
||||
|
||||
/**
|
||||
* Check if a road vehicle built for a road type has power on another road type.
|
||||
* @param engine_road_type The road type the road vehicle is built for.
|
||||
* @param road_road_type The road type you want to check.
|
||||
* @pre ScriptRoad::IsRoadTypeAvailable(engine_road_type).
|
||||
* @pre ScriptRoad::IsRoadTypeAvailable(road_road_type).
|
||||
* @return Whether a road vehicle built for 'engine_road_type' has power on 'road_road_type'.
|
||||
*/
|
||||
static bool RoadVehHasPowerOnRoad(ScriptRoad::RoadType engine_road_type, ScriptRoad::RoadType road_road_type);
|
||||
|
||||
|
||||
/**
|
||||
* Convert the road on all tiles within a rectangle to another RoadType.
|
||||
* @param start_tile One corner of the rectangle.
|
||||
* @param end_tile The opposite corner of the rectangle.
|
||||
* @param road_type The RoadType you want to convert.
|
||||
* @pre ScriptMap::IsValidTile(start_tile).
|
||||
* @pre ScriptMap::IsValidTile(end_tile).
|
||||
* @pre IsRoadTypeAvailable(road_type).
|
||||
* @game @pre Valid ScriptCompanyMode active in scope.
|
||||
* @exception ScriptRoad::ERR_UNSUITABLE_ROAD
|
||||
* @return Whether at least some road has been converted successfully.
|
||||
*/
|
||||
static bool ConvertRoadType(TileIndex start_tile, TileIndex end_tile, RoadType road_type);
|
||||
|
||||
/**
|
||||
* Check if a given tile has RoadType.
|
||||
* @param tile The tile to check.
|
||||
|
@ -482,16 +530,28 @@ public:
|
|||
|
||||
/**
|
||||
* Get the baseprice of building a road-related object.
|
||||
* @param roadtype the roadtype that is build (on)
|
||||
* @param roadtype the roadtype of the object to build
|
||||
* @param build_type the type of object to build
|
||||
* @pre IsRoadTypeAvailable(railtype)
|
||||
* @pre IsRoadTypeAvailable(roadtype)
|
||||
* @return The baseprice of building the given object.
|
||||
*/
|
||||
static Money GetBuildCost(RoadType roadtype, BuildType build_type);
|
||||
|
||||
/**
|
||||
* Get the maintenance cost factor of a roadtype.
|
||||
* @param roadtype The roadtype to get the maintenance factor of.
|
||||
* Get the maximum speed of road vehicles running on this roadtype.
|
||||
* @param road_type The roadtype to get the maximum speed of.
|
||||
* @pre IsRoadTypeAvailable(road_type)
|
||||
* @return The maximum speed road vehicles can run on this roadtype
|
||||
* or 0 if there is no limit.
|
||||
* @note The speed is in OpenTTD's internal speed unit.
|
||||
* This is mph / 0.8, which is roughly 0.5 km/h.
|
||||
* To get km/h multiply this number by 2.01168.
|
||||
*/
|
||||
static int32 GetMaxSpeed(RoadType road_type);
|
||||
|
||||
/**
|
||||
* Get the maintenance cost factor of a road type.
|
||||
* @param roadtype The road type to get the maintenance factor of.
|
||||
* @pre IsRoadTypeAvailable(roadtype)
|
||||
* @return Maintenance cost factor of the roadtype.
|
||||
*/
|
||||
|
|
|
@ -211,13 +211,11 @@ template<bool Tfrom, bool Tvia>
|
|||
if (!IsValidStation(station_id)) return false;
|
||||
if (!ScriptRoad::IsRoadTypeAvailable(road_type)) return false;
|
||||
|
||||
::RoadTypes r = RoadTypeToRoadTypes((::RoadType)road_type);
|
||||
|
||||
for (const RoadStop *rs = ::Station::Get(station_id)->GetPrimaryRoadStop(ROADSTOP_BUS); rs != nullptr; rs = rs->next) {
|
||||
if ((::GetRoadTypes(rs->xy) & r) != 0) return true;
|
||||
if (HasBit(::GetPresentRoadTypes(rs->xy), (::RoadType)road_type)) return true;
|
||||
}
|
||||
for (const RoadStop *rs = ::Station::Get(station_id)->GetPrimaryRoadStop(ROADSTOP_TRUCK); rs != nullptr; rs = rs->next) {
|
||||
if ((::GetRoadTypes(rs->xy) & r) != 0) return true;
|
||||
if (HasBit(::GetPresentRoadTypes(rs->xy), (::RoadType)road_type)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -33,12 +33,12 @@
|
|||
case MP_WATER: return IsCoast(tile);
|
||||
case MP_ROAD:
|
||||
/* Tram bits aren't considered buildable */
|
||||
if (::GetRoadTypes(tile) != ROADTYPES_ROAD) return false;
|
||||
if (::GetRoadTypeTram(tile) != INVALID_ROADTYPE) return false;
|
||||
/* Depots and crossings aren't considered buildable */
|
||||
if (::GetRoadTileType(tile) != ROAD_TILE_NORMAL) return false;
|
||||
if (!HasExactlyOneBit(::GetRoadBits(tile, ROADTYPE_ROAD))) return false;
|
||||
if (::IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN)) return true;
|
||||
if (::IsRoadOwner(tile, ROADTYPE_ROAD, ScriptObject::GetCompany())) return true;
|
||||
if (!HasExactlyOneBit(::GetRoadBits(tile, RTT_ROAD))) return false;
|
||||
if (::IsRoadOwner(tile, RTT_ROAD, OWNER_TOWN)) return true;
|
||||
if (::IsRoadOwner(tile, RTT_ROAD, ScriptObject::GetCompany())) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +201,12 @@
|
|||
{
|
||||
if (!::IsValidTile(tile)) return false;
|
||||
|
||||
return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, UINT32_MAX)) != TRACKDIR_BIT_NONE;
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 0)) != TRACKDIR_BIT_NONE ||
|
||||
::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 1)) != TRACKDIR_BIT_NONE;
|
||||
} else {
|
||||
return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 0)) != TRACKDIR_BIT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ int32 ScriptTile::GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int radius)
|
||||
|
|
|
@ -90,7 +90,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
|
|||
uint type = 0;
|
||||
if (vehicle_type == ScriptVehicle::VT_ROAD) {
|
||||
type |= (TRANSPORT_ROAD << 8);
|
||||
type |= ::RoadTypeToRoadTypes((::RoadType)ScriptObject::GetRoadType());
|
||||
type |= ScriptRoad::GetCurrentRoadType();
|
||||
} else {
|
||||
type |= (TRANSPORT_RAIL << 8);
|
||||
type |= ScriptRail::GetCurrentRailType();
|
||||
|
|
|
@ -401,7 +401,7 @@
|
|||
if (!IsValidVehicle(vehicle_id)) return ScriptRoad::ROADTYPE_INVALID;
|
||||
if (GetVehicleType(vehicle_id) != VT_ROAD) return ScriptRoad::ROADTYPE_INVALID;
|
||||
|
||||
return (ScriptRoad::RoadType)(::RoadVehicle::Get(vehicle_id))->roadtype;
|
||||
return (ScriptRoad::RoadType)(int)(::RoadVehicle::Get(vehicle_id))->roadtype;
|
||||
}
|
||||
|
||||
/* static */ int32 ScriptVehicle::GetCapacity(VehicleID vehicle_id, CargoID cargo)
|
||||
|
|
|
@ -954,9 +954,11 @@ public:
|
|||
WID_RV_INFO_TAB = ::WID_RV_INFO_TAB, ///< Info tab.
|
||||
WID_RV_STOP_REPLACE = ::WID_RV_STOP_REPLACE, ///< Stop Replacing button.
|
||||
|
||||
/* Train/road only widgets */
|
||||
WID_RV_RAIL_ROAD_TYPE_DROPDOWN = ::WID_RV_RAIL_ROAD_TYPE_DROPDOWN, ///< Dropdown menu about the rail/roadtype.
|
||||
|
||||
/* Train only widgets. */
|
||||
WID_RV_TRAIN_ENGINEWAGON_DROPDOWN = ::WID_RV_TRAIN_ENGINEWAGON_DROPDOWN, ///< Dropdown to select engines and/or wagons.
|
||||
WID_RV_TRAIN_RAILTYPE_DROPDOWN = ::WID_RV_TRAIN_RAILTYPE_DROPDOWN, ///< Dropdown menu about the railtype.
|
||||
WID_RV_TRAIN_WAGONREMOVE_TOGGLE = ::WID_RV_TRAIN_WAGONREMOVE_TOGGLE, ///< Button to toggle removing wagons.
|
||||
};
|
||||
|
||||
|
@ -1170,6 +1172,8 @@ public:
|
|||
WID_CI_RAIL_COUNT = ::WID_CI_RAIL_COUNT, ///< Count of rail.
|
||||
WID_CI_ROAD_DESC = ::WID_CI_ROAD_DESC, ///< Description of road.
|
||||
WID_CI_ROAD_COUNT = ::WID_CI_ROAD_COUNT, ///< Count of road.
|
||||
WID_CI_TRAM_DESC = ::WID_CI_TRAM_DESC, ///< Description of tram.
|
||||
WID_CI_TRAM_COUNT = ::WID_CI_TRAM_COUNT, ///< Count of tram.
|
||||
WID_CI_WATER_DESC = ::WID_CI_WATER_DESC, ///< Description of water.
|
||||
WID_CI_WATER_COUNT = ::WID_CI_WATER_COUNT, ///< Count of water.
|
||||
WID_CI_STATION_DESC = ::WID_CI_STATION_DESC, ///< Description of station.
|
||||
|
@ -2125,6 +2129,7 @@ public:
|
|||
/** Widgets of the #BuildRoadToolbarWindow class. */
|
||||
enum RoadToolbarWidgets {
|
||||
/* Name starts with RO instead of R, because of collision with RailToolbarWidgets */
|
||||
WID_ROT_CAPTION = ::WID_ROT_CAPTION, ///< Caption of the window
|
||||
WID_ROT_ROAD_X = ::WID_ROT_ROAD_X, ///< Build road in x-direction.
|
||||
WID_ROT_ROAD_Y = ::WID_ROT_ROAD_Y, ///< Build road in y-direction.
|
||||
WID_ROT_AUTOROAD = ::WID_ROT_AUTOROAD, ///< Autorail.
|
||||
|
@ -2136,6 +2141,7 @@ public:
|
|||
WID_ROT_BUILD_BRIDGE = ::WID_ROT_BUILD_BRIDGE, ///< Build bridge.
|
||||
WID_ROT_BUILD_TUNNEL = ::WID_ROT_BUILD_TUNNEL, ///< Build tunnel.
|
||||
WID_ROT_REMOVE = ::WID_ROT_REMOVE, ///< Remove road.
|
||||
WID_ROT_CONVERT_ROAD = ::WID_ROT_CONVERT_ROAD, ///< Convert road.
|
||||
};
|
||||
|
||||
/** Widgets of the #BuildRoadDepotWindow class. */
|
||||
|
@ -2435,6 +2441,7 @@ public:
|
|||
WID_TN_BUILDING_TOOLS_START = ::WID_TN_BUILDING_TOOLS_START, ///< Helper for the offset of the building tools
|
||||
WID_TN_RAILS = ::WID_TN_RAILS, ///< Rail building menu.
|
||||
WID_TN_ROADS = ::WID_TN_ROADS, ///< Road building menu.
|
||||
WID_TN_TRAMS = ::WID_TN_TRAMS, ///< Tram building menu.
|
||||
WID_TN_WATER = ::WID_TN_WATER, ///< Water building toolbar.
|
||||
WID_TN_AIR = ::WID_TN_AIR, ///< Airport building toolbar.
|
||||
WID_TN_LANDSCAPE = ::WID_TN_LANDSCAPE, ///< Landscaping toolbar.
|
||||
|
@ -2462,11 +2469,11 @@ public:
|
|||
WID_TE_TOWN_GENERATE = ::WID_TE_TOWN_GENERATE, ///< Town building window.
|
||||
WID_TE_INDUSTRY = ::WID_TE_INDUSTRY, ///< Industry building window.
|
||||
WID_TE_ROADS = ::WID_TE_ROADS, ///< Road building menu.
|
||||
WID_TE_TRAMS = ::WID_TE_TRAMS, ///< Tram building menu.
|
||||
WID_TE_WATER = ::WID_TE_WATER, ///< Water building toolbar.
|
||||
WID_TE_TREES = ::WID_TE_TREES, ///< Tree building toolbar.
|
||||
WID_TE_SIGNS = ::WID_TE_SIGNS, ///< Sign building.
|
||||
WID_TE_DATE_PANEL = ::WID_TE_DATE_PANEL, ///< Container for the date widgets.
|
||||
/* The following three need to have the same actual widget number as the normal toolbar due to shared code. */
|
||||
WID_TE_MUSIC_SOUND = ::WID_TE_MUSIC_SOUND, ///< Music/sound configuration menu.
|
||||
WID_TE_HELP = ::WID_TE_HELP, ///< Help menu.
|
||||
WID_TE_SWITCH_BAR = ::WID_TE_SWITCH_BAR, ///< Only available when toolbar has been split to switch between different subsets.
|
||||
|
|
|
@ -460,28 +460,51 @@ static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
|
|||
*/
|
||||
static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
|
||||
{
|
||||
if (t == MP_STATION) {
|
||||
switch (GetStationType(tile)) {
|
||||
case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
|
||||
case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
|
||||
case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
|
||||
case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
|
||||
case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
|
||||
default: return MKCOLOUR_FFFF;
|
||||
switch (t) {
|
||||
case MP_STATION:
|
||||
switch (GetStationType(tile)) {
|
||||
case STATION_RAIL: return MKCOLOUR_XXXX(PC_VERY_DARK_BROWN);
|
||||
case STATION_AIRPORT: return MKCOLOUR_XXXX(PC_RED);
|
||||
case STATION_TRUCK: return MKCOLOUR_XXXX(PC_ORANGE);
|
||||
case STATION_BUS: return MKCOLOUR_XXXX(PC_YELLOW);
|
||||
case STATION_DOCK: return MKCOLOUR_XXXX(PC_LIGHT_BLUE);
|
||||
default: return MKCOLOUR_FFFF;
|
||||
}
|
||||
|
||||
case MP_RAILWAY: {
|
||||
AndOr andor = {
|
||||
MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
|
||||
_smallmap_contours_andor[t].mand
|
||||
};
|
||||
|
||||
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
|
||||
return ApplyMask(cs->default_colour, &andor);
|
||||
}
|
||||
} else if (t == MP_RAILWAY) {
|
||||
AndOr andor = {
|
||||
MKCOLOUR_0XX0(GetRailTypeInfo(GetRailType(tile))->map_colour),
|
||||
_smallmap_contours_andor[t].mand
|
||||
};
|
||||
|
||||
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
|
||||
return ApplyMask(cs->default_colour, &andor);
|
||||
case MP_ROAD: {
|
||||
const RoadTypeInfo *rti = nullptr;
|
||||
if (GetRoadTypeRoad(tile) != INVALID_ROADTYPE) {
|
||||
rti = GetRoadTypeInfo(GetRoadTypeRoad(tile));
|
||||
} else {
|
||||
rti = GetRoadTypeInfo(GetRoadTypeTram(tile));
|
||||
}
|
||||
if (rti != nullptr) {
|
||||
AndOr andor = {
|
||||
MKCOLOUR_0XX0(rti->map_colour),
|
||||
_smallmap_contours_andor[t].mand
|
||||
};
|
||||
|
||||
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
|
||||
return ApplyMask(cs->default_colour, &andor);
|
||||
}
|
||||
FALLTHROUGH;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Ground colour */
|
||||
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
|
||||
return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
|
||||
}
|
||||
|
||||
/* Ground colour */
|
||||
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
|
||||
return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -189,7 +189,7 @@ RoadStop *Station::GetPrimaryRoadStop(const RoadVehicle *v) const
|
|||
|
||||
for (; rs != nullptr; rs = rs->next) {
|
||||
/* The vehicle cannot go to this roadstop (different roadtype) */
|
||||
if ((GetRoadTypes(rs->xy) & v->compatible_roadtypes) == ROADTYPES_NONE) continue;
|
||||
if (!HasTileAnyRoadType(rs->xy, v->compatible_roadtypes)) continue;
|
||||
/* The vehicle is articulated and can therefore not go to a standard road stop. */
|
||||
if (IsStandardRoadStopTile(rs->xy) && v->HasArticulatedPart()) continue;
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "station_kdtree.h"
|
||||
#include "roadstop_base.h"
|
||||
#include "newgrf_railtype.h"
|
||||
#include "newgrf_roadtype.h"
|
||||
#include "waypoint_base.h"
|
||||
#include "waypoint_func.h"
|
||||
#include "pbs.h"
|
||||
|
@ -934,10 +935,10 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl
|
|||
* @param is_truck_stop True when building a truck stop, false otherwise.
|
||||
* @param axis Axis of a drive-through road stop.
|
||||
* @param station StationID to be queried and returned if available.
|
||||
* @param rts Road types to build.
|
||||
* @param rt Road type to build.
|
||||
* @return The cost in case of success, or an error code if it failed.
|
||||
*/
|
||||
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadTypes rts)
|
||||
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
|
||||
{
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
int allowed_z = -1;
|
||||
|
@ -988,47 +989,54 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
|
|||
}
|
||||
}
|
||||
|
||||
RoadTypes cur_rts = IsNormalRoadTile(cur_tile) ? GetRoadTypes(cur_tile) : ROADTYPES_NONE;
|
||||
uint num_roadbits = 0;
|
||||
if (build_over_road) {
|
||||
/* There is a road, check if we can build road+tram stop over it. */
|
||||
if (HasBit(cur_rts, ROADTYPE_ROAD)) {
|
||||
Owner road_owner = GetRoadOwner(cur_tile, ROADTYPE_ROAD);
|
||||
RoadType road_rt = GetRoadType(cur_tile, RTT_ROAD);
|
||||
if (road_rt != INVALID_ROADTYPE) {
|
||||
Owner road_owner = GetRoadOwner(cur_tile, RTT_ROAD);
|
||||
if (road_owner == OWNER_TOWN) {
|
||||
if (!_settings_game.construction.road_stop_on_town_road) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD);
|
||||
} else if (!_settings_game.construction.road_stop_on_competitor_road && road_owner != OWNER_NONE) {
|
||||
CommandCost ret = CheckOwnership(road_owner);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_ROAD));
|
||||
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD));
|
||||
|
||||
if (RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
|
||||
cost.AddCost(RoadBuildCost(road_rt) * (2 - num_pieces));
|
||||
} else if (RoadTypeIsRoad(rt)) {
|
||||
cost.AddCost(RoadBuildCost(rt) * 2);
|
||||
}
|
||||
|
||||
if (GetDisallowedRoadDirections(cur_tile) != DRD_NONE) return_cmd_error(STR_ERROR_DRIVE_THROUGH_ON_ONEWAY_ROAD);
|
||||
|
||||
/* There is a tram, check if we can build road+tram stop over it. */
|
||||
if (HasBit(cur_rts, ROADTYPE_TRAM)) {
|
||||
Owner tram_owner = GetRoadOwner(cur_tile, ROADTYPE_TRAM);
|
||||
RoadType tram_rt = GetRoadType(cur_tile, RTT_TRAM);
|
||||
if (tram_rt != INVALID_ROADTYPE) {
|
||||
Owner tram_owner = GetRoadOwner(cur_tile, RTT_TRAM);
|
||||
if (Company::IsValidID(tram_owner) &&
|
||||
(!_settings_game.construction.road_stop_on_competitor_road ||
|
||||
/* Disallow breaking end-of-line of someone else
|
||||
* so trams can still reverse on this tile. */
|
||||
HasExactlyOneBit(GetRoadBits(cur_tile, ROADTYPE_TRAM)))) {
|
||||
HasExactlyOneBit(GetRoadBits(cur_tile, RTT_TRAM)))) {
|
||||
CommandCost ret = CheckOwnership(tram_owner);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
num_roadbits += CountBits(GetRoadBits(cur_tile, ROADTYPE_TRAM));
|
||||
}
|
||||
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM));
|
||||
|
||||
/* Take into account existing roadbits. */
|
||||
rts |= cur_rts;
|
||||
if (RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
|
||||
cost.AddCost(RoadBuildCost(tram_rt) * (2 - num_pieces));
|
||||
} else if (RoadTypeIsTram(rt)) {
|
||||
cost.AddCost(RoadBuildCost(rt) * 2);
|
||||
}
|
||||
} else {
|
||||
ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
cost.AddCost(RoadBuildCost(rt) * 2);
|
||||
}
|
||||
|
||||
uint roadbits_to_build = CountBits(rts) * 2 - num_roadbits;
|
||||
cost.AddCost(_price[PR_BUILD_ROAD] * roadbits_to_build);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1783,10 +1791,10 @@ static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID statio
|
|||
* bit 8..15: Length of the road stop.
|
||||
* @param p2 bit 0: 0 For bus stops, 1 for truck stops.
|
||||
* bit 1: 0 For normal stops, 1 for drive-through.
|
||||
* bit 2..3: The roadtypes.
|
||||
* bit 5: Allow stations directly adjacent to other stations.
|
||||
* bit 6..7: Entrance direction (#DiagDirection) for normal stops.
|
||||
* bit 6: #Axis of the road for drive-through stops.
|
||||
* bit 2: Allow stations directly adjacent to other stations.
|
||||
* bit 3..4: Entrance direction (#DiagDirection) for normal stops.
|
||||
* bit 3: #Axis of the road for drive-through stops.
|
||||
* bit 5..10: The roadtype.
|
||||
* bit 16..31: Station ID to join (NEW_STATION if build new one).
|
||||
* @param text Unused.
|
||||
* @return The cost of this operation or an error.
|
||||
|
@ -1795,7 +1803,8 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||
{
|
||||
bool type = HasBit(p2, 0);
|
||||
bool is_drive_through = HasBit(p2, 1);
|
||||
RoadTypes rts = Extract<RoadTypes, 2, 2>(p2);
|
||||
RoadType rt = Extract<RoadType, 5, 6>(p2);
|
||||
if (!ValParamRoadType(rt)) return CMD_ERROR;
|
||||
StationID station_to_join = GB(p2, 16, 16);
|
||||
bool reuse = (station_to_join != NEW_STATION);
|
||||
if (!reuse) station_to_join = INVALID_STATION;
|
||||
|
@ -1815,20 +1824,18 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||
|
||||
if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
|
||||
|
||||
if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
|
||||
|
||||
/* Trams only have drive through stops */
|
||||
if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR;
|
||||
if (!is_drive_through && RoadTypeIsTram(rt)) return CMD_ERROR;
|
||||
|
||||
DiagDirection ddir;
|
||||
Axis axis;
|
||||
if (is_drive_through) {
|
||||
/* By definition axis is valid, due to there being 2 axes and reading 1 bit. */
|
||||
axis = Extract<Axis, 6, 1>(p2);
|
||||
axis = Extract<Axis, 3, 1>(p2);
|
||||
ddir = AxisToDiagDir(axis);
|
||||
} else {
|
||||
/* By definition ddir is valid, due to there being 4 diagonal directions and reading 2 bits. */
|
||||
ddir = Extract<DiagDirection, 6, 2>(p2);
|
||||
ddir = Extract<DiagDirection, 3, 2>(p2);
|
||||
axis = DiagDirToAxis(ddir);
|
||||
}
|
||||
|
||||
|
@ -1838,12 +1845,12 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||
/* Total road stop cost. */
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
|
||||
StationID est = INVALID_STATION;
|
||||
ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rts);
|
||||
ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rt);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
|
||||
Station *st = nullptr;
|
||||
ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 5), roadstop_area, &st);
|
||||
ret = FindJoiningRoadStop(est, station_to_join, HasBit(p2, 2), roadstop_area, &st);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
/* Check if this number of road stops can be allocated. */
|
||||
|
@ -1855,9 +1862,11 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||
if (flags & DC_EXEC) {
|
||||
/* Check every tile in the area. */
|
||||
TILE_AREA_LOOP(cur_tile, roadstop_area) {
|
||||
RoadTypes cur_rts = GetRoadTypes(cur_tile);
|
||||
Owner road_owner = HasBit(cur_rts, ROADTYPE_ROAD) ? GetRoadOwner(cur_tile, ROADTYPE_ROAD) : _current_company;
|
||||
Owner tram_owner = HasBit(cur_rts, ROADTYPE_TRAM) ? GetRoadOwner(cur_tile, ROADTYPE_TRAM) : _current_company;
|
||||
/* Get existing road types and owners before any tile clearing */
|
||||
RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE;
|
||||
RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE;
|
||||
Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company;
|
||||
Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company;
|
||||
|
||||
if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
|
||||
RemoveRoadStop(cur_tile, flags);
|
||||
|
@ -1881,23 +1890,27 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||
|
||||
RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
|
||||
if (is_drive_through) {
|
||||
/* Update company infrastructure counts. If the current tile is a normal
|
||||
* road tile, count only the new road bits needed to get a full diagonal road. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, cur_rts | rts) {
|
||||
Company *c = Company::GetIfValid(rt == ROADTYPE_ROAD ? road_owner : tram_owner);
|
||||
if (c != nullptr) {
|
||||
c->infrastructure.road[rt] += 2 - (IsNormalRoadTile(cur_tile) && HasBit(cur_rts, rt) ? CountBits(GetRoadBits(cur_tile, rt)) : 0);
|
||||
DirtyCompanyInfrastructureWindows(c->index);
|
||||
}
|
||||
/* Update company infrastructure counts. If the current tile is a normal road tile, remove the old
|
||||
* bits first. */
|
||||
if (IsNormalRoadTile(cur_tile)) {
|
||||
UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD)));
|
||||
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM)));
|
||||
}
|
||||
|
||||
MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, axis);
|
||||
if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt;
|
||||
if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt;
|
||||
|
||||
UpdateCompanyRoadInfrastructure(road_rt, road_owner, 2);
|
||||
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, 2);
|
||||
|
||||
MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, road_rt, tram_rt, axis);
|
||||
road_stop->MakeDriveThrough();
|
||||
} else {
|
||||
if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt;
|
||||
if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt;
|
||||
/* Non-drive-through stop never overbuild and always count as two road bits. */
|
||||
Company::Get(st->owner)->infrastructure.road[FIND_FIRST_BIT(rts)] += 2;
|
||||
MakeRoadStop(cur_tile, st->owner, st->index, rs_type, rts, ddir);
|
||||
Company::Get(st->owner)->infrastructure.road[rt] += 2;
|
||||
MakeRoadStop(cur_tile, st->owner, st->index, rs_type, road_rt, tram_rt, ddir);
|
||||
}
|
||||
Company::Get(st->owner)->infrastructure.station++;
|
||||
|
||||
|
@ -1983,14 +1996,11 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
|||
}
|
||||
|
||||
/* Update company infrastructure counts. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
|
||||
if (c != nullptr) {
|
||||
c->infrastructure.road[rt] -= 2;
|
||||
DirtyCompanyInfrastructureWindows(c->index);
|
||||
}
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), -2);
|
||||
}
|
||||
|
||||
Company::Get(st->owner)->infrastructure.station--;
|
||||
DirtyCompanyInfrastructureWindows(st->owner);
|
||||
|
||||
|
@ -2064,16 +2074,16 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
|
|||
if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
|
||||
|
||||
/* Save information on to-be-restored roads before the stop is removed. */
|
||||
RoadTypes rts = ROADTYPES_NONE;
|
||||
RoadBits road_bits = ROAD_NONE;
|
||||
RoadType road_type[] = { INVALID_ROADTYPE, INVALID_ROADTYPE };
|
||||
Owner road_owner[] = { OWNER_NONE, OWNER_NONE };
|
||||
assert_compile(lengthof(road_owner) == ROADTYPE_END);
|
||||
if (IsDriveThroughStopTile(cur_tile)) {
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(cur_tile)) {
|
||||
road_owner[rt] = GetRoadOwner(cur_tile, rt);
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
road_type[rtt] = GetRoadType(cur_tile, rtt);
|
||||
if (road_type[rtt] == INVALID_ROADTYPE) continue;
|
||||
road_owner[rtt] = GetRoadOwner(cur_tile, rtt);
|
||||
/* If we don't want to preserve our roads then restore only roads of others. */
|
||||
if (keep_drive_through_roads || road_owner[rt] != _current_company) SetBit(rts, rt);
|
||||
if (!keep_drive_through_roads && road_owner[rtt] == _current_company) road_type[rtt] = INVALID_ROADTYPE;
|
||||
}
|
||||
road_bits = AxisToRoadBits(DiagDirToAxis(GetRoadStopDir(cur_tile)));
|
||||
}
|
||||
|
@ -2087,19 +2097,14 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
|
|||
had_success = true;
|
||||
|
||||
/* Restore roads. */
|
||||
if ((flags & DC_EXEC) && rts != ROADTYPES_NONE) {
|
||||
MakeRoadNormal(cur_tile, road_bits, rts, ClosestTownFromTile(cur_tile, UINT_MAX)->index,
|
||||
road_owner[ROADTYPE_ROAD], road_owner[ROADTYPE_TRAM]);
|
||||
if ((flags & DC_EXEC) && (road_type[RTT_ROAD] != INVALID_ROADTYPE || road_type[RTT_TRAM] != INVALID_ROADTYPE)) {
|
||||
MakeRoadNormal(cur_tile, road_bits, road_type[RTT_ROAD], road_type[RTT_TRAM], ClosestTownFromTile(cur_tile, UINT_MAX)->index,
|
||||
road_owner[RTT_ROAD], road_owner[RTT_TRAM]);
|
||||
|
||||
/* Update company infrastructure counts. */
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, rts) {
|
||||
Company *c = Company::GetIfValid(GetRoadOwner(cur_tile, rt));
|
||||
if (c != nullptr) {
|
||||
c->infrastructure.road[rt] += CountBits(road_bits);
|
||||
DirtyCompanyInfrastructureWindows(c->index);
|
||||
}
|
||||
}
|
||||
int count = CountBits(road_bits);
|
||||
UpdateCompanyRoadInfrastructure(road_type[RTT_ROAD], road_owner[RTT_ROAD], count);
|
||||
UpdateCompanyRoadInfrastructure(road_type[RTT_TRAM], road_owner[RTT_ROAD], count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2701,7 +2706,6 @@ static void DrawTile_Station(TileInfo *ti)
|
|||
const NewGRFSpriteLayout *layout = nullptr;
|
||||
DrawTileSprites tmp_rail_layout;
|
||||
const DrawTileSprites *t = nullptr;
|
||||
RoadTypes roadtypes;
|
||||
int32 total_offset;
|
||||
const RailtypeInfo *rti = nullptr;
|
||||
uint32 relocation = 0;
|
||||
|
@ -2712,7 +2716,6 @@ static void DrawTile_Station(TileInfo *ti)
|
|||
|
||||
if (HasStationRail(ti->tile)) {
|
||||
rti = GetRailTypeInfo(GetRailType(ti->tile));
|
||||
roadtypes = ROADTYPES_NONE;
|
||||
total_offset = rti->GetRailtypeSpriteOffset();
|
||||
|
||||
if (IsCustomStationSpecIndex(ti->tile)) {
|
||||
|
@ -2739,7 +2742,6 @@ static void DrawTile_Station(TileInfo *ti)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
roadtypes = IsRoadStop(ti->tile) ? GetRoadTypes(ti->tile) : ROADTYPES_NONE;
|
||||
total_offset = 0;
|
||||
}
|
||||
|
||||
|
@ -2924,10 +2926,30 @@ draw_default_foundation:
|
|||
|
||||
if (HasStationRail(ti->tile) && HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
|
||||
|
||||
if (HasBit(roadtypes, ROADTYPE_TRAM)) {
|
||||
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
|
||||
DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
|
||||
DrawRoadCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
|
||||
if (IsRoadStop(ti->tile)) {
|
||||
RoadType road_rt = GetRoadTypeRoad(ti->tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(ti->tile);
|
||||
const RoadTypeInfo* road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
|
||||
const RoadTypeInfo* tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
|
||||
|
||||
if (IsDriveThroughStopTile(ti->tile)) {
|
||||
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
|
||||
uint sprite_offset = axis == AXIS_X ? 1 : 0;
|
||||
|
||||
DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset);
|
||||
} else {
|
||||
/* Non-drivethrough road stops are only valid for roads. */
|
||||
assert(road_rt != INVALID_ROADTYPE && tram_rt == INVALID_ROADTYPE);
|
||||
|
||||
if (road_rti->UsesOverlay()) {
|
||||
DiagDirection dir = GetRoadStopDir(ti->tile);
|
||||
SpriteID ground = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ROADSTOP);
|
||||
DrawGroundSprite(ground + dir, PAL_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw road, tram catenary */
|
||||
DrawRoadCatenary(ti);
|
||||
}
|
||||
|
||||
if (IsRailWaypoint(ti->tile)) {
|
||||
|
@ -2960,8 +2982,29 @@ void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, Ro
|
|||
DrawSprite(img + total_offset, HasBit(img, PALETTE_MODIFIER_COLOUR) ? pal : PAL_NONE, x, y);
|
||||
}
|
||||
|
||||
if (roadtype == ROADTYPE_TRAM) {
|
||||
DrawSprite(SPR_TRAMWAY_TRAM + (t->ground.sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
|
||||
if (roadtype != INVALID_ROADTYPE) {
|
||||
const RoadTypeInfo* rti = GetRoadTypeInfo(roadtype);
|
||||
if (image >= 4) {
|
||||
/* Drive-through stop */
|
||||
uint sprite_offset = 5 - image;
|
||||
|
||||
/* Road underlay takes precendence over tram */
|
||||
if (rti->UsesOverlay()) {
|
||||
SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_GROUND);
|
||||
DrawSprite(ground + sprite_offset, PAL_NONE, x, y);
|
||||
|
||||
SpriteID overlay = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_OVERLAY);
|
||||
if (overlay) DrawSprite(overlay + sprite_offset, PAL_NONE, x, y);
|
||||
} else if (RoadTypeIsTram(roadtype)) {
|
||||
DrawSprite(SPR_TRAMWAY_TRAM + sprite_offset, PAL_NONE, x, y);
|
||||
}
|
||||
} else {
|
||||
/* Drive-in stop */
|
||||
if (RoadTypeIsRoad(roadtype) && rti->UsesOverlay()) {
|
||||
SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP);
|
||||
DrawSprite(ground + image, PAL_NONE, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Default waypoint has no railtype specific sprites */
|
||||
|
@ -2981,28 +3024,44 @@ static Foundation GetFoundation_Station(TileIndex tile, Slope tileh)
|
|||
static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
td->owner[0] = GetTileOwner(tile);
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
|
||||
if (IsRoadStopTile(tile)) {
|
||||
RoadType road_rt = GetRoadTypeRoad(tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(tile);
|
||||
Owner road_owner = INVALID_OWNER;
|
||||
Owner tram_owner = INVALID_OWNER;
|
||||
RoadTypes rts = GetRoadTypes(tile);
|
||||
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
|
||||
if (road_rt != INVALID_ROADTYPE) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
|
||||
td->roadtype = rti->strings.name;
|
||||
td->road_speed = rti->max_speed / 2;
|
||||
road_owner = GetRoadOwner(tile, RTT_ROAD);
|
||||
}
|
||||
|
||||
/* Is there a mix of owners? */
|
||||
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
|
||||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
|
||||
uint i = 1;
|
||||
if (road_owner != INVALID_OWNER) {
|
||||
td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
|
||||
td->owner[i] = road_owner;
|
||||
i++;
|
||||
}
|
||||
if (tram_owner != INVALID_OWNER) {
|
||||
td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
|
||||
td->owner[i] = tram_owner;
|
||||
if (tram_rt != INVALID_ROADTYPE) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
|
||||
td->tramtype = rti->strings.name;
|
||||
td->tram_speed = rti->max_speed / 2;
|
||||
tram_owner = GetRoadOwner(tile, RTT_TRAM);
|
||||
}
|
||||
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
/* Is there a mix of owners? */
|
||||
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
|
||||
(road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
|
||||
uint i = 1;
|
||||
if (road_owner != INVALID_OWNER) {
|
||||
td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
|
||||
td->owner[i] = road_owner;
|
||||
i++;
|
||||
}
|
||||
if (tram_owner != INVALID_OWNER) {
|
||||
td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
|
||||
td->owner[i] = tram_owner;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td->build_date = BaseStation::GetByTile(tile)->build_date;
|
||||
|
||||
if (HasStationTileRail(tile)) {
|
||||
|
@ -3088,7 +3147,10 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
|
|||
break;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
if ((GetRoadTypes(tile) & sub_mode) != 0 && IsRoadStop(tile)) {
|
||||
if (IsRoadStop(tile)) {
|
||||
RoadTramType rtt = (RoadTramType)sub_mode;
|
||||
if (!HasTileRoadType(tile, rtt)) break;
|
||||
|
||||
DiagDirection dir = GetRoadStopDir(tile);
|
||||
Axis axis = DiagDirToAxis(dir);
|
||||
|
||||
|
@ -3982,15 +4044,16 @@ void DeleteOilRig(TileIndex tile)
|
|||
static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
|
||||
{
|
||||
if (IsRoadStopTile(tile)) {
|
||||
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
/* Update all roadtypes, no matter if they are present */
|
||||
if (GetRoadOwner(tile, rt) == old_owner) {
|
||||
if (HasTileRoadType(tile, rt)) {
|
||||
if (GetRoadOwner(tile, rtt) == old_owner) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt != INVALID_ROADTYPE) {
|
||||
/* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
|
||||
Company::Get(old_owner)->infrastructure.road[rt] -= 2;
|
||||
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2;
|
||||
}
|
||||
SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
|
||||
SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4071,17 +4134,16 @@ static bool CanRemoveRoadWithStop(TileIndex tile, DoCommandFlag flags)
|
|||
/* Yeah... water can always remove stops, right? */
|
||||
if (_current_company == OWNER_WATER) return true;
|
||||
|
||||
RoadTypes rts = GetRoadTypes(tile);
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) {
|
||||
Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
|
||||
if (GetRoadTypeTram(tile) != INVALID_ROADTYPE) {
|
||||
Owner tram_owner = GetRoadOwner(tile, RTT_TRAM);
|
||||
if (tram_owner != OWNER_NONE && CheckOwnership(tram_owner).Failed()) return false;
|
||||
}
|
||||
if (HasBit(rts, ROADTYPE_ROAD)) {
|
||||
Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
|
||||
if (GetRoadTypeRoad(tile) != INVALID_ROADTYPE) {
|
||||
Owner road_owner = GetRoadOwner(tile, RTT_ROAD);
|
||||
if (road_owner != OWNER_TOWN) {
|
||||
if (road_owner != OWNER_NONE && CheckOwnership(road_owner).Failed()) return false;
|
||||
} else {
|
||||
if (CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, ROADTYPE_ROAD, flags).Failed()) return false;
|
||||
if (CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, RTT_ROAD), OWNER_TOWN, RTT_ROAD, flags).Failed()) return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4102,8 +4164,8 @@ CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
|
|||
case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
|
||||
case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
||||
case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
|
||||
case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
|
||||
case STATION_BUS: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
|
||||
case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
|
||||
case STATION_BUS: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
|
||||
case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
|
||||
case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
|
||||
case STATION_OILRIG:
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "vehicle_type.h"
|
||||
#include "economy_func.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
#include "linkgraph/linkgraph_type.h"
|
||||
#include "industry_type.h"
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "water_map.h"
|
||||
#include "station_func.h"
|
||||
#include "rail.h"
|
||||
#include "road.h"
|
||||
|
||||
typedef byte StationGfx; ///< Index of station graphics. @see _station_display_datas
|
||||
|
||||
|
@ -583,15 +584,16 @@ static inline void MakeRailWaypoint(TileIndex t, Owner o, StationID sid, Axis a,
|
|||
* @param o the owner of the roadstop
|
||||
* @param sid the station to which this tile belongs
|
||||
* @param rst the type of roadstop to make this tile
|
||||
* @param rt the roadtypes on this tile
|
||||
* @param road_rt the road roadtype on this tile
|
||||
* @param tram_rt the tram roadtype on this tile
|
||||
* @param d the direction of the roadstop
|
||||
*/
|
||||
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d)
|
||||
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, DiagDirection d)
|
||||
{
|
||||
MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), d);
|
||||
SetRoadTypes(t, rt);
|
||||
SetRoadOwner(t, ROADTYPE_ROAD, o);
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, o);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SetRoadOwner(t, RTT_ROAD, o);
|
||||
SetRoadOwner(t, RTT_TRAM, o);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -602,15 +604,16 @@ static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopTyp
|
|||
* @param tram the owner of the tram
|
||||
* @param sid the station to which this tile belongs
|
||||
* @param rst the type of roadstop to make this tile
|
||||
* @param rt the roadtypes on this tile
|
||||
* @param road_rt the road roadtype on this tile
|
||||
* @param tram_rt the tram roadtype on this tile
|
||||
* @param a the direction of the roadstop
|
||||
*/
|
||||
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadTypes rt, Axis a)
|
||||
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, Axis a)
|
||||
{
|
||||
MakeStation(t, station, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a);
|
||||
SetRoadTypes(t, rt);
|
||||
SetRoadOwner(t, ROADTYPE_ROAD, road);
|
||||
SetRoadOwner(t, ROADTYPE_TRAM, tram);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SetRoadOwner(t, RTT_ROAD, road);
|
||||
SetRoadOwner(t, RTT_TRAM, tram);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -669,7 +669,7 @@ static const AircraftVehicleInfo _orig_aircraft_vehicle_info[] = {
|
|||
* Tractive effort coefficient by default is the same as TTDPatch, 0.30*256=76
|
||||
* Air drag value depends on the top speed of the vehicle.
|
||||
*/
|
||||
#define ROV(a, b, c, d, e, f, g, h) { a, b, c, PR_RUNNING_ROADVEH, d, e, f, g, h, 76, 0, VE_DEFAULT, 0 }
|
||||
#define ROV(a, b, c, d, e, f, g, h) { a, b, c, PR_RUNNING_ROADVEH, d, e, f, g, h, 76, 0, VE_DEFAULT, 0, ROADTYPE_ROAD }
|
||||
static const RoadVehicleInfo _orig_road_vehicle_info[] = {
|
||||
/* image_index sfx max_speed power
|
||||
* | cost_factor | | capacity |
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "../newgrf_house.h"
|
||||
#include "../newgrf_engine.h"
|
||||
#include "../newgrf_roadtype.h"
|
||||
|
||||
/* Helper for filling property tables */
|
||||
#define NIP(prop, base, variable, type, name) { name, (ptrdiff_t)cpp_offsetof(base, variable), cpp_sizeof(base, variable), prop, type }
|
||||
|
@ -58,7 +59,7 @@ static const NIVariable _niv_vehicles[] = {
|
|||
NIV(0x47, "vehicle cargo info"),
|
||||
NIV(0x48, "vehicle type info"),
|
||||
NIV(0x49, "year of construction"),
|
||||
NIV(0x4A, "current rail type info"),
|
||||
NIV(0x4A, "current rail/road type info"),
|
||||
NIV(0x4B, "long date of last service"),
|
||||
NIV(0x4C, "current max speed"),
|
||||
NIV(0x4D, "position in articulated vehicle"),
|
||||
|
@ -554,6 +555,48 @@ static const NIFeature _nif_town = {
|
|||
new NIHTown(),
|
||||
};
|
||||
|
||||
/*** NewGRF road types ***/
|
||||
|
||||
static const NIVariable _niv_roadtypes[] = {
|
||||
NIV(0x40, "terrain type"),
|
||||
NIV(0x41, "enhanced tunnels"),
|
||||
NIV(0x42, "level crossing status"),
|
||||
NIV(0x43, "construction date"),
|
||||
NIV(0x44, "town zone"),
|
||||
NIV_END()
|
||||
};
|
||||
|
||||
class NIHRoadType : public NIHelper {
|
||||
bool IsInspectable(uint index) const override { return true; }
|
||||
uint GetParent(uint index) const override { return UINT32_MAX; }
|
||||
const void *GetInstance(uint index) const override { return nullptr; }
|
||||
const void *GetSpec(uint index) const override { return nullptr; }
|
||||
void SetStringParameters(uint index) const override { this->SetObjectAtStringParameters(STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_RAIL_TYPE, INVALID_STRING_ID, index); }
|
||||
uint32 GetGRFID(uint index) const override { return 0; }
|
||||
|
||||
uint Resolve(uint index, uint var, uint param, bool *avail) const override
|
||||
{
|
||||
/* There is no unique GRFFile for the tile. Multiple GRFs can define different parts of the railtype.
|
||||
* However, currently the NewGRF Debug GUI does not display variables depending on the GRF (like 0x7F) anyway. */
|
||||
RoadTypeResolverObject ro(nullptr, index, TCX_NORMAL, ROTSG_END);
|
||||
return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail);
|
||||
}
|
||||
};
|
||||
|
||||
static const NIFeature _nif_roadtype = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
_niv_roadtypes,
|
||||
new NIHRoadType(),
|
||||
};
|
||||
|
||||
static const NIFeature _nif_tramtype = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
_niv_roadtypes,
|
||||
new NIHRoadType(),
|
||||
};
|
||||
|
||||
/** Table with all NIFeatures. */
|
||||
static const NIFeature * const _nifeatures[] = {
|
||||
&_nif_vehicle, // GSF_TRAINS
|
||||
|
@ -574,6 +617,8 @@ static const NIFeature * const _nifeatures[] = {
|
|||
&_nif_object, // GSF_OBJECTS
|
||||
&_nif_railtype, // GSF_RAILTYPES
|
||||
&_nif_airporttile, // GSF_AIRPORTTILES
|
||||
&_nif_roadtype, // GSF_ROADTYPES
|
||||
&_nif_tramtype, // GSF_TRAMTYPES
|
||||
&_nif_town, // GSF_FAKE_TOWNS
|
||||
};
|
||||
assert_compile(lengthof(_nifeatures) == GSF_FAKE_END);
|
||||
|
|
|
@ -156,7 +156,7 @@ static const RailtypeInfo _original_railtypes[] = {
|
|||
STR_RAIL_MENU_ELRAIL_CONSTRUCTION,
|
||||
STR_BUY_VEHICLE_TRAIN_ELRAIL_CAPTION,
|
||||
STR_REPLACE_ELRAIL_VEHICLES,
|
||||
STR_ENGINE_PREVIEW_RAILROAD_LOCOMOTIVE,
|
||||
STR_ENGINE_PREVIEW_ELRAIL_LOCOMOTIVE,
|
||||
},
|
||||
|
||||
/* Offset of snow tiles */
|
||||
|
|
|
@ -41,35 +41,6 @@ static const DrawTileSprites _road_depot[] = {
|
|||
{ {0xA4A, PAL_NONE}, _road_depot_NW }
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _tram_depot_NE[] = {
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x35) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 0, 15, 16, 1)
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _tram_depot_SE[] = {
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x31) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 0, 0, 1, 16)
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x32) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 15, 0, 1, 16)
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _tram_depot_SW[] = {
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x33) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 0, 0, 16, 1)
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x34) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 0, 15, 16, 1)
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
static const DrawTileSeqStruct _tram_depot_NW[] = {
|
||||
TILE_SEQ_LINE((SPR_TRAMWAY_BASE + 0x36) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE, 15, 0, 1, 16)
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
static const DrawTileSprites _tram_depot[] = {
|
||||
{ {0xA4A, PAL_NONE}, _tram_depot_NE },
|
||||
{ {0xA4A, PAL_NONE}, _tram_depot_SE },
|
||||
{ {0xA4A, PAL_NONE}, _tram_depot_SW },
|
||||
{ {0xA4A, PAL_NONE}, _tram_depot_NW }
|
||||
};
|
||||
|
||||
/* Sprite layout for level crossings. The SpriteIDs are actually offsets
|
||||
* from the base SpriteID returned from the NewGRF sprite resolver. */
|
||||
static const DrawTileSeqStruct _crossing_layout_ALL[] = {
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file roadtypes.h
|
||||
* All the roadtype-specific information is stored here.
|
||||
*/
|
||||
|
||||
#ifndef ROADTYPES_H
|
||||
#define ROADTYPES_H
|
||||
|
||||
/**
|
||||
* Global Roadtype definition
|
||||
*/
|
||||
static const RoadTypeInfo _original_roadtypes[] = {
|
||||
/* Road */
|
||||
{
|
||||
/* GUI sprites */
|
||||
{
|
||||
SPR_IMG_ROAD_X_DIR,
|
||||
SPR_IMG_ROAD_Y_DIR,
|
||||
SPR_IMG_AUTOROAD,
|
||||
SPR_IMG_ROAD_DEPOT,
|
||||
SPR_IMG_ROAD_TUNNEL,
|
||||
SPR_IMG_CONVERT_ROAD,
|
||||
},
|
||||
|
||||
{
|
||||
SPR_CURSOR_ROAD_NESW,
|
||||
SPR_CURSOR_ROAD_NWSE,
|
||||
SPR_CURSOR_AUTOROAD,
|
||||
SPR_CURSOR_ROAD_DEPOT,
|
||||
SPR_CURSOR_TUNNEL_RAIL,
|
||||
SPR_CURSOR_CONVERT_ROAD,
|
||||
},
|
||||
|
||||
/* strings */
|
||||
{
|
||||
STR_ROAD_NAME_ROAD,
|
||||
STR_ROAD_TOOLBAR_ROAD_CONSTRUCTION_CAPTION,
|
||||
STR_ROAD_MENU_ROAD_CONSTRUCTION,
|
||||
STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION,
|
||||
STR_REPLACE_ROAD_VEHICLES,
|
||||
STR_ENGINE_PREVIEW_ROAD_VEHICLE,
|
||||
|
||||
STR_ERROR_CAN_T_BUILD_ROAD_HERE,
|
||||
STR_ERROR_CAN_T_REMOVE_ROAD_FROM,
|
||||
STR_ERROR_CAN_T_BUILD_ROAD_DEPOT,
|
||||
{ STR_ERROR_CAN_T_BUILD_BUS_STATION, STR_ERROR_CAN_T_BUILD_TRUCK_STATION },
|
||||
{ STR_ERROR_CAN_T_REMOVE_BUS_STATION, STR_ERROR_CAN_T_REMOVE_TRUCK_STATION },
|
||||
STR_ERROR_CAN_T_CONVERT_ROAD,
|
||||
{ STR_STATION_BUILD_BUS_ORIENTATION, STR_STATION_BUILD_TRUCK_ORIENTATION },
|
||||
{ STR_STATION_BUILD_BUS_ORIENTATION_TOOLTIP, STR_STATION_BUILD_TRUCK_ORIENTATION_TOOLTIP },
|
||||
},
|
||||
|
||||
/* Powered roadtypes */
|
||||
ROADTYPES_ROAD,
|
||||
|
||||
/* flags */
|
||||
ROTFB_TOWN_BUILD,
|
||||
|
||||
/* cost multiplier */
|
||||
8,
|
||||
|
||||
/* maintenance cost multiplier */
|
||||
16,
|
||||
|
||||
/* max speed */
|
||||
0,
|
||||
|
||||
/* road type label */
|
||||
'ROAD',
|
||||
|
||||
/* alternate labels */
|
||||
RoadTypeLabelList(),
|
||||
|
||||
/* map colour */
|
||||
0x01,
|
||||
|
||||
/* introduction date */
|
||||
MIN_YEAR,
|
||||
|
||||
/* roadtypes required for this to be introduced */
|
||||
ROADTYPES_NONE,
|
||||
|
||||
/* introduction road types */
|
||||
ROADTYPES_ROAD,
|
||||
|
||||
/* sort order */
|
||||
0x07,
|
||||
|
||||
{ nullptr },
|
||||
{ nullptr },
|
||||
},
|
||||
|
||||
/* Electrified Tram */
|
||||
{
|
||||
/* GUI sprites */
|
||||
{
|
||||
SPR_IMG_TRAMWAY_X_DIR,
|
||||
SPR_IMG_TRAMWAY_Y_DIR,
|
||||
SPR_IMG_AUTOTRAM,
|
||||
SPR_IMG_ROAD_DEPOT,
|
||||
SPR_IMG_ROAD_TUNNEL,
|
||||
SPR_IMG_CONVERT_TRAM,
|
||||
},
|
||||
|
||||
{
|
||||
SPR_CURSOR_TRAMWAY_NESW,
|
||||
SPR_CURSOR_TRAMWAY_NWSE,
|
||||
SPR_CURSOR_AUTOTRAM,
|
||||
SPR_CURSOR_ROAD_DEPOT,
|
||||
SPR_CURSOR_TUNNEL_RAIL,
|
||||
SPR_CURSOR_CONVERT_TRAM,
|
||||
},
|
||||
|
||||
/* strings */
|
||||
{
|
||||
STR_ROAD_NAME_TRAM,
|
||||
STR_ROAD_TOOLBAR_TRAM_CONSTRUCTION_CAPTION,
|
||||
STR_ROAD_MENU_TRAM_CONSTRUCTION,
|
||||
STR_BUY_VEHICLE_TRAM_VEHICLE_CAPTION,
|
||||
STR_REPLACE_TRAM_VEHICLES,
|
||||
STR_ENGINE_PREVIEW_TRAM_VEHICLE,
|
||||
|
||||
STR_ERROR_CAN_T_BUILD_TRAMWAY_HERE,
|
||||
STR_ERROR_CAN_T_REMOVE_TRAMWAY_FROM,
|
||||
STR_ERROR_CAN_T_BUILD_TRAM_DEPOT,
|
||||
{ STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION, STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION },
|
||||
{ STR_ERROR_CAN_T_REMOVE_PASSENGER_TRAM_STATION, STR_ERROR_CAN_T_REMOVE_CARGO_TRAM_STATION },
|
||||
STR_ERROR_CAN_T_CONVERT_TRAMWAY,
|
||||
{ STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION, STR_STATION_BUILD_CARGO_TRAM_ORIENTATION },
|
||||
{ STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION_TOOLTIP, STR_STATION_BUILD_CARGO_TRAM_ORIENTATION_TOOLTIP },
|
||||
},
|
||||
|
||||
/* Powered roadtypes */
|
||||
ROADTYPES_TRAM,
|
||||
|
||||
/* flags */
|
||||
ROTFB_CATENARY | ROTFB_NO_HOUSES,
|
||||
|
||||
/* cost multiplier */
|
||||
16,
|
||||
|
||||
/* maintenance cost multiplier */
|
||||
24,
|
||||
|
||||
/* max speed */
|
||||
0,
|
||||
|
||||
/* road type label */
|
||||
'ELRL',
|
||||
|
||||
/* alternate labels */
|
||||
RoadTypeLabelList(),
|
||||
|
||||
/* map colour */
|
||||
0x01,
|
||||
|
||||
/* introduction date */
|
||||
INVALID_DATE,
|
||||
|
||||
/* roadtypes required for this to be introduced */
|
||||
ROADTYPES_NONE,
|
||||
|
||||
/* introduction road types */
|
||||
ROADTYPES_TRAM,
|
||||
|
||||
/* sort order */
|
||||
0x17,
|
||||
|
||||
{ nullptr },
|
||||
{ nullptr },
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* ROADTYPES_H */
|
|
@ -56,7 +56,7 @@ static const SpriteID SPR_LARGE_SMALL_WINDOW = 682;
|
|||
|
||||
/** Extra graphic spritenumbers */
|
||||
static const SpriteID SPR_OPENTTD_BASE = 4896;
|
||||
static const uint16 OPENTTD_SPRITE_COUNT = 179;
|
||||
static const uint16 OPENTTD_SPRITE_COUNT = 184;
|
||||
|
||||
/* Halftile-selection sprites */
|
||||
static const SpriteID SPR_HALFTILE_SELECTION_FLAT = SPR_OPENTTD_BASE;
|
||||
|
@ -273,13 +273,15 @@ static const SpriteID SPR_TRAMWAY_BUS_STOP_DT_X_W = SPR_TRAMWAY_BASE + 24;
|
|||
static const SpriteID SPR_TRAMWAY_BUS_STOP_DT_X_E = SPR_TRAMWAY_BASE + 26;
|
||||
static const SpriteID SPR_TRAMWAY_PAVED_STRAIGHT_Y = SPR_TRAMWAY_BASE + 46;
|
||||
static const SpriteID SPR_TRAMWAY_PAVED_STRAIGHT_X = SPR_TRAMWAY_BASE + 47;
|
||||
static const SpriteID SPR_TRAMWAY_DEPOT_WITH_TRACK = SPR_TRAMWAY_BASE + 49;
|
||||
static const SpriteID SPR_TRAMWAY_BACK_WIRES_STRAIGHT = SPR_TRAMWAY_BASE + 55;
|
||||
static const SpriteID SPR_TRAMWAY_FRONT_WIRES_STRAIGHT = SPR_TRAMWAY_BASE + 56;
|
||||
static const SpriteID SPR_TRAMWAY_BACK_WIRES_SLOPED = SPR_TRAMWAY_BASE + 72;
|
||||
static const SpriteID SPR_TRAMWAY_FRONT_WIRES_SLOPED = SPR_TRAMWAY_BASE + 68;
|
||||
static const SpriteID SPR_TRAMWAY_TUNNEL_WIRES = SPR_TRAMWAY_BASE + 80;
|
||||
static const SpriteID SPR_TRAMWAY_BRIDGE = SPR_TRAMWAY_BASE + 107;
|
||||
static const uint16 TRAMWAY_SPRITE_COUNT = 113;
|
||||
static const SpriteID SPR_TRAMWAY_DEPOT_NO_TRACK = SPR_TRAMWAY_BASE + 113;
|
||||
static const uint16 TRAMWAY_SPRITE_COUNT = 119;
|
||||
|
||||
/** One way road sprites */
|
||||
static const SpriteID SPR_ONEWAY_BASE = SPR_TRAMWAY_BASE + TRAMWAY_SPRITE_COUNT;
|
||||
|
@ -563,6 +565,7 @@ static const SpriteID SPR_ROAD_SLOPE_START = 1343;
|
|||
static const SpriteID SPR_ROAD_Y_SNOW = 1351;
|
||||
static const SpriteID SPR_ROAD_X_SNOW = 1352;
|
||||
/* see _road_sloped_sprites_offset in road_cmd.cpp for offsets for sloped road tiles */
|
||||
static const SpriteID SPR_ROAD_DEPOT = 1408;
|
||||
|
||||
static const SpriteID SPR_EXCAVATION_X = 1414;
|
||||
static const SpriteID SPR_EXCAVATION_Y = 1415;
|
||||
|
@ -1099,6 +1102,7 @@ static const SpriteID SPR_IMG_ZOOMIN = 735;
|
|||
static const SpriteID SPR_IMG_ZOOMOUT = 736;
|
||||
static const SpriteID SPR_IMG_BUILDRAIL = 727;
|
||||
static const SpriteID SPR_IMG_BUILDROAD = 728;
|
||||
static const SpriteID SPR_IMG_BUILDTRAMS = SPR_OPENTTD_BASE + 179;
|
||||
static const SpriteID SPR_IMG_BUILDWATER = 729;
|
||||
static const SpriteID SPR_IMG_BUILDAIR = 730;
|
||||
static const SpriteID SPR_IMG_LANDSCAPING = 4083;
|
||||
|
@ -1343,6 +1347,11 @@ static const SpriteID SPR_IMG_GOAL = SPR_OPENTTD_BASE + 171;
|
|||
static const SpriteID SPR_IMG_GOAL_COMPLETED = SPR_OPENTTD_BASE + 172;
|
||||
static const SpriteID SPR_IMG_GOAL_BROKEN_REF= SPR_OPENTTD_BASE + 173;
|
||||
|
||||
static const SpriteID SPR_IMG_CONVERT_ROAD = SPR_OPENTTD_BASE + 180;
|
||||
static const CursorID SPR_CURSOR_CONVERT_ROAD = SPR_OPENTTD_BASE + 181;
|
||||
static const SpriteID SPR_IMG_CONVERT_TRAM = SPR_OPENTTD_BASE + 182;
|
||||
static const CursorID SPR_CURSOR_CONVERT_TRAM = SPR_OPENTTD_BASE + 183;
|
||||
|
||||
/* intro_gui.cpp, genworld_gui.cpp */
|
||||
static const SpriteID SPR_SELECT_TEMPERATE = 4882;
|
||||
static const SpriteID SPR_SELECT_TEMPERATE_PUSHED = 4883;
|
||||
|
|
|
@ -64,7 +64,10 @@ struct TileDesc {
|
|||
uint64 dparam[2]; ///< Parameters of the \a str string
|
||||
StringID railtype; ///< Type of rail on the tile.
|
||||
uint16 rail_speed; ///< Speed limit of rail (bridges and track)
|
||||
uint16 road_speed; ///< Speed limit of road (bridges)
|
||||
StringID roadtype; ///< Type of road on the tile.
|
||||
uint16 road_speed; ///< Speed limit of road (bridges and track)
|
||||
StringID tramtype; ///< Type of tram on the tile.
|
||||
uint16 tram_speed; ///< Speed limit of tram (bridges and track)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "command_func.h"
|
||||
#include "vehicle_gui.h"
|
||||
#include "rail_gui.h"
|
||||
#include "road.h"
|
||||
#include "road_gui.h"
|
||||
#include "date_func.h"
|
||||
#include "vehicle_func.h"
|
||||
|
@ -64,6 +65,7 @@ uint _toolbar_width = 0;
|
|||
|
||||
RailType _last_built_railtype;
|
||||
RoadType _last_built_roadtype;
|
||||
RoadType _last_built_tramtype;
|
||||
|
||||
static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the current query is about to confirm.
|
||||
|
||||
|
@ -893,22 +895,7 @@ static CallBackFunction MenuClickBuildRail(int index)
|
|||
|
||||
static CallBackFunction ToolbarBuildRoadClick(Window *w)
|
||||
{
|
||||
const Company *c = Company::Get(_local_company);
|
||||
DropDownList list;
|
||||
|
||||
/* Road is always visible and available. */
|
||||
list.emplace_back(new DropDownListIconItem(SPR_IMG_ROAD_X_DIR, PAL_NONE, STR_ROAD_MENU_ROAD_CONSTRUCTION, ROADTYPE_ROAD, false));
|
||||
|
||||
/* Tram is only visible when there will be a tram, and available when that has been introduced. */
|
||||
Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
|
||||
if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
|
||||
if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
|
||||
|
||||
list.emplace_back(new DropDownListIconItem(SPR_IMG_TRAMWAY_X_DIR, PAL_NONE, STR_ROAD_MENU_TRAM_CONSTRUCTION, ROADTYPE_TRAM, !HasBit(c->avail_roadtypes, ROADTYPE_TRAM)));
|
||||
break;
|
||||
}
|
||||
ShowDropDownList(w, std::move(list), _last_built_roadtype, WID_TN_ROADS, 140, true, true);
|
||||
ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TN_ROADS, 140, true, true);
|
||||
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
@ -926,6 +913,28 @@ static CallBackFunction MenuClickBuildRoad(int index)
|
|||
return CBF_NONE;
|
||||
}
|
||||
|
||||
/* --- Tram button menu --- */
|
||||
|
||||
static CallBackFunction ToolbarBuildTramClick(Window *w)
|
||||
{
|
||||
ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TN_TRAMS, 140, true, true);
|
||||
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on the entry in the Build Tram menu.
|
||||
*
|
||||
* @param index RoadType to show the build toolbar for.
|
||||
* @return #CBF_NONE
|
||||
*/
|
||||
static CallBackFunction MenuClickBuildTram(int index)
|
||||
{
|
||||
_last_built_tramtype = (RoadType)index;
|
||||
ShowBuildRoadToolbar(_last_built_tramtype);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
/* --- Water button menu --- */
|
||||
|
||||
static CallBackFunction ToolbarBuildWaterClick(Window *w)
|
||||
|
@ -1251,9 +1260,41 @@ static CallBackFunction ToolbarScenGenIndustry(Window *w)
|
|||
|
||||
static CallBackFunction ToolbarScenBuildRoadClick(Window *w)
|
||||
{
|
||||
w->HandleButtonClick(WID_TE_ROADS);
|
||||
ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TE_ROADS, 140, true, true);
|
||||
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||
ShowBuildRoadScenToolbar();
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on the entry in the Build Road menu.
|
||||
*
|
||||
* @param index RoadType to show the build toolbar for.
|
||||
* @return #CBF_NONE
|
||||
*/
|
||||
static CallBackFunction ToolbarScenBuildRoad(int index)
|
||||
{
|
||||
_last_built_roadtype = (RoadType)index;
|
||||
ShowBuildRoadScenToolbar(_last_built_roadtype);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
static CallBackFunction ToolbarScenBuildTramClick(Window *w)
|
||||
{
|
||||
ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TE_TRAMS, 140, true, true);
|
||||
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle click on the entry in the Build Tram menu.
|
||||
*
|
||||
* @param index RoadType to show the build toolbar for.
|
||||
* @return #CBF_NONE
|
||||
*/
|
||||
static CallBackFunction ToolbarScenBuildTram(int index)
|
||||
{
|
||||
_last_built_tramtype = (RoadType)index;
|
||||
ShowBuildRoadScenToolbar(_last_built_tramtype);
|
||||
return CBF_NONE;
|
||||
}
|
||||
|
||||
|
@ -1311,12 +1352,13 @@ static MenuClickedProc * const _menu_clicked_procs[] = {
|
|||
nullptr, // 20
|
||||
MenuClickBuildRail, // 21
|
||||
MenuClickBuildRoad, // 22
|
||||
MenuClickBuildWater, // 23
|
||||
MenuClickBuildAir, // 24
|
||||
MenuClickForest, // 25
|
||||
MenuClickMusicWindow, // 26
|
||||
MenuClickNewspaper, // 27
|
||||
MenuClickHelp, // 28
|
||||
MenuClickBuildTram, // 23
|
||||
MenuClickBuildWater, // 24
|
||||
MenuClickBuildAir, // 25
|
||||
MenuClickForest, // 26
|
||||
MenuClickMusicWindow, // 27
|
||||
MenuClickNewspaper, // 28
|
||||
MenuClickHelp, // 29
|
||||
};
|
||||
|
||||
/** Full blown container to make it behave exactly as we want :) */
|
||||
|
@ -1772,6 +1814,7 @@ class NWidgetMainToolbarContainer : public NWidgetToolbarContainer {
|
|||
WID_TN_ZOOM_OUT,
|
||||
WID_TN_RAILS,
|
||||
WID_TN_ROADS,
|
||||
WID_TN_TRAMS,
|
||||
WID_TN_WATER,
|
||||
WID_TN_AIR,
|
||||
WID_TN_LANDSCAPE,
|
||||
|
@ -1832,6 +1875,7 @@ class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
|
|||
WID_TE_TOWN_GENERATE,
|
||||
WID_TE_INDUSTRY,
|
||||
WID_TE_ROADS,
|
||||
WID_TE_TRAMS,
|
||||
WID_TE_WATER,
|
||||
WID_TE_TREES,
|
||||
WID_TE_SIGNS,
|
||||
|
@ -1851,6 +1895,7 @@ class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
|
|||
WID_TE_TOWN_GENERATE,
|
||||
WID_TE_INDUSTRY,
|
||||
WID_TE_ROADS,
|
||||
WID_TE_TRAMS,
|
||||
WID_TE_WATER,
|
||||
WID_TE_TREES,
|
||||
WID_TE_SIGNS,
|
||||
|
@ -1864,6 +1909,7 @@ class NWidgetScenarioToolbarContainer : public NWidgetToolbarContainer {
|
|||
WID_TE_TOWN_GENERATE,
|
||||
WID_TE_INDUSTRY,
|
||||
WID_TE_ROADS,
|
||||
WID_TE_TRAMS,
|
||||
WID_TE_WATER,
|
||||
WID_TE_TREES,
|
||||
WID_TE_SIGNS,
|
||||
|
@ -1939,6 +1985,7 @@ static ToolbarButtonProc * const _toolbar_button_procs[] = {
|
|||
ToolbarZoomOutClick,
|
||||
ToolbarBuildRailClick,
|
||||
ToolbarBuildRoadClick,
|
||||
ToolbarBuildTramClick,
|
||||
ToolbarBuildWaterClick,
|
||||
ToolbarBuildAirClick,
|
||||
ToolbarForestClick,
|
||||
|
@ -1973,6 +2020,7 @@ enum MainToolbarHotkeys {
|
|||
MTHK_ZOOM_OUT,
|
||||
MTHK_BUILD_RAIL,
|
||||
MTHK_BUILD_ROAD,
|
||||
MTHK_BUILD_TRAM,
|
||||
MTHK_BUILD_DOCKS,
|
||||
MTHK_BUILD_AIRPORT,
|
||||
MTHK_BUILD_TREES,
|
||||
|
@ -2017,7 +2065,7 @@ struct MainToolbarWindow : Window {
|
|||
/* If spectator, disable all construction buttons
|
||||
* ie : Build road, rail, ships, airports and landscaping
|
||||
* Since enabled state is the default, just disable when needed */
|
||||
this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
|
||||
this->SetWidgetsDisabledState(_local_company == COMPANY_SPECTATOR, WID_TN_RAILS, WID_TN_ROADS, WID_TN_TRAMS, WID_TN_WATER, WID_TN_AIR, WID_TN_LANDSCAPE, WIDGET_LIST_END);
|
||||
/* disable company list drop downs, if there are no companies */
|
||||
this->SetWidgetsDisabledState(Company::GetNumItems() == 0, WID_TN_STATIONS, WID_TN_FINANCES, WID_TN_TRAINS, WID_TN_ROADVEHS, WID_TN_SHIPS, WID_TN_AIRCRAFT, WIDGET_LIST_END);
|
||||
|
||||
|
@ -2025,6 +2073,8 @@ struct MainToolbarWindow : Window {
|
|||
this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0);
|
||||
|
||||
this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN));
|
||||
this->SetWidgetDisabledState(WID_TN_ROADS, !CanBuildVehicleInfrastructure(VEH_ROAD, RTT_ROAD));
|
||||
this->SetWidgetDisabledState(WID_TN_TRAMS, !CanBuildVehicleInfrastructure(VEH_ROAD, RTT_TRAM));
|
||||
this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT));
|
||||
|
||||
this->DrawWidgets();
|
||||
|
@ -2068,6 +2118,7 @@ struct MainToolbarWindow : Window {
|
|||
case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break;
|
||||
case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break;
|
||||
case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype); break;
|
||||
case MTHK_BUILD_TRAM: if (CanBuildVehicleInfrastructure(VEH_ROAD, RTT_TRAM)) ShowBuildRoadToolbar(_last_built_tramtype); break;
|
||||
case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break;
|
||||
case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break;
|
||||
case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break;
|
||||
|
@ -2179,6 +2230,7 @@ static Hotkey maintoolbar_hotkeys[] = {
|
|||
Hotkey(_maintoolbar_zoomout_keys, "zoomout", MTHK_ZOOM_OUT),
|
||||
Hotkey(WKC_SHIFT | WKC_F7, "build_rail", MTHK_BUILD_RAIL),
|
||||
Hotkey(WKC_SHIFT | WKC_F8, "build_road", MTHK_BUILD_ROAD),
|
||||
Hotkey((uint16)0, "build_tram", MTHK_BUILD_TRAM),
|
||||
Hotkey(WKC_SHIFT | WKC_F9, "build_docks", MTHK_BUILD_DOCKS),
|
||||
Hotkey(WKC_SHIFT | WKC_F10, "build_airport", MTHK_BUILD_AIRPORT),
|
||||
Hotkey(WKC_SHIFT | WKC_F11, "build_trees", MTHK_BUILD_TREES),
|
||||
|
@ -2224,6 +2276,7 @@ static NWidgetBase *MakeMainToolbar(int *biggest_index)
|
|||
SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT
|
||||
SPR_IMG_BUILDRAIL, // WID_TN_RAILS
|
||||
SPR_IMG_BUILDROAD, // WID_TN_ROADS
|
||||
SPR_IMG_BUILDTRAMS, // WID_TN_TRAMS
|
||||
SPR_IMG_BUILDWATER, // WID_TN_WATER
|
||||
SPR_IMG_BUILDAIR, // WID_TN_AIR
|
||||
SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE
|
||||
|
@ -2282,14 +2335,15 @@ static MenuClickedProc * const _scen_toolbar_dropdown_procs[] = {
|
|||
nullptr, // 11
|
||||
nullptr, // 12
|
||||
nullptr, // 13
|
||||
nullptr, // 14
|
||||
nullptr, // 15
|
||||
ToolbarScenBuildRoad, // 14
|
||||
ToolbarScenBuildTram, // 15
|
||||
nullptr, // 16
|
||||
nullptr, // 17
|
||||
nullptr, // 18
|
||||
MenuClickMusicWindow, // 19
|
||||
MenuClickHelp, // 20
|
||||
nullptr, // 21
|
||||
nullptr, // 19
|
||||
MenuClickMusicWindow, // 20
|
||||
MenuClickHelp, // 21
|
||||
nullptr, // 22
|
||||
};
|
||||
|
||||
static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
|
||||
|
@ -2308,6 +2362,7 @@ static ToolbarButtonProc * const _scen_toolbar_button_procs[] = {
|
|||
ToolbarScenGenTown,
|
||||
ToolbarScenGenIndustry,
|
||||
ToolbarScenBuildRoadClick,
|
||||
ToolbarScenBuildTramClick,
|
||||
ToolbarScenBuildDocks,
|
||||
ToolbarScenPlantTrees,
|
||||
ToolbarScenPlaceSign,
|
||||
|
@ -2326,6 +2381,7 @@ enum MainToolbarEditorHotkeys {
|
|||
MTEHK_GENTOWN,
|
||||
MTEHK_GENINDUSTRY,
|
||||
MTEHK_BUILD_ROAD,
|
||||
MTEHK_BUILD_TRAM,
|
||||
MTEHK_BUILD_DOCKS,
|
||||
MTEHK_BUILD_TREES,
|
||||
MTEHK_SIGN,
|
||||
|
@ -2366,6 +2422,8 @@ struct ScenarioEditorToolbarWindow : Window {
|
|||
{
|
||||
this->SetWidgetDisabledState(WID_TE_DATE_BACKWARD, _settings_game.game_creation.starting_year <= MIN_YEAR);
|
||||
this->SetWidgetDisabledState(WID_TE_DATE_FORWARD, _settings_game.game_creation.starting_year >= MAX_YEAR);
|
||||
this->SetWidgetDisabledState(WID_TE_ROADS, (GetRoadTypes(true) & ~_roadtypes_type) == ROADTYPES_NONE);
|
||||
this->SetWidgetDisabledState(WID_TE_TRAMS, (GetRoadTypes(true) & _roadtypes_type) == ROADTYPES_NONE);
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
@ -2432,6 +2490,7 @@ struct ScenarioEditorToolbarWindow : Window {
|
|||
case MTEHK_GENTOWN: ToolbarScenGenTown(this); break;
|
||||
case MTEHK_GENINDUSTRY: ToolbarScenGenIndustry(this); break;
|
||||
case MTEHK_BUILD_ROAD: ToolbarScenBuildRoadClick(this); break;
|
||||
case MTEHK_BUILD_TRAM: ToolbarScenBuildTramClick(this); break;
|
||||
case MTEHK_BUILD_DOCKS: ToolbarScenBuildDocks(this); break;
|
||||
case MTEHK_BUILD_TREES: ToolbarScenPlantTrees(this); break;
|
||||
case MTEHK_SIGN: cbf = ToolbarScenPlaceSign(this); break;
|
||||
|
@ -2535,6 +2594,7 @@ static Hotkey scenedit_maintoolbar_hotkeys[] = {
|
|||
Hotkey(WKC_F5, "gen_town", MTEHK_GENTOWN),
|
||||
Hotkey(WKC_F6, "gen_industry", MTEHK_GENINDUSTRY),
|
||||
Hotkey(WKC_F7, "build_road", MTEHK_BUILD_ROAD),
|
||||
Hotkey((uint16)0, "build_tram", MTEHK_BUILD_TRAM),
|
||||
Hotkey(WKC_F8, "build_docks", MTEHK_BUILD_DOCKS),
|
||||
Hotkey(WKC_F9, "build_trees", MTEHK_BUILD_TREES),
|
||||
Hotkey(WKC_F10, "build_sign", MTEHK_SIGN),
|
||||
|
@ -2577,7 +2637,8 @@ static const NWidgetPart _nested_toolb_scen_inner_widgets[] = {
|
|||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetDataTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetDataTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetDataTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_ROADS), SetDataTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_TRAMS), SetDataTip(SPR_IMG_BUILDTRAMS, STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_WATER), SetDataTip(SPR_IMG_BUILDWATER, STR_TOOLBAR_TOOLTIP_BUILD_SHIP_DOCKS),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TREES), SetDataTip(SPR_IMG_PLANTTREES, STR_SCENEDIT_TOOLBAR_PLANT_TREES),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_SIGNS), SetDataTip(SPR_IMG_SIGN, STR_SCENEDIT_TOOLBAR_PLACE_SIGN),
|
||||
|
@ -2609,6 +2670,7 @@ void AllocateToolbar()
|
|||
{
|
||||
/* Clean old GUI values; railtype is (re)set by rail_gui.cpp */
|
||||
_last_built_roadtype = ROADTYPE_ROAD;
|
||||
_last_built_tramtype = ROADTYPE_TRAM;
|
||||
|
||||
if (_game_mode == GM_EDITOR) {
|
||||
new ScenarioEditorToolbarWindow(&_toolb_scen_desc);
|
||||
|
|
|
@ -299,4 +299,6 @@ static inline uint16 TownTicksToGameTicks(uint16 ticks) {
|
|||
|
||||
extern CargoTypes _town_cargoes_accepted;
|
||||
|
||||
RoadType GetTownRoadType(const Town *t);
|
||||
|
||||
#endif /* TOWN_H */
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
/** @file town_cmd.cpp Handling of town tiles. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "road.h"
|
||||
#include "road_internal.h" /* Cleaning up road bits */
|
||||
#include "road_cmd.h"
|
||||
#include "landscape.h"
|
||||
|
@ -891,7 +892,38 @@ static RoadBits GetTownRoadBits(TileIndex tile)
|
|||
{
|
||||
if (IsRoadDepotTile(tile) || IsStandardRoadStopTile(tile)) return ROAD_NONE;
|
||||
|
||||
return GetAnyRoadBits(tile, ROADTYPE_ROAD, true);
|
||||
return GetAnyRoadBits(tile, RTT_ROAD, true);
|
||||
}
|
||||
|
||||
RoadType GetTownRoadType(const Town *t)
|
||||
{
|
||||
RoadType best_rt = ROADTYPE_ROAD;
|
||||
const RoadTypeInfo *best = nullptr;
|
||||
const uint16 assume_max_speed = 50;
|
||||
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
if (RoadTypeIsTram(rt)) continue;
|
||||
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||
|
||||
/* Unused road type. */
|
||||
if (rti->label == 0) continue;
|
||||
|
||||
/* Can town build this road. */
|
||||
if (!HasBit(rti->flags, ROTF_TOWN_BUILD)) continue;
|
||||
|
||||
/* Not yet introduced at this date. */
|
||||
if (IsInsideMM(rti->introduction_date, 0, MAX_DAY) && rti->introduction_date > _date) continue;
|
||||
|
||||
if (best != nullptr) {
|
||||
if ((rti->max_speed == 0 ? assume_max_speed : rti->max_speed) < (best->max_speed == 0 ? assume_max_speed : best->max_speed)) continue;
|
||||
}
|
||||
|
||||
best_rt = rt;
|
||||
best = rti;
|
||||
}
|
||||
|
||||
return best_rt;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -950,7 +982,8 @@ static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
|
|||
/* No, try if we are able to build a road piece there.
|
||||
* If that fails clear the land, and if that fails exit.
|
||||
* This is to make sure that we can build a road here later. */
|
||||
if (DoCommand(tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X), 0, DC_AUTO, CMD_BUILD_ROAD).Failed() &&
|
||||
RoadType rt = GetTownRoadType(t);
|
||||
if (DoCommand(tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X) | (rt << 4), 0, DC_AUTO, CMD_BUILD_ROAD).Failed() &&
|
||||
DoCommand(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR).Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1118,7 +1151,8 @@ static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
|
|||
*/
|
||||
static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd)
|
||||
{
|
||||
if (DoCommand(tile, rcmd, t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded()) {
|
||||
RoadType rt = GetTownRoadType(t);
|
||||
if (DoCommand(tile, rcmd | (rt << 4), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD).Succeeded()) {
|
||||
_grow_town_result = GROWTH_SUCCEED;
|
||||
return true;
|
||||
}
|
||||
|
@ -1181,8 +1215,9 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi
|
|||
byte bridge_type = RandomRange(MAX_BRIDGES - 1);
|
||||
|
||||
/* Can we actually build the bridge? */
|
||||
if (DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 15, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
|
||||
DoCommand(tile, bridge_tile, bridge_type | ROADTYPES_ROAD << 8 | TRANSPORT_ROAD << 15, DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE);
|
||||
RoadType rt = GetTownRoadType(t);
|
||||
if (DoCommand(tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
|
||||
DoCommand(tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE);
|
||||
_grow_town_result = GROWTH_SUCCEED;
|
||||
return true;
|
||||
}
|
||||
|
@ -1191,6 +1226,37 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether at least one surrounding roads allows to build a house here
|
||||
*
|
||||
* @param t the tile where the house will be built
|
||||
* @return true if at least one surrounding roadtype allows building houses here
|
||||
*/
|
||||
static inline bool RoadTypesAllowHouseHere(TileIndex t)
|
||||
{
|
||||
static const TileIndexDiffC tiles[] = { {-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1} };
|
||||
bool allow = false;
|
||||
|
||||
for (const TileIndexDiffC *ptr = tiles; ptr != endof(tiles); ++ptr) {
|
||||
TileIndex cur_tile = t + ToTileIndexDiff(*ptr);
|
||||
if (!IsValidTile(cur_tile)) continue;
|
||||
|
||||
if (!(IsTileType(cur_tile, MP_ROAD) || IsTileType(cur_tile, MP_STATION))) continue;
|
||||
allow = true;
|
||||
|
||||
RoadType road_rt = GetRoadTypeRoad(cur_tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(cur_tile);
|
||||
if (road_rt != INVALID_ROADTYPE && !HasBit(GetRoadTypeInfo(road_rt)->flags, ROTF_NO_HOUSES)) return true;
|
||||
if (tram_rt != INVALID_ROADTYPE && !HasBit(GetRoadTypeInfo(tram_rt)->flags, ROTF_NO_HOUSES)) return true;
|
||||
}
|
||||
|
||||
/* If no road was found surrounding the tile we can allow building the house since there is
|
||||
* nothing which forbids it, if a road was found but the execution reached this point, then
|
||||
* all the found roads don't allow houses to be built */
|
||||
return !allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grows the given town.
|
||||
* There are at the moment 3 possible way's for
|
||||
|
@ -1369,6 +1435,8 @@ static void GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection t
|
|||
}
|
||||
}
|
||||
|
||||
allow_house &= RoadTypesAllowHouseHere(house_tile);
|
||||
|
||||
if (allow_house) {
|
||||
/* Build a house, but not if there already is a house there. */
|
||||
if (!IsTileType(house_tile, MP_HOUSE)) {
|
||||
|
@ -1508,14 +1576,14 @@ static bool GrowTownAtRoad(Town *t, TileIndex tile)
|
|||
}
|
||||
tile = TileAddByDiagDir(tile, target_dir);
|
||||
|
||||
if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, ROADTYPE_ROAD)) {
|
||||
if (IsTileType(tile, MP_ROAD) && !IsRoadDepot(tile) && HasTileRoadType(tile, RTT_ROAD)) {
|
||||
/* Don't allow building over roads of other cities */
|
||||
if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN) && Town::GetByTile(tile) != t) {
|
||||
if (IsRoadOwner(tile, RTT_ROAD, OWNER_TOWN) && Town::GetByTile(tile) != t) {
|
||||
return false;
|
||||
} else if (IsRoadOwner(tile, ROADTYPE_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) {
|
||||
} else if (IsRoadOwner(tile, RTT_ROAD, OWNER_NONE) && _game_mode == GM_EDITOR) {
|
||||
/* If we are in the SE, and this road-piece has no town owner yet, it just found an
|
||||
* owner :) (happy happy happy road now) */
|
||||
SetRoadOwner(tile, ROADTYPE_ROAD, OWNER_TOWN);
|
||||
SetRoadOwner(tile, RTT_ROAD, OWNER_TOWN);
|
||||
SetTownIndex(tile, t->index);
|
||||
}
|
||||
}
|
||||
|
@ -1589,7 +1657,8 @@ static bool GrowTown(Town *t)
|
|||
/* Only work with plain land that not already has a house */
|
||||
if (!IsTileType(tile, MP_HOUSE) && IsTileFlat(tile)) {
|
||||
if (DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR).Succeeded()) {
|
||||
DoCommand(tile, GenRandomRoadBits(), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD);
|
||||
RoadType rt = GetTownRoadType(t);
|
||||
DoCommand(tile, GenRandomRoadBits() | (rt << 4), t->index, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD);
|
||||
cur_company.Restore();
|
||||
return true;
|
||||
}
|
||||
|
@ -2192,6 +2261,9 @@ static inline bool CanBuildHouseHere(TileIndex tile, bool noslope)
|
|||
Slope slope = GetTileSlope(tile);
|
||||
if ((noslope && slope != SLOPE_FLAT) || IsSteepSlope(slope)) return false;
|
||||
|
||||
/* at least one RoadTypes allow building the house here? */
|
||||
if (!RoadTypesAllowHouseHere(tile)) return false;
|
||||
|
||||
/* building under a bridge? */
|
||||
if (IsBridgeAbove(tile)) return false;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir);
|
|||
* @param d the direction facing out of the tunnel
|
||||
* @param r the road type used in the tunnel
|
||||
*/
|
||||
static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTypes r)
|
||||
static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadType road_rt, RoadType tram_rt)
|
||||
{
|
||||
SetTileType(t, MP_TUNNELBRIDGE);
|
||||
SetTileOwner(t, o);
|
||||
|
@ -59,9 +59,9 @@ static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d, RoadTyp
|
|||
SB(_me[t].m6, 2, 4, 0);
|
||||
_me[t].m7 = 0;
|
||||
_me[t].m8 = 0;
|
||||
SetRoadOwner(t, ROADTYPE_ROAD, o);
|
||||
if (o != OWNER_TOWN) SetRoadOwner(t, ROADTYPE_TRAM, o);
|
||||
SetRoadTypes(t, r);
|
||||
SetRoadOwner(t, RTT_ROAD, o);
|
||||
if (o != OWNER_TOWN) SetRoadOwner(t, RTT_TRAM, o);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define TUNNELBRIDGE_H
|
||||
|
||||
#include "map_func.h"
|
||||
#include "tile_map.h"
|
||||
|
||||
void MarkBridgeDirty(TileIndex begin, TileIndex end, DiagDirection direction, uint bridge_height);
|
||||
void MarkBridgeDirty(TileIndex tile);
|
||||
|
@ -33,6 +34,18 @@ static inline uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
|
|||
return abs(x2 + y2 - x1 - y1) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ownership of the bridge/tunnel ramps
|
||||
* @param begin The begin of the tunnel or bridge.
|
||||
* @param end The end of the tunnel or bridge.
|
||||
* @param owner The new owner to set
|
||||
*/
|
||||
static inline void SetTunnelBridgeOwner(TileIndex begin, TileIndex end, Owner owner)
|
||||
{
|
||||
SetTileOwner(begin, owner);
|
||||
SetTileOwner(end, owner);
|
||||
}
|
||||
|
||||
extern TileIndex _build_tunnel_endtile;
|
||||
|
||||
#endif /* TUNNELBRIDGE_H */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "pbs.h"
|
||||
#include "company_base.h"
|
||||
#include "newgrf_railtype.h"
|
||||
#include "newgrf_roadtype.h"
|
||||
#include "object_base.h"
|
||||
#include "water.h"
|
||||
#include "company_gui.h"
|
||||
|
@ -230,7 +231,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
CompanyID company = _current_company;
|
||||
|
||||
RailType railtype = INVALID_RAILTYPE;
|
||||
RoadTypes roadtypes = ROADTYPES_NONE;
|
||||
RoadType roadtype = INVALID_ROADTYPE;
|
||||
|
||||
/* unpack parameters */
|
||||
BridgeType bridge_type = GB(p2, 0, 8);
|
||||
|
@ -242,8 +243,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
/* type of bridge */
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_ROAD:
|
||||
roadtypes = Extract<RoadTypes, 8, 2>(p2);
|
||||
if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(company, roadtypes)) return CMD_ERROR;
|
||||
roadtype = Extract<RoadType, 8, 6>(p2);
|
||||
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case TRANSPORT_RAIL:
|
||||
|
@ -313,16 +314,41 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
Owner owner;
|
||||
bool is_new_owner;
|
||||
RoadType road_rt = INVALID_ROADTYPE;
|
||||
RoadType tram_rt = INVALID_ROADTYPE;
|
||||
if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
|
||||
GetOtherBridgeEnd(tile_start) == tile_end &&
|
||||
GetTunnelBridgeTransportType(tile_start) == transport_type) {
|
||||
/* Replace a current bridge. */
|
||||
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_RAIL:
|
||||
/* Keep the reservation, the path stays valid. */
|
||||
pbs_reservation = HasTunnelBridgeReservation(tile_start);
|
||||
break;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
/* Do not remove road types when upgrading a bridge */
|
||||
road_rt = GetRoadTypeRoad(tile_start);
|
||||
tram_rt = GetRoadTypeTram(tile_start);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* If this is a railway bridge, make sure the railtypes match. */
|
||||
if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
|
||||
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
}
|
||||
|
||||
/* If this is a road bridge, make sure the roadtype matches. */
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
RoadType existing_rt = RoadTypeIsRoad(roadtype) ? road_rt : tram_rt;
|
||||
if (existing_rt != roadtype && existing_rt != INVALID_ROADTYPE) {
|
||||
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do not replace town bridges with lower speed bridges, unless in scenario editor. */
|
||||
if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
|
||||
GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed &&
|
||||
|
@ -338,7 +364,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
}
|
||||
|
||||
/* Do not replace the bridge with the same bridge type. */
|
||||
if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || (roadtypes & ~GetRoadTypes(tile_start)) == 0)) {
|
||||
if (!(flags & DC_QUERY_COST) && (bridge_type == GetBridgeType(tile_start)) && (transport_type != TRANSPORT_ROAD || road_rt == roadtype || tram_rt == roadtype)) {
|
||||
return_cmd_error(STR_ERROR_ALREADY_BUILT);
|
||||
}
|
||||
|
||||
|
@ -353,20 +379,6 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
/* If bridge belonged to bankrupt company, it has a new owner now */
|
||||
is_new_owner = (owner == OWNER_NONE);
|
||||
if (is_new_owner) owner = company;
|
||||
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_RAIL:
|
||||
/* Keep the reservation, the path stays valid. */
|
||||
pbs_reservation = HasTunnelBridgeReservation(tile_start);
|
||||
break;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
/* Do not remove road types when upgrading a bridge */
|
||||
roadtypes |= GetRoadTypes(tile_start);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
/* Build a new bridge. */
|
||||
|
||||
|
@ -471,6 +483,13 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
is_new_owner = true;
|
||||
}
|
||||
|
||||
bool hasroad = road_rt != INVALID_ROADTYPE;
|
||||
bool hastram = tram_rt != INVALID_ROADTYPE;
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
if (RoadTypeIsRoad(roadtype)) road_rt = roadtype;
|
||||
if (RoadTypeIsTram(roadtype)) tram_rt = roadtype;
|
||||
}
|
||||
|
||||
/* do the drill? */
|
||||
if (flags & DC_EXEC) {
|
||||
DiagDirection dir = AxisToDiagDir(direction);
|
||||
|
@ -487,24 +506,26 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
break;
|
||||
|
||||
case TRANSPORT_ROAD: {
|
||||
RoadTypes prev_roadtypes = IsBridgeTile(tile_start) ? GetRoadTypes(tile_start) : ROADTYPES_NONE;
|
||||
if (is_new_owner) {
|
||||
/* Also give unowned present roadtypes to new owner */
|
||||
if (HasBit(prev_roadtypes, ROADTYPE_ROAD) && GetRoadOwner(tile_start, ROADTYPE_ROAD) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_ROAD);
|
||||
if (HasBit(prev_roadtypes, ROADTYPE_TRAM) && GetRoadOwner(tile_start, ROADTYPE_TRAM) == OWNER_NONE) ClrBit(prev_roadtypes, ROADTYPE_TRAM);
|
||||
if (hasroad && GetRoadOwner(tile_start, RTT_ROAD) == OWNER_NONE) hasroad = false;
|
||||
if (hastram && GetRoadOwner(tile_start, RTT_TRAM) == OWNER_NONE) hastram = false;
|
||||
}
|
||||
if (c != nullptr) {
|
||||
/* Add all new road types to the company infrastructure counter. */
|
||||
RoadType new_rt;
|
||||
FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ prev_roadtypes) {
|
||||
if (!hasroad && road_rt != INVALID_ROADTYPE) {
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
c->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
c->infrastructure.road[road_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
}
|
||||
if (!hastram && tram_rt != INVALID_ROADTYPE) {
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
c->infrastructure.road[tram_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
}
|
||||
}
|
||||
Owner owner_road = HasBit(prev_roadtypes, ROADTYPE_ROAD) ? GetRoadOwner(tile_start, ROADTYPE_ROAD) : company;
|
||||
Owner owner_tram = HasBit(prev_roadtypes, ROADTYPE_TRAM) ? GetRoadOwner(tile_start, ROADTYPE_TRAM) : company;
|
||||
MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, roadtypes);
|
||||
MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), roadtypes);
|
||||
Owner owner_road = hasroad ? GetRoadOwner(tile_start, RTT_ROAD) : company;
|
||||
Owner owner_tram = hastram ? GetRoadOwner(tile_start, RTT_TRAM) : company;
|
||||
MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, road_rt, tram_rt);
|
||||
MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), road_rt, tram_rt);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -538,7 +559,15 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
bridge_len += 2; // begin and end tiles/ramps
|
||||
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_ROAD: cost.AddCost(bridge_len * _price[PR_BUILD_ROAD] * 2 * CountBits(roadtypes)); break;
|
||||
case TRANSPORT_ROAD:
|
||||
if (road_rt != INVALID_ROADTYPE) {
|
||||
cost.AddCost(bridge_len * 2 * RoadBuildCost(road_rt));
|
||||
}
|
||||
if (tram_rt != INVALID_ROADTYPE) {
|
||||
cost.AddCost(bridge_len * 2 * RoadBuildCost(tram_rt));
|
||||
}
|
||||
break;
|
||||
|
||||
case TRANSPORT_RAIL: cost.AddCost(bridge_len * RailBuildCost(railtype)); break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -562,7 +591,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
|||
* Build Tunnel.
|
||||
* @param start_tile start tile of tunnel
|
||||
* @param flags type of operation
|
||||
* @param p1 bit 0-5 railtype or roadtypes
|
||||
* @param p1 bit 0-5 railtype or roadtype
|
||||
* bit 8-9 transport type
|
||||
* @param p2 unused
|
||||
* @param text unused
|
||||
|
@ -573,9 +602,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||
CompanyID company = _current_company;
|
||||
|
||||
TransportType transport_type = Extract<TransportType, 8, 2>(p1);
|
||||
|
||||
RailType railtype = INVALID_RAILTYPE;
|
||||
RoadTypes rts = ROADTYPES_NONE;
|
||||
RoadType roadtype = INVALID_ROADTYPE;
|
||||
_build_tunnel_endtile = 0;
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_RAIL:
|
||||
|
@ -584,8 +612,8 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||
break;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
rts = Extract<RoadTypes, 0, 2>(p1);
|
||||
if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(company, rts)) return CMD_ERROR;
|
||||
roadtype = Extract<RoadType, 0, 6>(p1);
|
||||
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
default: return CMD_ERROR;
|
||||
|
@ -713,7 +741,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||
|
||||
/* Pay for the rail/road in the tunnel including entrances */
|
||||
switch (transport_type) {
|
||||
case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * _price[PR_BUILD_ROAD] * 2); break;
|
||||
case TRANSPORT_ROAD: cost.AddCost((tiles + 2) * RoadBuildCost(roadtype) * 2); break;
|
||||
case TRANSPORT_RAIL: cost.AddCost((tiles + 2) * RailBuildCost(railtype)); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
@ -722,20 +750,17 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1,
|
|||
Company *c = Company::GetIfValid(company);
|
||||
uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
if (transport_type == TRANSPORT_RAIL) {
|
||||
if (!IsTunnelTile(start_tile) && c != nullptr) c->infrastructure.rail[railtype] += num_pieces;
|
||||
if (c != nullptr) c->infrastructure.rail[railtype] += num_pieces;
|
||||
MakeRailTunnel(start_tile, company, direction, railtype);
|
||||
MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype);
|
||||
AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company);
|
||||
YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
|
||||
} else {
|
||||
if (c != nullptr) {
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) {
|
||||
c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits.
|
||||
}
|
||||
}
|
||||
MakeRoadTunnel(start_tile, company, direction, rts);
|
||||
MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), rts);
|
||||
if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits.
|
||||
RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE;
|
||||
RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE;
|
||||
MakeRoadTunnel(start_tile, company, direction, road_rt, tram_rt);
|
||||
MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), road_rt, tram_rt);
|
||||
}
|
||||
DirtyCompanyInfrastructureWindows(company);
|
||||
}
|
||||
|
@ -756,12 +781,13 @@ static inline CommandCost CheckAllowRemoveTunnelBridge(TileIndex tile)
|
|||
|
||||
switch (GetTunnelBridgeTransportType(tile)) {
|
||||
case TRANSPORT_ROAD: {
|
||||
RoadTypes rts = GetRoadTypes(tile);
|
||||
RoadType road_rt = GetRoadTypeRoad(tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(tile);
|
||||
Owner road_owner = _current_company;
|
||||
Owner tram_owner = _current_company;
|
||||
|
||||
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
|
||||
if (road_rt != INVALID_ROADTYPE) road_owner = GetRoadOwner(tile, RTT_ROAD);
|
||||
if (tram_rt != INVALID_ROADTYPE) tram_owner = GetRoadOwner(tile, RTT_TRAM);
|
||||
|
||||
/* We can remove unowned road and if the town allows it */
|
||||
if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
|
||||
|
@ -856,15 +882,9 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
|
|||
|
||||
if (v != nullptr) TryPathReserve(v);
|
||||
} else {
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
|
||||
if (c != nullptr) {
|
||||
c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
DirtyCompanyInfrastructureWindows(c->index);
|
||||
}
|
||||
}
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
|
||||
UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
|
||||
|
||||
DoClearSquare(tile);
|
||||
DoClearSquare(endtile);
|
||||
|
@ -928,15 +948,9 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
|
|||
if (rail) {
|
||||
if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
} else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) {
|
||||
RoadType rt;
|
||||
FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
|
||||
Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
|
||||
if (c != nullptr) {
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
DirtyCompanyInfrastructureWindows(c->index);
|
||||
}
|
||||
}
|
||||
/* A full diagonal road tile has two road bits. */
|
||||
UpdateCompanyRoadInfrastructure(GetRoadTypeRoad(tile), GetRoadOwner(tile, RTT_ROAD), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
|
||||
UpdateCompanyRoadInfrastructure(GetRoadTypeTram(tile), GetRoadOwner(tile, RTT_TRAM), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR));
|
||||
} else { // Aqueduct
|
||||
if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.water -= len * TUNNELBRIDGE_TRACKBIT_FACTOR;
|
||||
}
|
||||
|
@ -1082,19 +1096,90 @@ static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis
|
|||
}
|
||||
|
||||
/**
|
||||
* Draws the trambits over an already drawn (lower end) of a bridge.
|
||||
* @param x the x of the bridge
|
||||
* @param y the y of the bridge
|
||||
* @param z the z of the bridge
|
||||
* @param offset number representing whether to level or sloped and the direction
|
||||
* @param overlay do we want to still see the road?
|
||||
* @param head are we drawing bridge head?
|
||||
* Draws the road and trambits over an already drawn (lower end) of a bridge.
|
||||
* @param head_tile bridge head tile with roadtype information
|
||||
* @param x the x of the bridge
|
||||
* @param y the y of the bridge
|
||||
* @param z the z of the bridge
|
||||
* @param offset sprite offset identifying flat to sloped bridge tiles
|
||||
* @param head are we drawing bridge head?
|
||||
*/
|
||||
static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bool head)
|
||||
static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head)
|
||||
{
|
||||
static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
|
||||
static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
|
||||
static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
|
||||
RoadType road_rt = GetRoadTypeRoad(head_tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(head_tile);
|
||||
const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
|
||||
const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
|
||||
|
||||
SpriteID seq_back[4] = { 0 };
|
||||
bool trans_back[4] = { false };
|
||||
SpriteID seq_front[4] = { 0 };
|
||||
bool trans_front[4] = { false };
|
||||
|
||||
static const SpriteID overlay_offsets[6] = { 0, 1, 11, 12, 13, 14 };
|
||||
static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
|
||||
static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
|
||||
|
||||
if (head || !IsInvisibilitySet(TO_BRIDGES)) {
|
||||
/* Road underlay takes precendence over tram */
|
||||
trans_back[0] = !head && IsTransparencySet(TO_BRIDGES);
|
||||
if (road_rti != nullptr) {
|
||||
if (road_rti->UsesOverlay()) {
|
||||
seq_back[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
|
||||
}
|
||||
} else if (tram_rti != nullptr) {
|
||||
if (tram_rti->UsesOverlay()) {
|
||||
seq_back[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset;
|
||||
} else {
|
||||
seq_back[0] = SPR_TRAMWAY_BRIDGE + offset;
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw road overlay */
|
||||
trans_back[1] = !head && IsTransparencySet(TO_BRIDGES);
|
||||
if (road_rti != nullptr) {
|
||||
if (road_rti->UsesOverlay()) {
|
||||
seq_back[1] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
if (seq_back[1] != 0) seq_back[1] += overlay_offsets[offset];
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw tram overlay */
|
||||
trans_back[2] = !head && IsTransparencySet(TO_BRIDGES);
|
||||
if (tram_rti != nullptr) {
|
||||
if (tram_rti->UsesOverlay()) {
|
||||
seq_back[2] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_OVERLAY, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
if (seq_back[2] != 0) seq_back[2] += overlay_offsets[offset];
|
||||
} else if (road_rti != nullptr) {
|
||||
seq_back[2] = SPR_TRAMWAY_OVERLAY + overlay_offsets[offset];
|
||||
}
|
||||
}
|
||||
|
||||
/* Road catenary takes precendence over tram */
|
||||
trans_back[3] = IsTransparencySet(TO_CATENARY);
|
||||
trans_front[0] = IsTransparencySet(TO_CATENARY);
|
||||
if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
|
||||
seq_back[3] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
seq_front[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
if (seq_back[3] == 0 || seq_front[0] == 0) {
|
||||
seq_back[3] = SPR_TRAMWAY_BASE + back_offsets[offset];
|
||||
seq_front[0] = SPR_TRAMWAY_BASE + front_offsets[offset];
|
||||
} else {
|
||||
seq_back[3] += 23 + offset;
|
||||
seq_front[0] += 23 + offset;
|
||||
}
|
||||
} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
|
||||
seq_back[3] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_CATENARY_BACK, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
seq_front[0] = GetCustomRoadSprite(tram_rti, head_tile, ROTSG_CATENARY_FRONT, head ? TCX_NORMAL : TCX_ON_BRIDGE);
|
||||
if (seq_back[3] == 0 || seq_front[0] == 0) {
|
||||
seq_back[3] = SPR_TRAMWAY_BASE + back_offsets[offset];
|
||||
seq_front[0] = SPR_TRAMWAY_BASE + front_offsets[offset];
|
||||
} else {
|
||||
seq_back[3] += 23 + offset;
|
||||
seq_front[0] += 23 + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
|
||||
static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
|
||||
|
@ -1103,28 +1188,25 @@ static void DrawBridgeTramBits(int x, int y, int z, int offset, bool overlay, bo
|
|||
|
||||
/* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
|
||||
* The bounding boxes here are the same as for bridge front/roof */
|
||||
if (head || !IsInvisibilitySet(TO_BRIDGES)) {
|
||||
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
|
||||
x, y, size_x[offset], size_y[offset], 0x28, z,
|
||||
!head && IsTransparencySet(TO_BRIDGES));
|
||||
}
|
||||
|
||||
/* Do not draw catenary if it is set invisible */
|
||||
if (!IsInvisibilitySet(TO_CATENARY)) {
|
||||
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
|
||||
x, y, size_x[offset], size_y[offset], 0x28, z,
|
||||
IsTransparencySet(TO_CATENARY));
|
||||
for (uint i = 0; i < lengthof(seq_back); ++i) {
|
||||
if (seq_back[i] != 0) {
|
||||
AddSortableSpriteToDraw(seq_back[i], PAL_NONE,
|
||||
x, y, size_x[offset], size_y[offset], 0x28, z,
|
||||
trans_back[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start a new SpriteCombine for the front part */
|
||||
EndSpriteCombine();
|
||||
StartSpriteCombine();
|
||||
|
||||
/* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
|
||||
if (!IsInvisibilitySet(TO_CATENARY)) {
|
||||
AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
|
||||
x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
|
||||
IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
|
||||
for (uint i = 0; i < lengthof(seq_front); ++i) {
|
||||
if (seq_front[i] != 0) {
|
||||
AddSortableSpriteToDraw(seq_front[i], PAL_NONE,
|
||||
x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
|
||||
trans_front[i],
|
||||
front_bb_offset_x[offset], front_bb_offset_y[offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1188,19 +1270,36 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
|||
DrawGroundSprite(image, PAL_NONE);
|
||||
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
RoadTypes rts = GetRoadTypes(ti->tile);
|
||||
RoadType road_rt = GetRoadTypeRoad(ti->tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(ti->tile);
|
||||
const RoadTypeInfo *road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
|
||||
const RoadTypeInfo *tram_rti = tram_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(tram_rt);
|
||||
uint sprite_offset = DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? 1 : 0;
|
||||
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) {
|
||||
static const SpriteID tunnel_sprites[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
|
||||
DrawRoadOverlays(ti, PAL_NONE, road_rti, tram_rti, sprite_offset, sprite_offset);
|
||||
|
||||
DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
|
||||
|
||||
/* Do not draw wires if they are invisible */
|
||||
if (!IsInvisibilitySet(TO_CATENARY)) {
|
||||
catenary = true;
|
||||
StartSpriteCombine();
|
||||
AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
|
||||
/* Road catenary takes precendence over tram */
|
||||
SpriteID catenary_sprite_base = 0;
|
||||
if (road_rti != nullptr && HasRoadCatenaryDrawn(road_rt)) {
|
||||
catenary_sprite_base = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_CATENARY_FRONT);
|
||||
if (catenary_sprite_base == 0) {
|
||||
catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
|
||||
} else {
|
||||
catenary_sprite_base += 19;
|
||||
}
|
||||
} else if (tram_rti != nullptr && HasRoadCatenaryDrawn(tram_rt)) {
|
||||
catenary_sprite_base = GetCustomRoadSprite(tram_rti, ti->tile, ROTSG_CATENARY_FRONT);
|
||||
if (catenary_sprite_base == 0) {
|
||||
catenary_sprite_base = SPR_TRAMWAY_TUNNEL_WIRES;
|
||||
} else {
|
||||
catenary_sprite_base += 19;
|
||||
}
|
||||
}
|
||||
|
||||
if (catenary_sprite_base != 0) {
|
||||
catenary = true;
|
||||
StartSpriteCombine();
|
||||
AddSortableSpriteToDraw(catenary_sprite_base + tunnelbridge_direction, PAL_NONE, ti->x, ti->y, BB_data[10], BB_data[11], TILE_HEIGHT, ti->z, IsTransparencySet(TO_CATENARY), BB_data[8], BB_data[9], BB_Z_SEPARATOR);
|
||||
}
|
||||
} else {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
|
||||
|
@ -1294,20 +1393,18 @@ static void DrawTile_TunnelBridge(TileInfo *ti)
|
|||
AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
|
||||
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
RoadTypes rts = GetRoadTypes(ti->tile);
|
||||
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) {
|
||||
uint offset = tunnelbridge_direction;
|
||||
int z = ti->z;
|
||||
if (ti->tileh != SLOPE_FLAT) {
|
||||
offset = (offset + 1) & 1;
|
||||
z += TILE_HEIGHT;
|
||||
} else {
|
||||
offset += 2;
|
||||
}
|
||||
/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
|
||||
DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
|
||||
uint offset = tunnelbridge_direction;
|
||||
int z = ti->z;
|
||||
if (ti->tileh != SLOPE_FLAT) {
|
||||
offset = (offset + 1) & 1;
|
||||
z += TILE_HEIGHT;
|
||||
} else {
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
|
||||
DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true);
|
||||
|
||||
EndSpriteCombine();
|
||||
} else if (transport_type == TRANSPORT_RAIL) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
|
||||
|
@ -1465,15 +1562,8 @@ void DrawBridgeMiddle(const TileInfo *ti)
|
|||
psid++;
|
||||
|
||||
if (transport_type == TRANSPORT_ROAD) {
|
||||
RoadTypes rts = GetRoadTypes(rampsouth);
|
||||
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) {
|
||||
/* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
|
||||
DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false);
|
||||
} else {
|
||||
EndSpriteCombine();
|
||||
StartSpriteCombine();
|
||||
}
|
||||
/* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */
|
||||
DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false);
|
||||
} else if (transport_type == TRANSPORT_RAIL) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth));
|
||||
if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) {
|
||||
|
@ -1593,9 +1683,20 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
|
|||
|
||||
Owner road_owner = INVALID_OWNER;
|
||||
Owner tram_owner = INVALID_OWNER;
|
||||
RoadTypes rts = GetRoadTypes(tile);
|
||||
if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
|
||||
if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
|
||||
RoadType road_rt = GetRoadTypeRoad(tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(tile);
|
||||
if (road_rt != INVALID_ROADTYPE) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(road_rt);
|
||||
td->roadtype = rti->strings.name;
|
||||
td->road_speed = rti->max_speed / 2;
|
||||
road_owner = GetRoadOwner(tile, RTT_ROAD);
|
||||
}
|
||||
if (tram_rt != INVALID_ROADTYPE) {
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(tram_rt);
|
||||
td->tramtype = rti->strings.name;
|
||||
td->tram_speed = rti->max_speed / 2;
|
||||
tram_owner = GetRoadOwner(tile, RTT_TRAM);
|
||||
}
|
||||
|
||||
/* Is there a mix of owners? */
|
||||
if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
|
||||
|
@ -1624,7 +1725,9 @@ static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
|
|||
}
|
||||
}
|
||||
} else if (tt == TRANSPORT_ROAD && !IsTunnel(tile)) {
|
||||
td->road_speed = GetBridgeSpec(GetBridgeType(tile))->speed;
|
||||
uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
|
||||
if (road_rt != INVALID_ROADTYPE && (td->road_speed == 0 || spd < td->road_speed)) td->road_speed = spd;
|
||||
if (tram_rt != INVALID_ROADTYPE && (td->tram_speed == 0 || spd < td->tram_speed)) td->tram_speed = spd;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1660,7 +1763,7 @@ static void TileLoop_TunnelBridge(TileIndex tile)
|
|||
static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
|
||||
{
|
||||
TransportType transport_type = GetTunnelBridgeTransportType(tile);
|
||||
if (transport_type != mode || (transport_type == TRANSPORT_ROAD && (GetRoadTypes(tile) & sub_mode) == 0)) return 0;
|
||||
if (transport_type != mode || (transport_type == TRANSPORT_ROAD && !HasTileRoadType(tile, (RoadTramType)sub_mode))) return 0;
|
||||
|
||||
DiagDirection dir = GetTunnelBridgeDirection(tile);
|
||||
if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
|
||||
|
@ -1674,17 +1777,18 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner
|
|||
* don't want to update the infrastructure counts twice. */
|
||||
uint num_pieces = tile < other_end ? (GetTunnelBridgeLength(tile, other_end) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR : 0;
|
||||
|
||||
for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
|
||||
FOR_ALL_ROADTRAMTYPES(rtt) {
|
||||
/* Update all roadtypes, no matter if they are present */
|
||||
if (GetRoadOwner(tile, rt) == old_owner) {
|
||||
if (HasBit(GetRoadTypes(tile), rt)) {
|
||||
if (GetRoadOwner(tile, rtt) == old_owner) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
if (rt != INVALID_ROADTYPE) {
|
||||
/* Update company infrastructure counts. A full diagonal road tile has two road bits.
|
||||
* No need to dirty windows here, we'll redraw the whole screen anyway. */
|
||||
Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2;
|
||||
if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2;
|
||||
}
|
||||
|
||||
SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
|
||||
SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1757,7 +1757,7 @@ UnitID GetFreeUnitNumber(VehicleType type)
|
|||
* @return true if there is any reason why you may build
|
||||
* the infrastructure for the given vehicle type
|
||||
*/
|
||||
bool CanBuildVehicleInfrastructure(VehicleType type)
|
||||
bool CanBuildVehicleInfrastructure(VehicleType type, byte subtype)
|
||||
{
|
||||
assert(IsCompanyBuildableVehicleType(type));
|
||||
|
||||
|
@ -1770,7 +1770,10 @@ bool CanBuildVehicleInfrastructure(VehicleType type)
|
|||
if (!HasAnyRailtypesAvail(_local_company)) return false;
|
||||
max = _settings_game.vehicle.max_trains;
|
||||
break;
|
||||
case VEH_ROAD: max = _settings_game.vehicle.max_roadveh; break;
|
||||
case VEH_ROAD:
|
||||
if (!HasAnyRoadTypesAvail(_local_company, (RoadTramType)subtype)) return false;
|
||||
max = _settings_game.vehicle.max_roadveh;
|
||||
break;
|
||||
case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
|
||||
case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
|
||||
default: NOT_REACHED();
|
||||
|
@ -1781,6 +1784,7 @@ bool CanBuildVehicleInfrastructure(VehicleType type)
|
|||
/* Can we actually build the vehicle type? */
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, type) {
|
||||
if (type == VEH_ROAD && GetRoadTramType(e->u.road.roadtype) != (RoadTramType)subtype) continue;
|
||||
if (HasBit(e->company_avail, _local_company)) return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1789,6 +1793,7 @@ bool CanBuildVehicleInfrastructure(VehicleType type)
|
|||
/* We should be able to build infrastructure when we have the actual vehicle type */
|
||||
const Vehicle *v;
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (type == VEH_ROAD && GetRoadTramType(RoadVehicle::From(v)->roadtype) != (RoadTramType)subtype) continue;
|
||||
if (v->owner == _local_company && v->type == type) return true;
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue