Merge branch 'road-stops' into jgrpp
commit
df92b7e449
@ -0,0 +1,317 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>JGR's Patchpack - NewGRF Road Stops Addition to NewGRF Specifications</title>
|
||||
<style type="text/css">
|
||||
td li { white-space: nowrap; text-align: left; }
|
||||
th { white-space: nowrap; text-align: center; }
|
||||
td, th { border: 1px solid #CCCCCC; padding: 0px 5px; }
|
||||
table { border-collapse: collapse; empty-cells: show; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>NewGRF Road Stops Addition to NewGRF Specifications in JGR's Patchpack</h2>
|
||||
<p>This document describes the non-standard addition of the NewGRF road stops feature to the <a href="https://newgrf-specs.tt-wiki.net/wiki/Main_Page">Official OpenTTD NewGRF Specifications</a>, as implemented in this patchpack.</br>
|
||||
This feature does not match OpenTTD PR #7955 in a number of key areas, this feature may not necessarily match implementations of NewGRF road stops in other patches, branches, etc.</br>
|
||||
This feature as implemented here MAY also be present in other patchpacks.</p>
|
||||
<p>See the <a href="newgrf-additions.html#feature-test">NewGRF additions</a> document for background information on additions to the NewGRF specifications.</p>
|
||||
<p>A subset of the functionality listed below is (will be) also supported in a fork of NML, see the associated <a href="newgrf-roadstops-nml.html">NML road stops</a> and <a href="newgrf-additions-nml.html">NML additions</a> documents for more details.</p>
|
||||
<p>NewGRFs which use this feature SHOULD use the <a href="newgrf-additions.html#feature-test">feature testing</a> mechanism to check whether the road stop feature and/or feature ID mapping is supported.</p>
|
||||
<p>NewGRFs which use this feature MUST use the <a href="newgrf-additions.html#feature-id-mapping">feature ID mapping</a> mechanism to map the non-standard NewGRF road stop feature to a local feature ID.</p>
|
||||
<p>This feature is indicated by the feature name: <font face="monospace">road_stops</font>, version 1.</br>
|
||||
The feature name to use for feature ID mapping is <font face="monospace">road_stops</font>.</p>
|
||||
|
||||
|
||||
<p><b>Actions:</b>
|
||||
<ul>
|
||||
<li><a href="#a0roadstops">Action 0</a></li>
|
||||
<li><a href="#a2roadstops">Action 2</a></li>
|
||||
<li><a href="#varaction2roadstops">Variational Action 2</a></li>
|
||||
<li><a href="#randomaction2roadstops">Random Action 2</a></li>
|
||||
<li><a href="#a3roadstops">Action 3</a></li>
|
||||
</ul></p>
|
||||
|
||||
<h3 id="a0roadstops">Action 0 - Road Stops</h3>
|
||||
|
||||
<p>See the <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0">Action 0 Specification</a> for background information.</p>
|
||||
|
||||
<b>Properties:</b>
|
||||
<table>
|
||||
<tr><th>Number</th><th>Mappable name</th><th>Size in bytes</th><th>Description</th></tr>
|
||||
<tr><td><a href="#roadstop_class_id">08</a></td><td><a href="#roadstop_class_id">roadstop_class_id</a></td><td>4</td><td>Class ID</td></tr>
|
||||
<tr><td><a href="#roadstop_stop_type">09</a></td><td><a href="#roadstop_stop_type">roadstop_stop_type</a></td><td>1</td><td>Stop type availability</td></tr>
|
||||
<tr><td><a href="#roadstop_stop_name">0A</a></td><td><a href="#roadstop_stop_name">roadstop_stop_name</a></td><td>2</td><td>Name</td></tr>
|
||||
<tr><td><a href="#roadstop_class_name">0B</a></td><td><a href="#roadstop_class_name">roadstop_class_name</a></td><td>2</td><td>Class name</td></tr>
|
||||
<tr><td><a href="#roadstop_draw_mode">0C</a></td><td><a href="#roadstop_draw_mode">roadstop_draw_mode</a></td><td>1</td><td>Draw mode</td></tr>
|
||||
<tr><td><a href="#roadstop_random_trigger_cargoes">0D</a></td><td><a href="#roadstop_random_trigger_cargoes">roadstop_random_trigger_cargoes</a></td><td>4</td><td>Random trigger cargoes</td></tr>
|
||||
<tr><td><a href="#roadstop_animation_info">0E</a></td><td><a href="#roadstop_animation_info">roadstop_animation_info</a></td><td>2</td><td>Animation info</td></tr>
|
||||
<tr><td><a href="#roadstop_animation_speed">0F</a></td><td><a href="#roadstop_animation_speed">roadstop_animation_speed</a></td><td>1</td><td>Animation speed</td></tr>
|
||||
<tr><td><a href="#roadstop_animation_triggers">10</a></td><td><a href="#roadstop_animation_triggers">roadstop_animation_triggers</a></td><td>2</td><td>Animation triggers</td></tr>
|
||||
<tr><td><a href="#roadstop_callback_mask">11</a></td><td><a href="#roadstop_callback_mask">roadstop_callback_mask</a></td><td>1</td><td>Callback flags</td></tr>
|
||||
<tr><td><a href="#roadstop_general_flags">12</a></td><td><a href="#roadstop_general_flags">roadstop_general_flags</a></td><td>4</td><td>General flags</td></tr>
|
||||
<tr><td><a href="#roadstop_min_bridge_height">13</a></td><td><a href="#roadstop_min_bridge_height">roadstop_min_bridge_height</a></td><td>6</td><td>Minimum bridge heights</td></tr>
|
||||
<tr><td><a href="#roadstop_disallowed_bridge_pillars">14</a></td><td><a href="#roadstop_disallowed_bridge_pillars">roadstop_disallowed_bridge_pillars</a></td><td>6</td><td>Disallowed bridge pillars</td></tr>
|
||||
</table>
|
||||
|
||||
<h4 id="roadstop_class_id">Road stop class ID (08, or mappable property: roadstop_class_id)</h4>
|
||||
<p>This property sets the road stop class ID for this road stop ID.<br />
|
||||
This property must be used first before any other property for this road stop ID.<br />
|
||||
Two class names are pre-defined:
|
||||
<table>
|
||||
<tr><th>Name</th><th>Class ID</th><th>Meaning</th></tr>
|
||||
<tr><td>DFLT</td><td>44 46 4C 54</td><td>Default bus and lorry stops</td></tr>
|
||||
<tr><td>WAYP</td><td>57 41 59 50</td><td>This class is used for road waypoints</td></tr>
|
||||
</table>
|
||||
All classes except WAYP are used for bus and/or lorry stops.<br />
|
||||
This functions the same way as <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Station_class_.2808.29">station (feature 4) property 08</a>.<br />
|
||||
The property length is 4 bytes.
|
||||
</p>
|
||||
<h4 id="roadstop_stop_type">Road stop type availability (09, or mappable property: roadstop_stop_type)</h4>
|
||||
<p>This property sets the road stop type availability, this is ignored for road stops in the WAYP class.<br />
|
||||
The property length is 1 byte. The format is:
|
||||
<table>
|
||||
<tr><th>Value</th><th>Meaning</th></tr>
|
||||
<tr><td>0</td><td>Passenger/bus stop</td></tr>
|
||||
<tr><td>1</td><td>Freight/lorry stop</td></tr>
|
||||
<tr><td>2</td><td>Both passenger/bus and freight/lorry stops</td></tr>
|
||||
</table>
|
||||
The default value is 2 (both bus and lorry stops).
|
||||
</p>
|
||||
<h4 id="roadstop_stop_name">Road stop name (0A, or mappable property: roadstop_stop_name)</h4>
|
||||
<p>This property sets the road stop name string ID.<br />
|
||||
The property length is 2 bytes. This should be a D8xx or DCxx string ID.</p>
|
||||
<h4 id="roadstop_class_name">Road stop class name (0B, or mappable property: roadstop_class_name)</h4>
|
||||
<p>This property sets the road stop class name string ID.<br />
|
||||
The property length is 2 bytes. This should be a D8xx or DCxx string ID.</p>
|
||||
<h4 id="roadstop_draw_mode">Road stop draw mode (0C, or mappable property: roadstop_draw_mode)</h4>
|
||||
<p>This property sets the road stop draw mode.<br />
|
||||
The property length is 1 byte. The format is:
|
||||
<table>
|
||||
<tr><th>Bit</th><th>Value</th><th>Meaning</th></tr>
|
||||
<tr><td>0</td><td>1</td><td>Bay stops: Draw road type ground sprite</td></tr>
|
||||
<tr><td>1</td><td>2</td><td>Drive through stops: Draw road/tram type overlays</td></tr>
|
||||
</table>
|
||||
The default value is 3 (bits 0 and 1 both set).
|
||||
</p>
|
||||
<h4 id="roadstop_random_trigger_cargoes">Road stop random trigger cargoes (0D, or mappable property: roadstop_random_trigger_cargoes)</h4>
|
||||
<p>This property sets the cargo types for random triggers.<br />
|
||||
This functions the same way as <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Cargo_types_for_random_triggers_.2812.29">station (feature 4) property 12</a>.<br />
|
||||
This sets which cargo types should trigger re-randomizing. The cargo types are given as a bitmask of the bits from column 3 (type B) in CargoTypes. If nothing is set (the default), the no random triggers will happen, to conserve CPU time.<br />
|
||||
With GRF version 7 and above, the interpretation of bits changes. Instead of climate-dependent cargo slot numbers (type B), you have to set the bits of climate-independent cargo ID (type A).<br />
|
||||
The property length is 4 bytes.</p>
|
||||
<h4 id="roadstop_animation_info">Road stop animation info (0E, or mappable property: roadstop_animation_info)</h4>
|
||||
<p>This property sets the cargo types for random triggers.<br />
|
||||
This functions the same way as <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Animation_information_.2816.29">station (feature 4) property 16</a>.<br />
|
||||
The low byte specifies the number of animation frames minus one, so 00 means 1 frame, 01 means 2 frames etc. The maximum number of frames is 256, although you can have some problems if your animation exceeds FD (253) frames.
|
||||
The high byte must be 0 for non-looping animations and 01 for looping animations. Every other value is reserved for future use.
|
||||
In addition, if the whole word contains FFFF, animation is turned off for this station (this is the default value). Since you can't have properties for individual station tiles, this property applies for every tile of the station.
|
||||
If you don't want to animate some tiles, you should check the current position during callback 140 and return FD if the current tile doesn't need to be animated. If you also need animations of different length per tile, you'll have to use callback 141 for that.<br />
|
||||
The property length is 2 bytes.</p>
|
||||
<h4 id="roadstop_animation_speed">Road stop animation speed (0F, or mappable property: roadstop_animation_speed)</h4>
|
||||
<p>This property sets the cargo types for random triggers.<br />
|
||||
This functions the same way as <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Animation_speed_.2817.29">station (feature 4) property 17</a>.<br />
|
||||
This is the amount of time between switching frames. The default value is 2, which means the switch occurs every 108 milliseconds. Increasing this value by one doubles the wait, i.e. 3 will cause 216 ms delay, while 4 will pause 432 ms, and so on.
|
||||
The minimum is 0, which means the fastest possible animation, changing frames every game tick (27ms). The maximum is 16, which means 1769 seconds (approx. half an hour) delay. Settings above this value may cause strange behaviour.<br />
|
||||
The property length is 1 byte.</p>
|
||||
<h4 id="roadstop_animation_triggers">Road stop animation triggers (10, or mappable property: roadstop_animation_triggers)</h4>
|
||||
<p>This property sets the cargo types for random triggers.<br />
|
||||
This functions the same way as <a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Stations#Animation_triggers_.2818.29">station (feature 4) property 18</a>.<br />
|
||||
This is a bit mask of events that should trigger callback 140, allowing to change the animation state.<br />
|
||||
<table>
|
||||
<tr><th>Bit</th><th>Value</th><th>Meaning</th><th>Happens on</th><th>Var 18</th></tr>
|
||||
<tr><td>0</td><td>1</td><td>Road stop is built</td><td>newly built tile</td><td></td></tr>
|
||||
<tr><td>1</td><td>2</td><td>New cargo arrives at station</td><td>all tiles</td><td>Bits 8..15 contain the triggering cargo type</td></tr>
|
||||
<tr><td>2</td><td>4</td><td>Cargo removed from station</td><td>all tiles</td><td>Bits 8..15 contain the triggering cargo type</td></tr>
|
||||
<tr><td>3</td><td>8</td><td>Road vehicle enters stop (starts loading/unloading)</td><td>tile where the vehicle is</td><td></td></tr>
|
||||
<tr><td>4</td><td>10</td><td>Road vehicle leaves stop (done loading/unloading)</td><td>tile where the vehicle is</td><td></td></tr>
|
||||
<tr><td>5</td><td>20</td><td>Road vehicle loads/unloads cargo</td><td>tile where the vehicle is</td><td></td></tr>
|
||||
<tr><td>6</td><td>40</td><td>Every 250 ticks</td><td>all tiles</td><td></td></tr>
|
||||
</table>
|
||||
For bits 1 and 2: bits 8..15 of var 18 contain the triggering cargo type. If your GRF has a cargo translation table, the cargo type will be an index in that table, or FFh if the cargo isn't in the table. If you don't have a cargo translation table, the cargo type will simply be the climate-dependent cargo type number.</p>
|
||||
<h4 id="roadstop_callback_mask">Road stop callback flags (11, or mappable property: roadstop_callback_mask)</h4>
|
||||
<p>This property enables callbacks for this road stop type.<br />
|
||||
The property length is 1 byte. The format is:
|
||||
<table>
|
||||
<tr><th>Bit</th><th>Value</th><th>Variable 0C value</th><th>Callback</th></tr>
|
||||
<tr><td>0</td><td>1</td><td>13</td><td>Whether to make road stop available in construction window (non-zero callback return) or not (callback returns zero)</td></tr>
|
||||
<tr><td>1</td><td>2</td><td>141</td><td>Decide next animation frame</td></tr>
|
||||
<tr><td>2</td><td>4</td><td>142</td><td>Decide animation speed</td></tr>
|
||||
</table>
|
||||
Variable 0C value is what variable 0C will be set to, for checking it in the VarAction2 for callbacks.<br />
|
||||
The default value is 0 (no callbacks enabled).
|
||||
</p>
|
||||
<h4 id="roadstop_general_flags">Road stop general flags (12, or mappable property: roadstop_general_flags)</h4>
|
||||
<p>This property sets general flags for this road stop type.<br />
|
||||
The property length is 4 bytes. The format is:
|
||||
<table>
|
||||
<tr><th>Bit</th><th>Value</th><th>Meaning</th></tr>
|
||||
<tr><td>0</td><td>1</td><td>Callback 141 needs random bits in variable 10</td></tr>
|
||||
</table>
|
||||
The default value is 0 (no flags enabled).
|
||||
</p>
|
||||
<h4 id="roadstop_min_bridge_height">Road stop minimum bridge heights (13, or mappable property: roadstop_min_bridge_height)</h4>
|
||||
<p>This property allows or disallows building bridges over road stops.<br />
|
||||
The bridge height property defines minimum clearances required for a bridge for each of the 6 views/rotations (or 0 to not allow any bridge). Values are given in height level units (1 level == 8px).<br />
|
||||
Each height value is 1 byte, the total property length is 6 bytes.
|
||||
</p>
|
||||
<h4 id="roadstop_disallowed_bridge_pillars">Road stop disallowed bridge pillars (14, or mappable property: roadstop_disallowed_bridge_pillars)</h4>
|
||||
<p>This property describes which bridge pillars are not allowed on the road stop tile.<br />
|
||||
It consists of a set of pillar flags, for each of the 6 road stop views/rotations.<br />
|
||||
Each set of flags is 1 byte, the total property length is 6 bytes.<br />
|
||||
Each set of flags has the format described in the <a href="newgrf-additions.html#bridge_pillar_flags">bridge_pillar_flags property section</a>.
|
||||
</p>
|
||||
|
||||
<p style="padding-top: 0.25em;">
|
||||
<div id="roadstop_views">The 6 road stop views/rotations are described below.</div>
|
||||
<table>
|
||||
<tr><th>Views/rotation</th><th>Type</th><th>Description</tr>
|
||||
<tr><td>0</td><td>Bay</td><td>Facing north-east</td></tr>
|
||||
<tr><td>1</td><td>Bay</td><td>Facing south-east</td></tr>
|
||||
<tr><td>2</td><td>Bay</td><td>Facing south-west</td></tr>
|
||||
<tr><td>3</td><td>Bay</td><td>Facing north-west</td></tr>
|
||||
<tr><td>4</td><td>Drive-through</td><td>X-axis: north-east to south-west</td></tr>
|
||||
<tr><td>5</td><td>Drive-through</td><td>Y-axis: north-west to south-east</td></tr>
|
||||
</table>
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<h3 id="a2roadstops">Action 2 - Road Stops</h3>
|
||||
|
||||
<p>See the <a href="https://newgrf-specs.tt-wiki.net/wiki/Action2">Action 2 Specification</a> for background information.</p>
|
||||
|
||||
<p>Road stops use the <a href="https://newgrf-specs.tt-wiki.net/wiki/Action2/Sprite_Layout">special sprite layout format</a>, the same as Action 2 features: 7 (house), 9 (industry tile), F (object), 11 (airport tile).</p>
|
||||
<br />
|
||||
|
||||
<h3 id="varaction2roadstops">Variational Action 2 - Road Stops</h3>
|
||||
|
||||
<p>See the <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2 Specification</a> for background information.</p>
|
||||
|
||||
<b>Variables:</b>
|
||||
<table>
|
||||
<tr><th>Number</th><th>Mappable name</th><th>Description</th></tr>
|
||||
<tr><td><a href="#roadstop_view">40</a></td><td><a href="#roadstop_view">roadstop_view</a></td><td>View/rotation</td></tr>
|
||||
<tr><td><a href="#roadstop_type">41</a></td><td><a href="#roadstop_type">roadstop_type</a></td><td>Stop type</td></tr>
|
||||
<tr><td><a href="#roadstop_terrain_type">42</a></td><td><a href="#roadstop_terrain_type">roadstop_terrain_type</a></td><td>Terrain type</td></tr>
|
||||
<tr><td><a href="#roadstop_road_type">43</a></td><td><a href="#roadstop_road_type">roadstop_road_type</a></td><td>Road type</td></tr>
|
||||
<tr><td><a href="#roadstop_tram_type">44</a></td><td><a href="#roadstop_tram_type">roadstop_tram_type</a></td><td>Tram type</td></tr>
|
||||
<tr><td><a href="#roadstop_town_zone">45</a></td><td><a href="#roadstop_town_zone">roadstop_town_zone</a></td><td>Town zone and Manhattan distance of town</td></tr>
|
||||
<tr><td><a href="#roadstop_town_distance_squared">46</a></td><td><a href="#roadstop_town_distance_squared">roadstop_town_distance_squared</a></td><td>Square of Euclidean distance of town</td></tr>
|
||||
<tr><td><a href="#roadstop_company_info">47</a></td><td><a href="#roadstop_company_info">roadstop_company_info</a></td><td>Player/company info</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">48</a></td><td></td><td>Bitmask of accepted cargoes (BaseStation)</td></tr>
|
||||
<tr><td><a href="#roadstop_animation_frame">49</a></td><td><a href="#roadstop_animation_frame">roadstop_animation_frame</a></td><td>Current animation frame</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">60</a></td><td></td><td>Amount of cargo waiting (BaseStation)</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">61</a></td><td></td><td>Time since last cargo pickup (BaseStation)</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">62</a></td><td></td><td>Rating of cargo (BaseStation)</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">63</a></td><td></td><td>Time spent on route (BaseStation)</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">64</a></td><td></td><td>Information about last vehicle picking cargo up (BaseStation)</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">65</a></td><td></td><td>Amount of cargo acceptance (BaseStation)</td></tr>
|
||||
<tr><td><a href="#roadstop_animation_frame_nearby_tiles">66</a></td><td><a href="#roadstop_animation_frame_nearby_tiles">roadstop_animation_frame_nearby_tiles</a></td><td>Animation frame of nearby tile</td></tr>
|
||||
<tr><td><a href="#roadstop_land_info_nearby_tiles">67</a></td><td><a href="#roadstop_land_info_nearby_tiles">roadstop_land_info_nearby_tiles</a></td><td>Land info of nearby tiles</td></tr>
|
||||
<tr><td><a href="#roadstop_road_stop_info_nearby_tiles">68</a></td><td><a href="#roadstop_road_stop_info_nearby_tiles">roadstop_road_stop_info_nearby_tiles</a></td><td>Road stop info of nearby tiles</td></tr>
|
||||
<tr><td><a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/BaseStation">69</a></td><td></td><td>Information about cargo accepted in the past (BaseStation)</td></tr>
|
||||
<tr><td><a href="#roadstop_road_stop_grfid_nearby_tiles">6A</a></td><td><a href="#roadstop_road_stop_grfid_nearby_tiles">roadstop_road_stop_grfid_nearby_tiles</a></td><td>GRFID of nearby road stop tiles</td></tr>
|
||||
</table>
|
||||
|
||||
<h4 id="roadstop_view">Road stop view/rotation (40, or mappable variable: roadstop_view)</h4>
|
||||
<p>This has the range 0 - 5, see <a href="#roadstop_views">the 6 road stop views/rotations</a></p>
|
||||
|
||||
<h4 id="roadstop_type">Road stop type (41, or mappable variable: roadstop_type)</h4>
|
||||
<p>
|
||||
<table>
|
||||
<tr><th>Value</th><th>Meaning</th></tr>
|
||||
<tr><td>0</td><td>Passenger/bus stop</td></tr>
|
||||
<tr><td>1</td><td>Freight/lorry stop</td></tr>
|
||||
<tr><td>2</td><td>Road waypoint</td></tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<h4 id="roadstop_terrain_type">Road stop tile/terrain type (42, or mappable variable: roadstop_terrain_type)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Objects#Tile_information_.2841.29">object (feature F) variable 41</a>.</p>
|
||||
|
||||
<h4 id="roadstop_road_type">Road stop road type (43, or mappable variable: roadstop_road_type)</h4>
|
||||
<p>This has the value of the (translated) roadtype the road stop is built on, or the current roadtype in the build GUI. If the roadtype has no entry in the roadtype translation table of the GRF, this value will be 0xFF. If no translation table is present, the raw value will be returned. Note: only exact matches of roadtypes are reported. If the translation table of the GRF does not contain the exact roadtype 0xFF is returned.<br />
|
||||
If the tile has no road at all (tram only) 0xFFFFFFFF is returned.</p>
|
||||
|
||||
<h4 id="roadstop_tram_type">Road stop tram type (44, or mappable variable: roadstop_road_type)</h4>
|
||||
<p>This has the value of the (translated) tramtype the road stop is built on, or the current tramtype in the build GUI. If the tramtype has no entry in the tramtype translation table of the GRF, this value will be 0xFF. If no translation table is present, the raw value will be returned. Note: only exact matches of tramtypes are reported. If the translation table of the GRF does not contain the exact tramtype 0xFF is returned.<br />
|
||||
If the tile has no tram at all (road only) 0xFFFFFFFF is returned.</p>
|
||||
|
||||
<h4 id="roadstop_town_zone">Town zone and Manhattan distance of town (45, or mappable variable: roadstop_town_zone)</h4>
|
||||
<p>The town used is the one associated with the station/waypoint (this is in the station/waypoint name by default).
|
||||
<table>
|
||||
<tr><th>Bits</th><th>Meaning</th></tr>
|
||||
<tr><td>0 - 15</td><td>Manhattan distance from town</td></tr>
|
||||
<tr><td>16 - 24</td><td>Town zone</td></tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<h4 id="roadstop_town_distance_squared">Square of Euclidean distance of town (46, or mappable variable: roadstop_town_distance_squared)</h4>
|
||||
<p>The town used is the one associated with the station/waypoint (this is in the station/waypoint name by default).</p>
|
||||
|
||||
<h4 id="roadstop_company_info">Player/company info (47, or mappable variable: roadstop_company_info)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Vehicles#Player_info_.2843.29">vehicle (features 0 - 3) variable 43</a>.<br />
|
||||
The company used is the owner of the station/waypoint, not the owner of the underlying road and/or tram.</p>
|
||||
|
||||
<h4 id="roadstop_animation_frame">Current animation frame (49, or mappable variable: roadstop_animation_frame)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations">station (feature 4) variable 4A</a>.</p>
|
||||
|
||||
<h4 id="roadstop_animation_frame_nearby_tiles">Animation frame of nearby tile (66, or mappable variable: roadstop_animation_frame_nearby_tiles)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations#Animation_frame_of_nearby_tile_.2866.29">station (feature 4) variable 66</a>.</p>
|
||||
|
||||
<h4 id="roadstop_land_info_nearby_tiles">Land info of nearby tile (67, or mappable variable: roadstop_land_info_nearby_tiles)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Industry_Tiles#Land_info_of_nearby_tiles_.2860.29">industry tile (feature 9) variable 60</a>.</p>
|
||||
|
||||
<h4 id="roadstop_road_stop_info_nearby_tiles">Road stop of mearby tile (68, or mappable variable: roadstop_road_stop_info_nearby_tiles)</h4>
|
||||
<p>This has a similar value to <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations#Station_info_of_nearby_tiles_.2868.29">station (feature 4) variable 68</a>.<br />
|
||||
|
||||
<table>
|
||||
<tr><th>Bits</th><th>Meaning</th></tr>
|
||||
<tr><td>0 - 7</td><td>If the tile is defined in the current GRF, this is the setID used in the definition. Otherwise, the content is undefined. </td></tr>
|
||||
<tr><td>8 - 9</td><td>
|
||||
0 - The tile uses original TTD graphics<br />
|
||||
1 - The tile is defined in the current GRF<br />
|
||||
2 - The tile is defined in another GRF
|
||||
</td></tr>
|
||||
<tr><td>10</td><td>Set if the selected tile belongs to the current station, clear otherwise</td></tr>
|
||||
<tr><td>11</td><td>Clear if the selected tile has the same view/rotation, set if a different view/rotation</td></tr>
|
||||
<tr><td>14 - 12</td><td>View/rotation of the selected tile</td></tr>
|
||||
</table>
|
||||
</p>
|
||||
|
||||
<h4 id="roadstop_road_stop_grfid_nearby_tiles">GRFID of nearby road stop tile (6A, or mappable variable: roadstop_road_stop_grfid_nearby_tiles)</h4>
|
||||
<p>This has the same value as <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2/Stations#GRFID_of_nearby_station_tile_.286A.29">station (feature 4) variable 6A</a>.</p>
|
||||
|
||||
<br />
|
||||
<h3 id="randomaction2roadstops">Random Action 2 - Road Stops</h3>
|
||||
|
||||
<p>See the <a href="https://newgrf-specs.tt-wiki.net/wiki/RandomAction2">Random Action 2 Specification</a> for background information.</p>
|
||||
|
||||
<p>Road stops have 16+8 random bits. Bits 0 to 15 are a property of the station as a whole, and bits 16 to 23 are different for each tile.
|
||||
|
||||
<table>
|
||||
<tr><th>Bit</th><th>Value</th><th>Trigger</th></tr>
|
||||
<tr><td>0</td><td>01</td><td>New cargo waiting</td></tr>
|
||||
<tr><td>1</td><td>02</td><td>No more cargo</td></tr>
|
||||
<tr><td>2</td><td>04</td><td>Road vehicle arrives (starts unloading/loading)</td></tr>
|
||||
<tr><td>3</td><td>08</td><td>Road vehicle leaves (done unloading & loading)</td></tr>
|
||||
<tr><td>4</td><td>10</td><td>Road vehicle loads or unloads cargo</td></tr>
|
||||
</table>
|
||||
Note that a road vehicle arrives trigger does not imply that the stop was previously empty, and a road vehicle leaves trigger does not imply that the stop is now empty.</p>
|
||||
<p>
|
||||
Also note that none of the above triggers will actually trigger unless <a href="#roadstop_random_trigger_cargoes">property 0D/roadstop_random_trigger_cargoes</a> has at least one bit set.<br />
|
||||
Triggers 01 will be triggered for any of the cargo types set in <a href="#roadstop_random_trigger_cargoes">property 0D/roadstop_random_trigger_cargoes</a>, but trigger 02 will only be triggered if all of those cargo types have no more cargo waiting.<br />
|
||||
Triggers 04 and 08 are triggered no matter what cargo types the train transports, as long as <a href="#roadstop_random_trigger_cargoes">property 0D/roadstop_random_trigger_cargoes</a> is not zero.<br />
|
||||
Triggers 04, 08, and 10 only affect the tile on which they occur, as well as the random bits of the station, but not other tiles.
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<h3 id="a3roadstops">Action 3 - Road Stops</h3>
|
||||
|
||||
<p>See the <a href="https://newgrf-specs.tt-wiki.net/wiki/Action3">Action 3 Specification</a> for background information.</p>
|
||||
|
||||
<p>Road stops have the same Action 3 cargo-type values as feature 4 (station).</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* 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 command.cpp Handling of NewGRF road stops. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "debug.h"
|
||||
#include "station_base.h"
|
||||
#include "roadstop_base.h"
|
||||
#include "newgrf_roadstop.h"
|
||||
#include "newgrf_class_func.h"
|
||||
#include "newgrf_cargo.h"
|
||||
#include "newgrf_roadtype.h"
|
||||
#include "gfx_type.h"
|
||||
#include "company_func.h"
|
||||
#include "road.h"
|
||||
#include "window_type.h"
|
||||
#include "date_func.h"
|
||||
#include "town.h"
|
||||
#include "viewport_func.h"
|
||||
#include "newgrf_animation_base.h"
|
||||
#include "newgrf_sound.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
template <typename Tspec, typename Tid, Tid Tmax>
|
||||
void NewGRFClass<Tspec, Tid, Tmax>::InsertDefaults()
|
||||
{
|
||||
/* Set up initial data */
|
||||
classes[0].global_id = 'DFLT';
|
||||
classes[0].name = STR_STATION_CLASS_DFLT;
|
||||
classes[0].Insert(nullptr);
|
||||
|
||||
classes[1].global_id = 'WAYP';
|
||||
classes[1].name = STR_STATION_CLASS_WAYP;
|
||||
classes[1].Insert(nullptr);
|
||||
}
|
||||
|
||||
template <typename Tspec, typename Tid, Tid Tmax>
|
||||
bool NewGRFClass<Tspec, Tid, Tmax>::IsUIAvailable(uint index) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
INSTANTIATE_NEWGRF_CLASS_METHODS(RoadStopClass, RoadStopSpec, RoadStopClassID, ROADSTOP_CLASS_MAX)
|
||||
|
||||
static const uint NUM_ROADSTOPSPECS_PER_STATION = 63; ///< Maximum number of parts per station.
|
||||
|
||||
uint32 RoadStopScopeResolver::GetRandomBits() const
|
||||
{
|
||||
if (this->st == nullptr) return 0;
|
||||
|
||||
uint32 bits = this->st->random_bits;
|
||||
if (this->tile != INVALID_TILE && Station::IsExpected(this->st)) {
|
||||
bits |= Station::From(this->st)->GetRoadStopRandomBits(this->tile) << 16;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32 RoadStopScopeResolver::GetTriggers() const
|
||||
{
|
||||
return this->st == nullptr ? 0 : this->st->waiting_triggers;
|
||||
}
|
||||
|
||||
uint32 RoadStopScopeResolver::GetVariable(uint16 variable, uint32 parameter, GetVariableExtra *extra) const
|
||||
{
|
||||
auto get_road_type_variable = [&](RoadTramType rtt) -> uint32 {
|
||||
RoadType rt;
|
||||
if (this->tile == INVALID_TILE) {
|
||||
rt = (GetRoadTramType(this->roadtype) == rtt) ? this->roadtype : INVALID_ROADTYPE;
|
||||
} else {
|
||||
rt = GetRoadType(this->tile, rtt);
|
||||
}
|
||||
if (rt == INVALID_ROADTYPE) {
|
||||
return 0xFFFFFFFF;
|
||||
} else {
|
||||
return GetReverseRoadTypeTranslation(rt, this->roadstopspec->grf_prop.grffile);
|
||||
}
|
||||
};
|
||||
|
||||
switch (variable) {
|
||||
/* View/rotation */
|
||||
case 0x40: return this->view;
|
||||
|
||||
/* Stop type: 0: bus, 1: truck, 2: waypoint */
|
||||
case 0x41:
|
||||
if (this->type == STATION_BUS) return 0;
|
||||
if (this->type == STATION_TRUCK) return 1;
|
||||
return 2;
|
||||
|
||||
/* Terrain type */
|
||||
case 0x42: return this->tile == INVALID_TILE ? 0 : GetTerrainType(this->tile, TCX_NORMAL); // terrain_type
|
||||
|
||||
/* Road type */
|
||||
case 0x43: return get_road_type_variable(RTT_ROAD);
|
||||
|
||||
/* Tram type */
|
||||
case 0x44: return get_road_type_variable(RTT_TRAM);
|
||||
|
||||
/* Town zone and Manhattan distance of closest town */
|
||||
case 0x45: {
|
||||
if (this->tile == INVALID_TILE) return HZB_TOWN_EDGE << 16;
|
||||
const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
|
||||
return t != nullptr ? (GetTownRadiusGroup(t, this->tile) << 16 | std::min(DistanceManhattan(this->tile, t->xy), 0xFFFFu)) : HZB_TOWN_EDGE << 16;
|
||||
}
|
||||
|
||||
/* Get square of Euclidian distance of closest town */
|
||||
case 0x46: {
|
||||
if (this->tile == INVALID_TILE) return 0;
|
||||
const Town *t = (this->st == nullptr) ? ClosestTownFromTile(this->tile, UINT_MAX) : this->st->town;
|
||||
return t != nullptr ? DistanceSquare(this->tile, t->xy) : 0;
|
||||
}
|
||||
|
||||
/* Company information */
|
||||
case 0x47: return GetCompanyInfo(this->st == nullptr ? _current_company : this->st->owner);
|
||||
|
||||
/* Animation frame */
|
||||
case 0x49: return this->tile == INVALID_TILE ? 0 : this->st->GetRoadStopAnimationFrame(this->tile);
|
||||
|
||||
/* Variables which use the parameter */
|
||||
/* Variables 0x60 to 0x65 and 0x69 are handled separately below */
|
||||
|
||||
/* Animation frame of nearby tile */
|
||||
case 0x66: {
|
||||
if (this->tile == INVALID_TILE) return UINT_MAX;
|
||||
TileIndex tile = this->tile;
|
||||
if (parameter != 0) tile = GetNearbyTile(parameter, tile);
|
||||
return (IsAnyRoadStopTile(tile) && GetStationIndex(tile) == this->st->index) ? this->st->GetRoadStopAnimationFrame(tile) : UINT_MAX;
|
||||
}
|
||||
|
||||
/* Land info of nearby tile */
|
||||
case 0x67: {
|
||||
if (this->tile == INVALID_TILE) return 0;
|
||||
TileIndex tile = this->tile;
|
||||
if (parameter != 0) tile = GetNearbyTile(parameter, tile); // only perform if it is required
|
||||
return GetNearbyTileInformation(tile, this->ro.grffile->grf_version >= 8);
|
||||
}
|
||||
|
||||
/* Road stop info of nearby tiles */
|
||||
case 0x68: {
|
||||
if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
|
||||
TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
|
||||
|
||||
if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
|
||||
|
||||
uint32 grfid = this->st->roadstop_speclist[GetCustomRoadStopSpecIndex(this->tile)].grfid;
|
||||
bool same_orientation = GetStationGfx(this->tile) == GetStationGfx(nearby_tile);
|
||||
bool same_station = GetStationIndex(nearby_tile) == this->st->index;
|
||||
uint32 res = GetStationGfx(nearby_tile) << 12 | !same_orientation << 11 | !!same_station << 10;
|
||||
|
||||
if (IsCustomRoadStopSpecIndex(nearby_tile)) {
|
||||
const RoadStopSpecList ssl = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
|
||||
res |= 1 << (ssl.grfid != grfid ? 9 : 8) | ssl.localidx;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* GRFID of nearby road stop tiles */
|
||||
case 0x6A: {
|
||||
if (this->tile == INVALID_TILE) return 0xFFFFFFFF;
|
||||
TileIndex nearby_tile = GetNearbyTile(parameter, this->tile);
|
||||
|
||||
if (!IsAnyRoadStopTile(nearby_tile)) return 0xFFFFFFFF;
|
||||
if (!IsCustomRoadStopSpecIndex(nearby_tile)) return 0;
|
||||
|
||||
const RoadStopSpecList ssl = BaseStation::GetByTile(nearby_tile)->roadstop_speclist[GetCustomRoadStopSpecIndex(nearby_tile)];
|
||||
return ssl.grfid;
|
||||
}
|
||||
|
||||
case 0xF0: return this->st == nullptr ? 0 : this->st->facilities; // facilities
|
||||
|
||||
case 0xFA: return Clamp((this->st == nullptr ? _date : this->st->build_date) - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535); // build date
|
||||
}
|
||||
|
||||
if (this->st != nullptr) return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));
|
||||
|
||||
extra->available = false;
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
const SpriteGroup *RoadStopResolverObject::ResolveReal(const RealSpriteGroup *group) const
|
||||
{
|
||||
if (group == nullptr) return nullptr;
|
||||
|
||||
return group->loading[0];
|
||||
}
|
||||
|
||||
RoadStopResolverObject::RoadStopResolverObject(const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8 view,
|
||||
CallbackID callback, uint32 param1, uint32 param2)
|
||||
: ResolverObject(roadstopspec->grf_prop.grffile, callback, param1, param2), roadstop_scope(*this, st, roadstopspec, tile, roadtype, type, view)
|
||||
{
|
||||
|
||||
this->town_scope = nullptr;
|
||||
|
||||
CargoID ctype = CT_DEFAULT_NA;
|
||||
|
||||
if (st == nullptr) {
|
||||
/* No station, so we are in a purchase list */
|
||||
ctype = CT_PURCHASE;
|
||||
} else if (Station::IsExpected(st)) {
|
||||
const Station *station = Station::From(st);
|
||||
/* Pick the first cargo that we have waiting */
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
if (roadstopspec->grf_prop.spritegroup[cs->Index()] != nullptr &&
|
||||
station->goods[cs->Index()].cargo.TotalCount() > 0) {
|
||||
ctype = cs->Index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (roadstopspec->grf_prop.spritegroup[ctype] == nullptr) {
|
||||
ctype = CT_DEFAULT;
|
||||
}
|
||||
|
||||
/* Remember the cargo type we've picked */
|
||||
this->roadstop_scope.cargo_type = ctype;
|
||||
this->root_spritegroup = roadstopspec->grf_prop.spritegroup[ctype];
|
||||
}
|
||||
|
||||
RoadStopResolverObject::~RoadStopResolverObject()
|
||||
{
|
||||
delete this->town_scope;
|
||||
}
|
||||
|
||||
TownScopeResolver* RoadStopResolverObject::GetTown()
|
||||
{
|
||||
if (this->town_scope == nullptr) {
|
||||
Town *t;
|
||||
if (this->roadstop_scope.st != nullptr) {
|
||||
t = this->roadstop_scope.st->town;
|
||||
} else {
|
||||
t = ClosestTownFromTile(this->roadstop_scope.tile, UINT_MAX);
|
||||
}
|
||||
if (t == nullptr) return nullptr;
|
||||
this->town_scope = new TownScopeResolver(*this, t, this->roadstop_scope.st == nullptr);
|
||||
}
|
||||
return this->town_scope;
|
||||
}
|
||||
|
||||
uint16 GetRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8 view)
|
||||
{
|
||||
RoadStopResolverObject object(roadstopspec, st, tile, roadtype, type, view, callback, param1, param2);
|
||||
return object.ResolveCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw representation of a road stop tile for GUI purposes.
|
||||
* @param x position x of image.
|
||||
* @param y position y of image.
|
||||
* @param image an int offset for the sprite.
|
||||
* @param roadtype the RoadType of the underlying road.
|
||||
* @param spec the RoadStop's spec.
|
||||
* @return true of the tile was drawn (allows for fallback to default graphics)
|
||||
*/
|
||||
void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view)
|
||||
{
|
||||
assert(roadtype != INVALID_ROADTYPE);
|
||||
assert(spec != nullptr);
|
||||
|
||||
const RoadTypeInfo *rti = GetRoadTypeInfo(roadtype);
|
||||
RoadStopResolverObject object(spec, nullptr, INVALID_TILE, roadtype, type, view);
|
||||
const SpriteGroup *group = object.Resolve();
|
||||
if (group == nullptr || group->type != SGT_TILELAYOUT) return;
|
||||
const DrawTileSprites *dts = ((const TileLayoutSpriteGroup *)group)->ProcessRegisters(nullptr);
|
||||
|
||||
PaletteID palette = COMPANY_SPRITE_COLOUR(_local_company);
|
||||
|
||||
SpriteID image = dts->ground.sprite;
|
||||
PaletteID pal = dts->ground.pal;
|
||||
|
||||
if (GB(image, 0, SPRITE_WIDTH) != 0) {
|
||||
DrawSprite(image, GroundSpritePaletteTransform(image, pal, palette), x, y);
|
||||
}
|
||||
|
||||
if (view >= 4) {
|
||||
/* Drive-through stop */
|
||||
uint sprite_offset = 5 - view;
|
||||
|
||||
/* Road underlay takes precedence over tram */
|
||||
if (spec->draw_mode & ROADSTOP_DRAW_MODE_OVERLAY) {
|
||||
TileInfo ti {};
|
||||
ti.tile = INVALID_TILE;
|
||||
DrawRoadOverlays(&ti, PAL_NONE, RoadTypeIsRoad(roadtype) ? rti : nullptr, RoadTypeIsTram(roadtype) ? rti : nullptr, sprite_offset, sprite_offset);
|
||||
}
|
||||
|
||||
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 (rti->UsesOverlay()) {
|
||||
SpriteID ground = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_ROADSTOP);
|
||||
DrawSprite(ground + view, PAL_NONE, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
DrawCommonTileSeqInGUI(x, y, dts, 0, 0, palette, true);
|
||||
}
|
||||
|
||||
/** Wrapper for animation control, see GetRoadStopCallback. */
|
||||
uint16 GetAnimRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, int extra_data)
|
||||
{
|
||||
return GetRoadStopCallback(callback, param1, param2, roadstopspec, st, tile, INVALID_ROADTYPE, GetStationType(tile), GetStationGfx(tile));
|
||||
}
|
||||
|
||||
struct RoadStopAnimationFrameAnimationHelper {
|
||||
static byte Get(BaseStation *st, TileIndex tile) { return st->GetRoadStopAnimationFrame(tile); }
|
||||
static void Set(BaseStation *st, TileIndex tile, byte frame) { st->SetRoadStopAnimationFrame(tile, frame); }
|
||||
};
|
||||
|
||||
/** Helper class for animation control. */
|
||||
struct RoadStopAnimationBase : public AnimationBase<RoadStopAnimationBase, RoadStopSpec, BaseStation, int, GetAnimRoadStopCallback, RoadStopAnimationFrameAnimationHelper> {
|
||||
static const CallbackID cb_animation_speed = CBID_STATION_ANIMATION_SPEED;
|
||||
static const CallbackID cb_animation_next_frame = CBID_STATION_ANIM_NEXT_FRAME;
|
||||
|
||||
static const RoadStopCallbackMask cbm_animation_speed = CBM_ROAD_STOP_ANIMATION_SPEED;
|
||||
static const RoadStopCallbackMask cbm_animation_next_frame = CBM_ROAD_STOP_ANIMATION_NEXT_FRAME;
|
||||
};
|
||||
|
||||
void AnimateRoadStopTile(TileIndex tile)
|
||||
{
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(tile);
|
||||
if (ss == nullptr) return;
|
||||
|
||||
RoadStopAnimationBase::AnimateTile(ss, BaseStation::GetByTile(tile), tile, HasBit(ss->flags, RSF_CB141_RANDOM_BITS));
|
||||
}
|
||||
|
||||
uint8 GetRoadStopTileAnimationSpeed(TileIndex tile)
|
||||
{
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(tile);
|
||||
if (ss == nullptr) return 0;
|
||||
|
||||
return RoadStopAnimationBase::GetAnimationSpeed(ss);
|
||||
}
|
||||
|
||||
void TriggerRoadStopAnimation(BaseStation *st, TileIndex trigger_tile, StationAnimationTrigger trigger, CargoID cargo_type)
|
||||
{
|
||||
/* Get Station if it wasn't supplied */
|
||||
if (st == nullptr) st = BaseStation::GetByTile(trigger_tile);
|
||||
|
||||
/* Check the cached animation trigger bitmask to see if we need
|
||||
* to bother with any further processing. */
|
||||
if (!HasBit(st->cached_roadstop_anim_triggers, trigger)) return;
|
||||
|
||||
uint16 random_bits = Random();
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
|
||||
if (ss != nullptr && HasBit(ss->animation.triggers, trigger)) {
|
||||
CargoID cargo;
|
||||
if (cargo_type == CT_INVALID) {
|
||||
cargo = CT_INVALID;
|
||||
} else {
|
||||
cargo = ss->grf_prop.grffile->cargo_map[cargo_type];
|
||||
}
|
||||
RoadStopAnimationBase::ChangeAnimationFrame(CBID_STATION_ANIM_START_STOP, ss, st, cur_tile, (random_bits << 16) | Random(), (uint8)trigger | (cargo << 8));
|
||||
}
|
||||
};
|
||||
|
||||
if (trigger == SAT_NEW_CARGO || trigger == SAT_CARGO_TAKEN || trigger == SAT_250_TICKS) {
|
||||
for (TileIndex cur_tile : st->custom_road_stop_tiles) {
|
||||
process_tile(cur_tile);
|
||||
}
|
||||
} else {
|
||||
process_tile(trigger_tile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger road stop randomisation
|
||||
*
|
||||
* @param st the station being triggered
|
||||
* @param tile the exact tile of the station that should be triggered
|
||||
* @param trigger trigger type
|
||||
* @param cargo_type cargo type causing the trigger
|
||||
*/
|
||||
void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type)
|
||||
{
|
||||
if (st == nullptr) st = Station::GetByTile(tile);
|
||||
|
||||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
* to bother with any further processing. */
|
||||
if (st->cached_roadstop_cargo_triggers == 0) return;
|
||||
if (cargo_type != CT_INVALID && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
|
||||
|
||||
SetBit(st->waiting_triggers, trigger);
|
||||
|
||||
uint32 whole_reseed = 0;
|
||||
|
||||
CargoTypes empty_mask = 0;
|
||||
if (trigger == RSRT_CARGO_TAKEN) {
|
||||
/* Create a bitmask of completely empty cargo types to be matched */
|
||||
for (CargoID i = 0; i < NUM_CARGO; i++) {
|
||||
if (st->goods[i].cargo.TotalCount() == 0) {
|
||||
SetBit(empty_mask, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 used_triggers = 0;
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
const RoadStopSpec *ss = GetRoadStopSpec(cur_tile);
|
||||
if (ss == nullptr) return;
|
||||
|
||||
/* Cargo taken "will only be triggered if all of those
|
||||
* cargo types have no more cargo waiting." */
|
||||
if (trigger == RSRT_CARGO_TAKEN) {
|
||||
if ((ss->cargo_triggers & ~empty_mask) != 0) return;
|
||||
}
|
||||
|
||||
if (cargo_type == CT_INVALID || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
RoadStopResolverObject object(ss, st, cur_tile, INVALID_ROADTYPE, GetStationType(cur_tile), GetStationGfx(cur_tile));
|
||||
object.waiting_triggers = st->waiting_triggers;
|
||||
|
||||
const SpriteGroup *group = object.Resolve();
|
||||
if (group == nullptr) return;
|
||||
|
||||
used_triggers |= object.used_triggers;
|
||||
|
||||
uint32 reseed = object.GetReseedSum();
|
||||
if (reseed != 0) {
|
||||
whole_reseed |= reseed;
|
||||
reseed >>= 16;
|
||||
|
||||
/* Set individual tile random bits */
|
||||
uint8 random_bits = st->GetRoadStopRandomBits(cur_tile);
|
||||
random_bits &= ~reseed;
|
||||
random_bits |= Random() & reseed;
|
||||
st->SetRoadStopRandomBits(cur_tile, random_bits);
|
||||
|
||||
MarkTileDirtyByTile(cur_tile, VMDF_NOT_MAP_MODE);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (trigger == RSRT_NEW_CARGO || trigger == RSRT_CARGO_TAKEN) {
|
||||
for (TileIndex cur_tile : st->custom_road_stop_tiles) {
|
||||
process_tile(cur_tile);
|
||||
}
|
||||
} else {
|
||||
process_tile(tile);
|
||||
}
|
||||
|
||||
/* Update whole station random bits */
|
||||
st->waiting_triggers &= ~used_triggers;
|
||||
if ((whole_reseed & 0xFFFF) != 0) {
|
||||
st->random_bits &= ~whole_reseed;
|
||||
st->random_bits |= Random() & whole_reseed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there's any new stations by a specific RoadStopType
|
||||
* @param rs the RoadStopType to check for.
|
||||
* @return true if there was any new RoadStopSpec's found for the given RoadStopType, else false.
|
||||
*/
|
||||
bool GetIfNewStopsByType(RoadStopType rs)
|
||||
{
|
||||
if (!(RoadStopClass::GetClassCount() > 1 || RoadStopClass::Get(ROADSTOP_CLASS_DFLT)->GetSpecCount() > 1)) return false;
|
||||
for (uint i = 0; i < RoadStopClass::GetClassCount(); i++) {
|
||||
// We don't want to check the default or waypoint classes. These classes are always available.
|
||||
if (i == ROADSTOP_CLASS_DFLT || i == ROADSTOP_CLASS_WAYP) continue;
|
||||
RoadStopClass *roadstopclass = RoadStopClass::Get((RoadStopClassID)i);
|
||||
if (GetIfClassHasNewStopsByType(roadstopclass, rs)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given RoadStopClass has any specs assigned to it, compatible with the given RoadStopType.
|
||||
* @param roadstopclass the RoadStopClass to check.
|
||||
* @param rs the RoadStopType to check by.
|
||||
* @return true if the roadstopclass has any specs compatible with the given RoadStopType.
|
||||
*/
|
||||
bool GetIfClassHasNewStopsByType(RoadStopClass *roadstopclass, RoadStopType rs)
|
||||
{
|
||||
for (uint j = 0; j < roadstopclass->GetSpecCount(); j++) {
|
||||
if (GetIfStopIsForType(roadstopclass->GetSpec(j), rs)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given RoadStopSpec is compatible with the given RoadStopType.
|
||||
* @param roadstopspec the RoadStopSpec to check.
|
||||
* @param rs the RoadStopType to check by.
|
||||
* @return true if the roadstopspec is compatible with the given RoadStopType.
|
||||
*/
|
||||
bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs)
|
||||
{
|
||||
// The roadstopspec is nullptr, must be the default station, always return true.
|
||||
if (roadstopspec == nullptr) return true;
|
||||
if (roadstopspec->stop_type == ROADSTOPTYPE_ALL) return true;
|
||||
|
||||
switch (rs) {
|
||||
case ROADSTOP_BUS: if (roadstopspec->stop_type == ROADSTOPTYPE_PASSENGER) return true; break;
|
||||
case ROADSTOP_TRUCK: if (roadstopspec->stop_type == ROADSTOPTYPE_FREIGHT) return true; break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const RoadStopSpec *GetRoadStopSpec(TileIndex t)
|
||||
{
|
||||
if (!IsCustomRoadStopSpecIndex(t)) return nullptr;
|
||||
|
||||
const BaseStation *st = BaseStation::GetByTile(t);
|
||||
uint specindex = GetCustomRoadStopSpecIndex(t);
|
||||
return specindex < st->num_roadstop_specs ? st->roadstop_speclist[specindex].spec : nullptr;
|
||||
}
|
||||
|
||||
int AllocateRoadStopSpecToStation(const RoadStopSpec *statspec, BaseStation *st, bool exec)
|
||||
{
|
||||
uint i;
|
||||
|
||||
if (statspec == nullptr || st == nullptr) return 0;
|
||||
|
||||
/* Try to find the same spec and return that one */
|
||||
for (i = 1; i < st->num_roadstop_specs && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
|
||||
if (st->roadstop_speclist[i].spec == statspec) return i;
|
||||
}
|
||||
|
||||
/* Try to find an unused spec slot */
|
||||
for (i = 1; i < st->num_roadstop_specs && i < NUM_ROADSTOPSPECS_PER_STATION; i++) {
|
||||
if (st->roadstop_speclist[i].spec == nullptr && st->roadstop_speclist[i].grfid == 0) break;
|
||||
}
|
||||
|
||||
if (i == NUM_ROADSTOPSPECS_PER_STATION) {
|
||||
/* Full, give up */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (exec) {
|
||||
if (i >= st->num_roadstop_specs) {
|
||||
st->num_roadstop_specs = i + 1;
|
||||
st->roadstop_speclist = ReallocT(st->roadstop_speclist, st->num_roadstop_specs);
|
||||
|
||||
if (st->num_roadstop_specs == 2) {
|
||||
/* Initial allocation */
|
||||
st->roadstop_speclist[0].spec = nullptr;
|
||||
st->roadstop_speclist[0].grfid = 0;
|
||||
st->roadstop_speclist[0].localidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
st->roadstop_speclist[i].spec = statspec;
|
||||
st->roadstop_speclist[i].grfid = statspec->grf_prop.grffile->grfid;
|
||||
st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id;
|
||||
|
||||
StationUpdateRoadStopCachedTriggers(st);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void DeallocateRoadStopSpecFromStation(BaseStation *st, byte specindex)
|
||||
{
|
||||
/* specindex of 0 (default) is never freeable */
|
||||
if (specindex == 0) return;
|
||||
|
||||
/* Check custom road stop tiles if the specindex is still in use */
|
||||
for (TileIndex tile : st->custom_road_stop_tiles) {
|
||||
if (GetCustomRoadStopSpecIndex(tile) == specindex) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* This specindex is no longer in use, so deallocate it */
|
||||
st->roadstop_speclist[specindex].spec = nullptr;
|
||||
st->roadstop_speclist[specindex].grfid = 0;
|
||||
st->roadstop_speclist[specindex].localidx = 0;
|
||||
|
||||
/* If this was the highest spec index, reallocate */
|
||||
if (specindex == st->num_roadstop_specs - 1) {
|
||||
for (; st->roadstop_speclist[st->num_roadstop_specs - 1].grfid == 0 && st->num_roadstop_specs > 1; st->num_roadstop_specs--) {}
|
||||
|
||||
if (st->num_roadstop_specs > 1) {
|
||||
st->roadstop_speclist = ReallocT(st->roadstop_speclist, st->num_roadstop_specs);
|
||||
} else {
|
||||
free(st->roadstop_speclist);
|
||||
st->num_roadstop_specs = 0;
|
||||
st->roadstop_speclist = nullptr;
|
||||
st->cached_roadstop_anim_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StationUpdateRoadStopCachedTriggers(st);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached animation trigger bitmask for a station.
|
||||
* @param st Station to update.
|
||||
*/
|
||||
void StationUpdateRoadStopCachedTriggers(BaseStation *st)
|
||||
{
|
||||
st->cached_roadstop_anim_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
|
||||
/* Combine animation trigger bitmask for all road stop specs
|
||||
* of this station. */
|
||||
for (uint i = 0; i < st->num_roadstop_specs; i++) {
|
||||
const RoadStopSpec *ss = st->roadstop_speclist[i].spec;
|
||||
if (ss != nullptr) {
|
||||
st->cached_roadstop_anim_triggers |= ss->animation.triggers;
|
||||
st->cached_roadstop_cargo_triggers |= ss->cargo_triggers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpRoadStopSpriteGroup(const BaseStation *st, const RoadStopSpec *spec, std::function<void(const char *)> print)
|
||||
{
|
||||
CargoID ctype = CT_DEFAULT_NA;
|
||||
|
||||
if (st == nullptr) {
|
||||
/* No station, so we are in a purchase list */
|
||||
ctype = CT_PURCHASE;
|
||||
} else if (Station::IsExpected(st)) {
|
||||
const Station *station = Station::From(st);
|
||||
/* Pick the first cargo that we have waiting */
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
if (spec->grf_prop.spritegroup[cs->Index()] != nullptr &&
|
||||
station->goods[cs->Index()].cargo.TotalCount() > 0) {
|
||||
ctype = cs->Index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spec->grf_prop.spritegroup[ctype] == nullptr) {
|
||||
ctype = CT_DEFAULT;
|
||||
}
|
||||
|
||||
DumpSpriteGroup(spec->grf_prop.spritegroup[ctype], std::move(print));
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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_roadstop.h NewGRF definitions and structures for road stops.
|
||||
*/
|
||||
|
||||
#ifndef NEWGRF_ROADSTATION_H
|
||||
#define NEWGRF_ROADSTATION_H
|
||||
|
||||
#include "newgrf_animation_type.h"
|
||||
#include "newgrf_spritegroup.h"
|
||||
#include "newgrf_class.h"
|
||||
#include "newgrf_commons.h"
|
||||
#include "newgrf_town.h"
|
||||
#include "road.h"
|
||||
|
||||
/** The maximum amount of roadstops a single GRF is allowed to add */
|
||||
static const int NUM_ROADSTOPS_PER_GRF = 255;
|
||||
|
||||
enum RoadStopClassID : byte {
|
||||
ROADSTOP_CLASS_BEGIN = 0, ///< The lowest valid value
|
||||
ROADSTOP_CLASS_DFLT = 0, ///< Default road stop class.
|
||||
ROADSTOP_CLASS_WAYP, ///< Waypoint class.
|
||||
ROADSTOP_CLASS_MAX = 255, ///< Maximum number of classes.
|
||||
};
|
||||
DECLARE_POSTFIX_INCREMENT(RoadStopClassID)
|
||||
|
||||
/* Some Triggers etc. */
|
||||
enum RoadStopRandomTrigger {
|
||||
RSRT_NEW_CARGO, ///< Trigger roadstop on arrival of new cargo.
|
||||
RSRT_CARGO_TAKEN, ///< Trigger roadstop when cargo is completely taken.
|
||||
RSRT_VEH_ARRIVES, ///< Trigger roadstop when road vehicle arrives.
|
||||
RSRT_VEH_DEPARTS, ///< Trigger roadstop when road vehicle leaves.
|
||||
RSRT_VEH_LOADS, ///< Trigger roadstop when road vehicle loads.
|
||||
};
|
||||
|
||||
/**
|
||||
* Various different options for availability, restricting
|
||||
* the roadstop to be only for busses or for trucks.
|
||||
*/
|
||||
enum RoadStopAvailabilityType : byte {
|
||||
ROADSTOPTYPE_PASSENGER, ///< This RoadStop is for passenger (bus) stops.
|
||||
ROADSTOPTYPE_FREIGHT, ///< This RoadStop is for freight (truck) stops.
|
||||
ROADSTOPTYPE_ALL, ///< This RoadStop is for both types of station road stops.
|
||||
|
||||
ROADSTOPTYPE_END,
|
||||
};
|
||||
|
||||
/**
|
||||
* Different draw modes to disallow rendering of some parts of the stop
|
||||
* or road.
|
||||
*/
|
||||
enum RoadStopDrawMode : byte {
|
||||
ROADSTOP_DRAW_MODE_NONE = 0,
|
||||
ROADSTOP_DRAW_MODE_ROAD = 1 << 0, ///< 0b01, Draw the road itself
|
||||
ROADSTOP_DRAW_MODE_OVERLAY = 1 << 1, ///< 0b10, Draw the road overlay for roadstops, e.g. pavement
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadStopDrawMode)
|
||||
|
||||
enum RoadStopSpecFlags {
|
||||
RSF_CB141_RANDOM_BITS, ///< Callback 141 needs random bits.
|
||||
};
|
||||
|
||||
enum RoadStopSpecIntlFlags {
|
||||
RSIF_BRIDGE_HEIGHTS_SET, ///< byte bridge_height[6] is set.
|
||||
RSIF_BRIDGE_DISALLOWED_PILLARS_SET, ///< byte bridge_disallowed_pillars[6] is set.
|
||||
};
|
||||
|
||||
/** Scope resolver for road stops. */
|
||||
struct RoadStopScopeResolver : public ScopeResolver {
|
||||
TileIndex tile; ///< %Tile of the station.
|
||||
struct BaseStation *st; ///< Instance of the station.
|
||||
const struct RoadStopSpec *roadstopspec; ///< Station (type) specification.
|
||||
CargoID cargo_type; ///< Type of cargo of the station.
|
||||
StationType type; ///< Station type.
|
||||
uint8 view; ///< Station axis.
|
||||
RoadType roadtype; ///< Road type (used when no tile)
|
||||
|
||||
RoadStopScopeResolver(ResolverObject& ro, BaseStation* st, const RoadStopSpec *roadstopspec, TileIndex tile, RoadType roadtype, StationType type, uint8 view = 0)
|
||||
: ScopeResolver(ro), tile(tile), st(st), roadstopspec(roadstopspec), type(type), view(view), roadtype(roadtype)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32 GetRandomBits() const override;
|
||||
uint32 GetTriggers() const override;
|
||||
|
||||
uint32 GetVariable(uint16 variable, uint32 parameter, GetVariableExtra *extra) const override;
|
||||
};
|
||||
|
||||
/** Road stop resolver. */
|
||||
struct RoadStopResolverObject : public ResolverObject {
|
||||
RoadStopScopeResolver roadstop_scope; ///< The stop scope resolver.
|
||||
TownScopeResolver *town_scope; ///< The town scope resolver (created on the first call).
|
||||
|
||||
RoadStopResolverObject(const RoadStopSpec* roadstopspec, BaseStation* st, TileIndex tile, RoadType roadtype, StationType type, uint8 view, CallbackID callback = CBID_NO_CALLBACK, uint32 param1 = 0, uint32 param2 = 0);
|
||||
~RoadStopResolverObject();
|
||||
|
||||
ScopeResolver* GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override {
|
||||
switch (scope) {
|
||||
case VSG_SCOPE_SELF: return &this->roadstop_scope;
|
||||
case VSG_SCOPE_PARENT: {
|
||||
TownScopeResolver *tsr = this->GetTown();
|
||||
if (tsr != nullptr) return tsr;
|
||||
FALLTHROUGH;
|
||||
}
|
||||
default: return ResolverObject::GetScope(scope, relative);
|
||||
}
|
||||
}
|
||||
|
||||
TownScopeResolver *GetTown();
|
||||
|
||||
const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
|
||||
};
|
||||
|
||||
/** Road stop specification. */
|
||||
struct RoadStopSpec {
|
||||
/**
|
||||
* Properties related the the grf file.
|
||||
* NUM_CARGO real cargo plus three pseudo cargo sprite groups.
|
||||
* Used for obtaining the sprite offset of custom sprites, and for
|
||||
* evaluating callbacks.
|
||||
*/
|
||||
GRFFilePropsBase<NUM_CARGO + 3> grf_prop;
|
||||
RoadStopClassID cls_id; ///< The class to which this spec belongs.
|
||||
int spec_id; ///< The ID of this spec inside the class.
|
||||
StringID name; ///< Name of this stop
|
||||
|
||||
RoadStopAvailabilityType stop_type = ROADSTOPTYPE_ALL;
|
||||
RoadStopDrawMode draw_mode = ROADSTOP_DRAW_MODE_ROAD | ROADSTOP_DRAW_MODE_OVERLAY;
|
||||
uint8 callback_mask = 0;
|
||||
uint8 flags = 0;
|
||||
uint8 internal_flags = 0; ///< Bitmask of internal spec flags (RoadStopSpecIntlFlags)
|
||||
|
||||
CargoTypes cargo_triggers = 0; ///< Bitmask of cargo types which cause trigger re-randomizing
|
||||
|
||||
AnimationInfo animation;
|
||||
|
||||
byte bridge_height[6]; ///< Minimum height for a bridge above, 0 for none
|
||||
byte bridge_disallowed_pillars[6]; ///< Disallowed pillar flags for a bridge above
|
||||
|
||||
static const RoadStopSpec *Get(uint16 index);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct EnumPropsT<RoadStopClassID> : MakeEnumPropsT<RoadStopClassID, byte, ROADSTOP_CLASS_BEGIN, ROADSTOP_CLASS_MAX, ROADSTOP_CLASS_MAX, 8> {};
|
||||
|
||||
typedef NewGRFClass<RoadStopSpec, RoadStopClassID, ROADSTOP_CLASS_MAX> RoadStopClass;
|
||||
|
||||
void DrawRoadStopTile(int x, int y, RoadType roadtype, const RoadStopSpec *spec, StationType type, int view);
|
||||
|
||||
uint16 GetRoadStopCallback(CallbackID callback, uint32 param1, uint32 param2, const RoadStopSpec *roadstopspec, BaseStation *st, TileIndex tile, RoadType roadtype, StationType type, uint8 view);
|
||||
|
||||
void AnimateRoadStopTile(TileIndex tile);
|
||||
uint8 GetRoadStopTileAnimationSpeed(TileIndex tile);
|
||||
void TriggerRoadStopAnimation(BaseStation *st, TileIndex tile, StationAnimationTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
void TriggerRoadStopRandomisation(Station *st, TileIndex tile, RoadStopRandomTrigger trigger, CargoID cargo_type = CT_INVALID);
|
||||
|
||||
bool GetIfNewStopsByType(RoadStopType rs);
|
||||
bool GetIfClassHasNewStopsByType(RoadStopClass *roadstopclass, RoadStopType rs);
|
||||
bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs);
|
||||
|
||||
uint GetCountOfCompatibleStopsByType(RoadStopClass *roadstopclass, RoadStopType rs);
|
||||
|
||||
const RoadStopSpec *GetRoadStopSpec(TileIndex t);
|
||||
int AllocateRoadStopSpecToStation(const RoadStopSpec *statspec, BaseStation *st, bool exec);
|
||||
void DeallocateRoadStopSpecFromStation(BaseStation *st, byte specindex);
|
||||
void StationUpdateRoadStopCachedTriggers(BaseStation *st);
|
||||
|
||||
#endif /* NEWGRF_ROADSTATION_H */
|
Loading…
Reference in New Issue