Changeset - r6332:7393965b5322
[Not reviewed]
master
0 23 5
maedhros - 18 years ago 2007-03-19 11:27:30
maedhros@openttd.org
(svn r9315) -Merge: The newhouses branch. With this merge comes almost complete support for
the newhouses grf specs, so all newhouses grfs will be playable in the game.

Many thanks to everyone who contributed code and ideas, and all the testers
who found things we missed.
28 files changed with 3050 insertions and 1270 deletions:
0 comments (0 inline, 0 general)
docs/landscape.html
Show inline comments
 
@@ -565,627 +565,73 @@
 
   <td><strong>Town building </strong></td>
 
  </tr>
 
  <tr>
 
   <td valign=top nowrap>&nbsp;</td>
 
   <td>
 
    <ul>
 
     <li>m2: Index into the array of towns</li>
 
     <li>m3 bits 7..6: stage of construction (<tt>3</tt> = completed)</li>
 
     <li>m4: <a name="HouseTypes">town building type</a>:<br>
 
      <small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
 
      <table>
 
       <tr>
 
        <th align=left>Type&nbsp;</th>
 
        <th align=left>Size&nbsp;</th>
 
        <th align=left>Climates&nbsp;</th>
 
        <th align=left>Description</th>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>00</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>01</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>02</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>small block of flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>03</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>church</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>04</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-arctic, sub-tropical</td>
 
        <td align=left>large office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>05</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>large office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>06</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>town houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
 
        <td>1&times;2</td>
 
        <td>temperate</td>
 
        <td align=left>hotel</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>09</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
 
        <td align=left>statue</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>0A</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-arctic, sub-tropical</td>
 
        <td align=left>fountain</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>0B</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>park (with a pond)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>0C</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>park (with an alley)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>0D</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>various types of shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>11</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-arctic, sub-tropical</td>
 
        <td align=left>modern office building</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>12</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>warehouse</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>13</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>office block (with spiral stairway on the side)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
 
        <td>2&times;2</td>
 
        <td>temperate</td>
 
        <td align=left>stadium</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>18</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>old houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>19</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>cottages</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1A</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1B</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1C</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1D</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1E</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-tropical</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>1F</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>theatre</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
 
        <td>2&times;2</td>
 
        <td>temperate, sub-arctic, sub-tropical</td>
 
        <td align=left>stadium (modern style)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>24</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate, sub-arctic, sub-tropical</td>
 
        <td align=left>offices (the modern 'vertical tube' style)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>25</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>26</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>27</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>temperate</td>
 
        <td align=left>cinema</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
 
        <td>2&times;2</td>
 
        <td>temperate</td>
 
        <td align=left>shopping mall</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>2C</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>2D</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>2E</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>2F</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>30</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>31</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>32</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic, sub-tropical</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>33</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>34</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>35</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>36</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic, sub-tropical</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>37</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>38</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>39</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3A</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3B</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3C</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>church</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3D</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>church</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3E</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>3F</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>40</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>41</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
 
        <td>1&times;2</td>
 
        <td>sub-arctic</td>
 
        <td align=left>hotel</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
 
        <td>1&times;2</td>
 
        <td>snow</td>
 
        <td align=left>hotel</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>46</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic, sub-tropical</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>47</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>48</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>49</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>snow</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
 
        <td>2&times;1</td>
 
        <td>sub-arctic</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
 
        <td>2&times;1</td>
 
        <td>snow</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>4E</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>houses (with a tree in a corner)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>51</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>houses (suburb-type)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>52</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>53</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>church</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>54</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>houses (with two trees in front)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
 
        <td>2&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>59</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>flats</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>5A</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>sub-tropical</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>5B</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>church</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>various types of toyland houses</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>62</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
 
        <td>1&times;2</td>
 
        <td>toyland</td>
 
        <td align=left>houses ('shoe' style)</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>65</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>66</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>igloo</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>67</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>tepees</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>shops and offices</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>6A</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>tall office block</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>6B</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>statue</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>6C</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>teapot-house</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>6D</tt>&nbsp; </td>
 
        <td>1&times;1</td>
 
        <td>toyland</td>
 
        <td align=left>piggy-bank</td>
 
       </tr>
 
      </table>
 
     </li>
 
     <li>m5 bits 2..0: construction counter, for buildings under construction incremented on every periodic tile processing<br>
 
         On wraparound the stage of construction in m3 is increased
 
     </li>
 
     <li>for large office blocks (types <tt>04</tt> and <tt>05</tt>):
 
     <li>m1 : Random bits <a href="#newhouses">(newhouses)</a> </li>
 
     <li>m2 : index into the array of industries</li>
 
     <li>m3 bit 7 :
 
      <ul>
 
       <li>m1 bits 6..0: position of the lift</li>
 
       <li>m1 bit 7: if set the lift is moving</li>
 
       <li>m5 bit 7: if set then m5 bits 5..0 hold the destination floor of the lift, which could be 0..6, except 1.<br>
 
           So the building has 6 effective floors. This is due to the fact that the first floor is 2 'normal' floors high.<br>
 
           One 'normal' floor has a height of 6 lift positions.</li>
 
       <li> set : House is complete
 
        <ul>
 
         <li>m5 : age of House. Maximum been 255, which means 255 years and more</li>
 
        </ul>
 
       </li>
 
       <li> clear : House is in construction
 
        <ul>
 
         <li>m5 bits 7..5 : free</li>
 
         <li>m5 bits 4..3 : construction stage</li>
 
         <li>m5 bits 2..0 : construction counter</li>
 
        </ul>
 
       </li>
 
      </ul>
 
     <li>m3 bit 6 : 9th bit of house type (m4), allowing 512 different types.</li>
 
     <li>m3 bits 5..0 : triggers activated <a href="#newhouses">(newhouses)</a></li>
 
     <li>m4 : <a href="landscape_externals.html">town building type</a> (with m3[6] bit)</li>
 
     <li>m5 : see m3 bit 7</li>
 
     <li>m6 :
 
      <ul>
 
       <li>If <a href="#newhouses">newhouses</a> is activated
 
        <ul>
 
         <li>bits 7..3 : Current animation frame</li>
 
         <li>bit 2 : free</li>
 
        </ul>
 
       </li>
 
       <li>Standard behaviour
 
        <ul>
 
         <li>bits 7..2 : lift position (for houses type 04 and 05)</li>
 
        </ul>
 
       </li>
 
       <li>bits 1..0 : tropic zone specifier</li>
 
      </ul>
 
     </li>
 
     <li>m6 bits 1..0 : <a href="#tropic_zone">Tropic zone definition</a></li>
 
     <li>m7 :
 
      <ul>
 
       <li>If <a href="#newhouses">newhouses</a> is activated
 
        <ul>
 
         <li>Periodic processing time remaining</li>
 
        </ul>
 
       </li>
 
       <li>Standard behaviour (only for houses type 04 and 05)
 
        <ul>
 
         <li>bits 7..4 : free</li>
 
         <li>bits 3..1 : lift destination.  Values can be 0..6, except 1.<br>
 
             So the building has 6 effective floors. This is due to the fact that the first floor is 2 'normal' floors high.<br>
 
             One 'normal' floor has a height of 6 lift positions.
 
         </li>
 
         <li>bit 0 : Lift has destination when set</li>
 
        </ul>
 
       </li>
 
      </ul>
 
     </li>
 
    </ul>
 
    <small><a name="newhouses">Newhouses is the name englobing a newGRF feature developped by TTDPatch devs (mainly Csaboka).<br>
 
    It allows the replacement of the properties as well as the graphics of houses in the game.<br>
 
    To distinguish between the standard behaviour and the newGRF one, HouseID (m4 + m3[6]) is tested for anything above 110.<br>
 
    110 is the count of standard houses. So above 110 means there is a new definition of at least one house</small>
 
   </td>
 
  </tr>
 

	
 
  <tr bgcolor="#CCCCCC">
 
   <td valign=top nowrap><strong><a name="Class4"><tt> 4 </tt></a></strong></td>
 
   <td><strong>Trees </strong></td>
docs/landscape_externals.html
Show inline comments
 
new file 100644
 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 
<html>
 

	
 
<head>
 
 <meta name="Author" content="Marcin Grzegorczyk">
 
 <meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
 
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 
 <title>OpenTTD Landscape externals</title>
 
</head>
 

	
 
<body>
 
 <h3><a name="Landscape">Landscape</a></h3>
 
 <p>
 
 These are the different house types available on standard game.<br>
 
 <small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
 
 </p>
 

	
 
 <table>
 
  <tr>
 
   <th align=left>Type&nbsp;</th>
 
   <th align=left>Size&nbsp;</th>
 
   <th align=left>Climates&nbsp;</th>
 
   <th align=left>Description</th>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>00</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>01</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>02</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>small block of flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>03</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>church</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>04</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-arctic, sub-tropical</td>
 
   <td align=left>large office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>05</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>large office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>06</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>town houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
 
   <td>1&times;2</td>
 
   <td>temperate</td>
 
   <td align=left>hotel</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>09</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
 
   <td align=left>statue</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>0A</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-arctic, sub-tropical</td>
 
   <td align=left>fountain</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>0B</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>park (with a pond)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>0C</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>park (with an alley)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>0D</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>various types of shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>11</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-arctic, sub-tropical</td>
 
   <td align=left>modern office building</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>12</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>warehouse</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>13</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>office block (with spiral stairway on the side)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
 
   <td>2&times;2</td>
 
   <td>temperate</td>
 
   <td align=left>stadium</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>18</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>old houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>19</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>cottages</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1A</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1B</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1C</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1D</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1E</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-tropical</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>1F</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>theatre</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
 
   <td>2&times;2</td>
 
   <td>temperate, sub-arctic, sub-tropical</td>
 
   <td align=left>stadium (modern style)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>24</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate, sub-arctic, sub-tropical</td>
 
   <td align=left>offices (the modern 'vertical tube' style)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>25</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>26</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>27</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>temperate</td>
 
   <td align=left>cinema</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
 
   <td>2&times;2</td>
 
   <td>temperate</td>
 
   <td align=left>shopping mall</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>2C</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>2D</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>2E</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>2F</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>30</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>31</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>32</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic, sub-tropical</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>33</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>34</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>35</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>36</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic, sub-tropical</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>37</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>38</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>39</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3A</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3B</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3C</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>church</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3D</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>church</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3E</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>3F</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>40</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>41</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
 
   <td>1&times;2</td>
 
   <td>sub-arctic</td>
 
   <td align=left>hotel</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
 
   <td>1&times;2</td>
 
   <td>snow</td>
 
   <td align=left>hotel</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>46</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic, sub-tropical</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>47</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>48</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>49</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>snow</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
 
   <td>2&times;1</td>
 
   <td>sub-arctic</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
 
   <td>2&times;1</td>
 
   <td>snow</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>4E</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>houses (with a tree in a corner)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>51</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>houses (suburb-type)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>52</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>53</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>church</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>54</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>houses (with two trees in front)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
 
   <td>2&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>59</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>flats</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>5A</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>sub-tropical</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>5B</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>church</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>various types of toyland houses</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>62</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
 
   <td>1&times;2</td>
 
   <td>toyland</td>
 
   <td align=left>houses ('shoe' style)</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>65</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>66</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>igloo</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>67</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>tepees</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>shops and offices</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>6A</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>tall office block</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>6B</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>statue</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>6C</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>teapot-house</td>
 
  </tr>
 

	
 
  <tr>
 
   <td nowrap valign=top><tt>6D</tt>&nbsp; </td>
 
   <td>1&times;1</td>
 
   <td>toyland</td>
 
   <td align=left>piggy-bank</td>
 
  </tr>
 
 </table>
 
</body>
 

	
 
</html>
 
\ No newline at end of file
docs/landscape_grid.html
Show inline comments
 
@@ -30,12 +30,13 @@ the array so you can quickly see what is
 
  <li><span style="font-weight: bold;">m1</span> - 8 bits in size, used to identify the owner of that tile (eg piece of rail, bridge, etc.)</li>
 
  <li><span style="font-weight: bold;">m2</span> - 16 bits in size, used to identify the index of the given tile (object) in the (object-)array</li>
 
  <li><span style="font-weight: bold;">m3</span> - 8 bits in size, is used for general storage</li>
 
  <li><span style="font-weight: bold;">m4</span> - 8 bits in size, is used for general storage</li>
 
  <li><span style="font-weight: bold;">m5</span> - 8 bits in size, is used for general storage</li>
 
  <li><span style="font-weight: bold;">m6</span> - 8 bits in size, special meaning : lower 2 bits only valid in tropic climate, upper 2 bits for bridges</li>
 
  <li><span style="font-weight: bold;">m7</span> - 8 bits in size, is used for general storage</li>
 
</ul>
 

	
 
<table align=center border="1" cellpadding="2" cellspacing="2">
 
  <tbody>
 
    <tr>
 
      <th colspan=2>class</th>
 
@@ -43,212 +44,236 @@ the array so you can quickly see what is
 
      <th>m1 (8)</th>
 
      <th>m2 (16)</th>
 
      <th>m3 (8)</th>
 
      <th>m4 (8)</th>
 
      <th>m5 (8)</th>
 
      <th>m6 (8)</th>
 
      <th>m7 (8)</th>
 
    </tr>
 
    <tr>
 
      <td colspan=2 class="caption">bits</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">FEDC BA98 7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
      <td class="bits">7654 3210</td>
 
    </tr>
 
    <tr>
 
      <td rowspan="2">0</td>
 
      <td class="caption">ground</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">XXXX XX<span class="free">OO</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">farmland</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOO</span>X XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td rowspan=3>1</td>
 
      <td class="caption">rail</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO O</span>XXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">depot</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits">XX<span class="free">OO O</span>XXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">waypoint</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits">XX<span class="free">OO O</span>XXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td rowspan=3>2</td>
 
      <td class="caption">road</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">level crossing</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XX<span class="free">OO</span></td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">road depot</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits">X<span class="free">OOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>3</td>
 
      <td class="caption">town</td>
 
      <td class="caption">house</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="abuse">XXXX XXXX</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OOOO</span></td>
 
      <td class="bits">XX<span class="free">O</span>X XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">X<span class="free">O</span>XX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits">XX<span class="abuse">XX XXXX</span></td>
 
      <td class="bits"><span class="abuse">XXXX XX</span>XX</td>
 
      <td class="bits"><span class="abuse">X</span>XX<span class="abuse">X XXX</span>X</td>
 
    </tr>
 
    <tr>
 
      <td>4</td>
 
      <td class="caption">trees</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XX<span class="free">OO</span></td>
 
      <td class="bits">XX<span class="free">OO O</span>XXX</td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>5</td>
 
      <td class="caption">station</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO O</span>XXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>6</td>
 
      <td class="caption">water</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td rowspan=3>8</td>
 
      <td class="caption">industry</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X XXXX</span></td>
 
      <td class="bits"><span class="abuse">X</span><span class="free">OO</span><span class="abuse">X
 
        XXXX</span></td>
 
      <td class="bits">XXXX XXXX XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>bubble/sugar/toffee,<BR>gold/copper/coal,<BR>oil wells, power station</td>
 
      <td>bubble/sugar/toffee,<BR>
 
        gold/copper/coal,<BR>
 
        oil wells, power station</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XXXX XXXX</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">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>toy factory</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="abuse">X</span><span class="free">OOO OOOO</span></td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td rowspan=2>9</td>
 
      <td class="caption">tunnel entrance</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits">X<span class="free">OOO OOOO</span></td>
 
      <td class="bits">X<span class="free">OOO</span> XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>bridge ramp</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span> <span class="free">OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span> <span class="abuse">XXXX</span>
 
        <span class="free">OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO</span> XXXX</td>
 
      <td class="bits">X<span class="free">OOO OOOO</span></td>
 
      <td class="bits">X<span class="free">OOO</span> XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td>A</td>
 
      <td class="caption">unmovables</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
  </tbody>
 
</table>
 

	
 
</body>
 
</html>
projects/openttd.vcproj
Show inline comments
 
@@ -516,24 +516,30 @@
 
				RelativePath=".\..\src\newgrf_config.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_engine.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_house.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_sound.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_spritegroup.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_station.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\news.h">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\npf.h">
 
			</File>
 
			<File
 
@@ -923,23 +929,29 @@
 
				RelativePath=".\..\src\newgrf_config.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_engine.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_house.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_sound.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_spritegroup.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_station.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.cpp">
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.cpp">
 
			</File>
 
		</Filter>
 
		<Filter
 
			Name="Map Accessors"
 
			Filter="">
 
			<File
 
				RelativePath=".\..\src\bridge_map.cpp">
projects/openttd_vs80.vcproj
Show inline comments
 
@@ -445,17 +445,17 @@
 
			>
 
			<File
 
				RelativePath=".\..\src\airport.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\aystar.cpp"
 
				RelativePath=".\..\src\autoreplace_cmd.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\autoreplace_cmd.cpp"
 
				RelativePath=".\..\src\aystar.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\bmp.cpp"
 
				>
 
			</File>
 
@@ -917,12 +917,16 @@
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_engine.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_house.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_sound.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_spritegroup.h"
 
				>
 
@@ -933,12 +937,16 @@
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\news.h"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\npf.h"
 
				>
 
@@ -1453,12 +1461,16 @@
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_engine.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_house.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_sound.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_spritegroup.cpp"
 
				>
 
@@ -1468,12 +1480,16 @@
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_text.cpp"
 
				>
 
			</File>
 
			<File
 
				RelativePath=".\..\src\newgrf_town.cpp"
 
				>
 
			</File>
 
		</Filter>
 
		<Filter
 
			Name="Map Accessors"
 
			>
 
			<File
 
				RelativePath=".\..\src\bridge_map.cpp"
source.list
Show inline comments
 
@@ -137,16 +137,18 @@ network/network_server.h
 
network/network_udp.h
 
newgrf.h
 
newgrf_callbacks.h
 
newgrf_cargo.h
 
newgrf_config.h
 
newgrf_engine.h
 
newgrf_house.h
 
newgrf_sound.h
 
newgrf_spritegroup.h
 
newgrf_station.h
 
newgrf_text.h
 
newgrf_town.h
 
news.h
 
npf.h
 
music/null_m.h
 
sound/null_s.h
 
video/null_v.h
 
oldpool.h
 
@@ -276,16 +278,18 @@ ai/trolly/shared.cpp
 
ai/trolly/trolly.cpp
 

	
 
# NewGRF
 
newgrf.cpp
 
newgrf_config.cpp
 
newgrf_engine.cpp
 
newgrf_house.cpp
 
newgrf_sound.cpp
 
newgrf_spritegroup.cpp
 
newgrf_station.cpp
 
newgrf_text.cpp
 
newgrf_town.cpp
 

	
 
# Map Accessors
 
bridge_map.cpp
 
bridge_map.h
 
clear_map.h
 
industry_map.h
src/map.cpp
Show inline comments
 
@@ -19,13 +19,14 @@ extern "C" _CRTIMP void __cdecl _assert(
 
uint _map_log_x;
 
uint _map_size_x;
 
uint _map_size_y;
 
uint _map_tile_mask;
 
uint _map_size;
 

	
 
Tile* _m = NULL;
 
Tile *_m = NULL;
 
TileExtended *_me = NULL;
 

	
 

	
 
void AllocateMap(uint size_x, uint size_y)
 
{
 
	/* Make sure that the map size is within the limits and that
 
	 * the x axis size is a power of 2. */
 
@@ -41,16 +42,22 @@ void AllocateMap(uint size_x, uint size_
 
	_map_size_x = size_x;
 
	_map_size_y = size_y;
 
	_map_size = size_x * size_y;
 
	_map_tile_mask = _map_size - 1;
 

	
 
	free(_m);
 
	free(_me);
 

	
 
	_m = CallocT<Tile>(_map_size);
 
 	_me = CallocT<TileExtended>(_map_size);
 

	
 
	/* XXX TODO handle memory shortage more gracefully */
 
	if (_m == NULL) error("Failed to allocate memory for the map");
 
 	/* XXX @todo handle memory shortage more gracefully
 
 	 * Maybe some attemps could be made to try with smaller maps down to 64x64
 
 	 * Maybe check for available memory before doing the calls, after all, we know how big
 
 	 * the map is */
 
	if ((_m == NULL) || (_me == NULL)) error("Failed to allocate memory for the map");
 
}
 

	
 

	
 
#ifdef _DEBUG
 
TileIndex TileAdd(TileIndex tile, TileIndexDiff add,
 
	const char *exp, const char *file, int line)
src/map.h
Show inline comments
 
@@ -25,13 +25,18 @@ struct Tile {
 
	byte m3;
 
	byte m4;
 
	byte m5;
 
	byte m6;
 
};
 

	
 
extern Tile* _m;
 
struct TileExtended {
 
	byte m7;
 
};
 

	
 
extern Tile *_m;
 
extern TileExtended *_me;
 

	
 
void AllocateMap(uint size_x, uint size_y);
 

	
 
/* binary logarithm of the map size, try to avoid using this one */
 
static inline uint MapLogX()  { return _map_log_x; }
 
/* The size of the map */
src/misc.cpp
Show inline comments
 
@@ -15,12 +15,13 @@
 
#include "vehicle.h"
 
#include "saveload.h"
 
#include "engine.h"
 
#include "vehicle_gui.h"
 
#include "variables.h"
 
#include "ai/ai.h"
 
#include "newgrf_house.h"
 
#include "date.h"
 
#include "cargotype.h"
 

	
 
char _name_array[512][32];
 

	
 
#ifndef MERSENNE_TWISTER
 
@@ -129,12 +130,13 @@ void InitializeGame(int mode, uint size_
 
	InitializeDockGui();
 
	InitializeTowns();
 
	InitializeTrees();
 
	InitializeSigns();
 
	InitializeStations();
 
	InitializeIndustries();
 
	InitializeBuildingCounts();
 
	InitializeMainGui();
 

	
 
	InitializeNameMgr();
 
	InitializeVehiclesGuiList();
 
	InitializeTrains();
 
	InitializeNPF();
 
@@ -575,12 +577,40 @@ static void Save_MAP6()
 

	
 
		for (j = 0; j != lengthof(buf); j++) buf[j] = _m[i++].m6;
 
		SlArray(buf, lengthof(buf), SLE_UINT8);
 
	}
 
}
 

	
 
static void Load_MAP7()
 
{
 
	uint size = MapSize();
 
	uint i;
 

	
 
	for (i = 0; i != size;) {
 
		uint8 buf[4096];
 
		uint j;
 

	
 
		SlArray(buf, lengthof(buf), SLE_UINT8);
 
		for (j = 0; j != lengthof(buf); j++) _me[i++].m7 = buf[j];
 
	}
 
}
 

	
 
static void Save_MAP7()
 
{
 
	uint size = MapSize();
 
	uint i;
 

	
 
	SlSetLength(size);
 
	for (i = 0; i != size;) {
 
		uint8 buf[4096];
 
		uint j;
 

	
 
		for (j = 0; j != lengthof(buf); j++) buf[j] = _me[i++].m7;
 
		SlArray(buf, lengthof(buf), SLE_UINT8);
 
	}
 
}
 

	
 
static void Save_CHTS()
 
{
 
	byte count = sizeof(_cheats)/sizeof(Cheat);
 
	Cheat* cht = (Cheat*) &_cheats;
 
	Cheat* cht_last = &cht[count];
 
@@ -611,12 +641,13 @@ extern const ChunkHandler _misc_chunk_ha
 
	{ 'MAPO', Save_MAP1,     Load_MAP1,     CH_RIFF },
 
	{ 'MAP2', Save_MAP2,     Load_MAP2,     CH_RIFF },
 
	{ 'M3LO', Save_MAP3,     Load_MAP3,     CH_RIFF },
 
	{ 'M3HI', Save_MAP4,     Load_MAP4,     CH_RIFF },
 
	{ 'MAP5', Save_MAP5,     Load_MAP5,     CH_RIFF },
 
	{ 'MAPE', Save_MAP6,     Load_MAP6,     CH_RIFF },
 
	{ 'MAP7', Save_MAP7,     Load_MAP7,     CH_RIFF },
 

	
 
	{ 'NAME', Save_NAME,     Load_NAME,     CH_ARRAY},
 
	{ 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF},
 
	{ 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF},
 
	{ 'CHTS', Save_CHTS,     Load_CHTS,     CH_RIFF | CH_LAST}
 
};
src/misc_gui.cpp
Show inline comments
 
@@ -185,12 +185,13 @@ static void Place_LandInfo(TileIndex til
 
	DEBUG(misc, LANDINFOD_LEVEL, "m1           = %#x", _m[tile].m1);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m2           = %#x", _m[tile].m2);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m3           = %#x", _m[tile].m3);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m4           = %#x", _m[tile].m4);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m5           = %#x", _m[tile].m5);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m6           = %#x", _m[tile].m6);
 
	DEBUG(misc, LANDINFOD_LEVEL, "m7           = %#x", _me[tile].m7);
 
#undef LANDINFOD_LEVEL
 
}
 

	
 
void PlaceLandBlockInfo()
 
{
 
	if (_cursor.sprite == SPR_CURSOR_QUERY) {
src/newgrf.cpp
Show inline comments
 
@@ -15,25 +15,28 @@
 
#include "sprite.h"
 
#include "newgrf.h"
 
#include "variables.h"
 
#include "string.h"
 
#include "table/strings.h"
 
#include "bridge.h"
 
#include "town.h"
 
#include "economy.h"
 
#include "newgrf_engine.h"
 
#include "vehicle.h"
 
#include "newgrf_text.h"
 
#include "table/sprites.h"
 
#include "fontcache.h"
 
#include "date.h"
 
#include "currency.h"
 
#include "sound.h"
 
#include "newgrf_config.h"
 
#include "newgrf_house.h"
 
#include "newgrf_sound.h"
 
#include "newgrf_spritegroup.h"
 
#include "helpers.hpp"
 
#include "table/town_land.h"
 
#include "cargotype.h"
 

	
 
/* TTDPatch extended GRF format codec
 
 * (c) Petr Baudis 2004 (GPL'd)
 
 * Changes by Florian octo Forster are (c) by the OpenTTD development team.
 
 *
 
@@ -65,12 +68,15 @@ static uint32 _ttdpatch_flags[8];
 
/* Used by Action 0x06 to preload a pseudo sprite and modify its content */
 
static byte *_preload_sprite = NULL;
 

	
 
/* Set if any vehicle is loaded which uses 2cc (two company colours) */
 
bool _have_2cc = false;
 

	
 
/* Set if there are any newhouses loaded. */
 
bool _have_newhouses = false;
 

	
 
/* Default cargo translation table. By default there are 27 possible cargo types */
 
static const uint _default_cargo_max = 27;
 
static CargoLabel _default_cargo_list[_default_cargo_max];
 

	
 

	
 
enum GrfDataType {
 
@@ -224,12 +230,38 @@ static GRFFile *GetFileByFilename(const 
 
		if (strcmp(file->filename, filename) == 0) break;
 
	}
 
	return file;
 
}
 

	
 

	
 
/** Used when setting an object's property to map to the GRF's strings
 
 * while taking in consideration the "drift" between TTDPatch string system and OpenTTD's one
 
 * @param str StringID that we want to have the equivalent in OoenTTD
 
 * @return the properly adjusted StringID
 
 */
 
static StringID MapGRFStringID(StringID str)
 
{
 
	/* 0xD0 and 0xDC stand for all the TextIDs in the range
 
	*  of 0xD000 (misc graphics texts) and 0xDC00 (misc persistent texts).
 
	 * These strings are unique to each grf file, and thus require to be used with the
 
	 * grfid in which they are declared */
 
	if (GB(str, 8, 8) == 0xD0 || GB(str, 8, 8) == 0xDC) {
 
		return GetGRFStringID(_cur_grffile->grfid, str);
 
	}
 

	
 
	/* Map building names according to our lang file changes
 
	 * 0x200F = Tall Office Block, first house name in the original data, the one that TTDPatch stil uses
 
	 * 0x201F = Old houses is the last house name.
 
	 * OpenTTD does not have exactly the same order aymore, so, the code below allows
 
	 * to compensate for the difference */
 
	if (str >= 0x200F && str <= 0x201F) return str + (STR_200F_TALL_OFFICE_BLOCK - 0x200F);
 

	
 
	return str;
 
}
 

	
 

	
 
typedef bool (*VCI_Handler)(uint engine, int numinfo, int prop, byte **buf, int len);
 

	
 
#define FOR_EACH_OBJECT for (i = 0; i < numinfo; i++)
 

	
 
static void dewagonize(int condition, int engine)
 
{
 
@@ -1165,12 +1197,212 @@ static bool BridgeChangeInfo(uint brid, 
 
	}
 

	
 
	*bufp = buf;
 
	return ret;
 
}
 

	
 
static bool TownHouseChangeInfo(uint hid, int numinfo, int prop, byte **bufp, int len)
 
{
 
	HouseSpec **housespec;
 
	byte *buf = *bufp;
 
	int i;
 
	bool ret = false;
 

	
 
	if (hid + numinfo >= HOUSE_MAX) {
 
		grfmsg(1, "TownHouseChangeInfo: Too many houses loaded (%u), max (%u). Ignoring.", hid + numinfo, HOUSE_MAX-1);
 
		return false;
 
	}
 

	
 
	/* Allocate house specs if they haven't been allocated already. */
 
	if (_cur_grffile->housespec == NULL) {
 
		_cur_grffile->housespec = CallocT<HouseSpec*>(HOUSE_MAX);
 

	
 
		/* Reset any overrides that have been set. */
 
		ResetHouseOverrides();
 
	}
 

	
 
	housespec = &_cur_grffile->housespec[hid];
 

	
 
	if (prop != 0x08) {
 
		/* Check that all the houses being modified have been defined. */
 
		FOR_EACH_OBJECT {
 
			if (housespec[i] == NULL) {
 
				grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i);
 
				return false;
 
			}
 
		}
 
	}
 

	
 
	switch (prop) {
 
		case 0x08: // Substitute building type, and definition of a new house
 
			FOR_EACH_OBJECT {
 
				byte subs_id = grf_load_byte(&buf);
 

	
 
				if (subs_id == 0xFF) {
 
					/* Instead of defining a new house, a substitute house id
 
					 * of 0xFF disables the old house with the current id. */
 
					_house_specs[hid + i].enabled = false;
 
					continue;
 
				} else if (subs_id >= NEW_HOUSE_OFFSET) {
 
					/* The substitute id must be one of the original houses. */
 
					grfmsg(2, "TownHouseChangeInfo: Attempt to use new house %u as substitute house for %u. Ignoring.", subs_id, hid + i);
 
					return false;
 
				}
 

	
 
				/* Allocate space for this house. */
 
				if (housespec[i] == NULL) housespec[i] = CallocT<HouseSpec>(1);
 

	
 
				memcpy(housespec[i], &_house_specs[subs_id], sizeof(_house_specs[subs_id]));
 

	
 
				housespec[i]->enabled = true;
 
				housespec[i]->local_id = hid + i;
 
				housespec[i]->substitute_id = subs_id;
 
				housespec[i]->random_colour[0] = 0x04;  // those 4 random colours are the base colour
 
				housespec[i]->random_colour[1] = 0x08;  // for all new houses
 
				housespec[i]->random_colour[2] = 0x0C;  // they stand for red, blue, orange and green
 
				housespec[i]->random_colour[3] = 0x06;
 

	
 
				/* New houses do not (currently) expect to have a default start
 
				 * date before 1930, as this breaks the build date stuff. See
 
				 * FinaliseHouseArray() for more details. */
 
				if (housespec[i]->min_date < 1930) housespec[i]->min_date = 1930;
 
			}
 
			_have_newhouses = true;
 
			break;
 

	
 
		case 0x09: // Building flags
 
			FOR_EACH_OBJECT {
 
				byte state = grf_load_byte(&buf);
 
				housespec[i]->building_flags = (BuildingFlags)state;
 
			}
 
			break;
 

	
 
		case 0x0A: // Availability years
 
			FOR_EACH_OBJECT {
 
				uint16 years = grf_load_word(&buf);
 
				housespec[i]->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
 
				housespec[i]->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
 
			}
 
			break;
 

	
 
		case 0x0B: // Population
 
			FOR_EACH_OBJECT housespec[i]->population = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x0C: // Mail generation multiplier
 
			FOR_EACH_OBJECT housespec[i]->mail_generation = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x0D: // Passenger acceptance
 
			FOR_EACH_OBJECT housespec[i]->passenger_acceptance = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x0E: // Mail acceptance
 
			FOR_EACH_OBJECT housespec[i]->mail_acceptance = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x0F: // Goods, food or fizzy drinks acceptance
 
			FOR_EACH_OBJECT {
 
				int8 goods = grf_load_byte(&buf);
 
				if (goods > 0) {
 
					housespec[i]->goods_acceptance = goods;
 
				} else {
 
					housespec[i]->food_acceptance = -goods;
 
				}
 
			}
 
			break;
 

	
 
		case 0x10: // Local authority rating decrease on removal
 
			FOR_EACH_OBJECT housespec[i]->remove_rating_decrease = grf_load_word(&buf);
 
			break;
 

	
 
		case 0x11: // Removal cost multiplier
 
			FOR_EACH_OBJECT housespec[i]->removal_cost = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x12: // Building name ID
 
			FOR_EACH_OBJECT housespec[i]->building_name = MapGRFStringID(grf_load_word(&buf));
 
			break;
 

	
 
		case 0x13: // Building availability mask
 
			FOR_EACH_OBJECT {
 
				uint16 avail = grf_load_word(&buf);
 
				housespec[i]->building_availability = (HouseZones)avail;
 
			}
 
			break;
 

	
 
		case 0x14: // House callback flags
 
			FOR_EACH_OBJECT housespec[i]->callback_mask = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x15: // House override byte
 
			FOR_EACH_OBJECT {
 
				byte override = grf_load_byte(&buf);
 

	
 
				/* The house being overridden must be an original house. */
 
				if (override >= NEW_HOUSE_OFFSET) {
 
					grfmsg(2, "TownHouseChangeInfo: Attempt to override new house %u with house id %u. Ignoring.", override, hid);
 
					return false;
 
				}
 

	
 
				AddHouseOverride(hid, override);
 
			}
 
			break;
 

	
 
		case 0x16: // Periodic refresh multiplier
 
			FOR_EACH_OBJECT housespec[i]->processing_time = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x17: // Four random colours to use
 
			FOR_EACH_OBJECT {
 
				uint j;
 
				for (j = 0; j < 4; j++)	housespec[i]->random_colour[j] = grf_load_byte(&buf);
 
			}
 
			break;
 

	
 
		case 0x18: // Relative probability of appearing
 
			FOR_EACH_OBJECT housespec[i]->probability = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x19: // Extra flags
 
			FOR_EACH_OBJECT {
 
				byte flags = grf_load_byte(&buf);
 
				housespec[i]->extra_flags = (HouseExtraFlags)flags;
 
			}
 
			break;
 

	
 
		case 0x1A: // Animation frames
 
			FOR_EACH_OBJECT housespec[i]->animation_frames = grf_load_byte(&buf);
 
			break;
 

	
 
		case 0x1B: // Animation speed
 
			FOR_EACH_OBJECT housespec[i]->animation_speed = clamp(grf_load_byte(&buf), 2, 16);
 
			break;
 

	
 
		case 0x1C: // Class of the building type
 
			FOR_EACH_OBJECT housespec[i]->class_id = AllocateHouseClassID(grf_load_byte(&buf), _cur_grffile->grfid);
 
			break;
 

	
 
		case 0x1D: // Callback flags 2
 
			FOR_EACH_OBJECT housespec[i]->callback_mask |= (grf_load_byte(&buf) << 8);
 
			break;
 

	
 
		case 0x1E: // Accepted cargo types
 
			FOR_EACH_OBJECT grf_load_dword(&buf);
 
			ret = true;
 
			break;
 

	
 
		default:
 
			ret = true;
 
			break;
 
	}
 

	
 
	*bufp = buf;
 
	return ret;
 
}
 

	
 
static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, int len)
 
{
 
	byte *buf = *bufp;
 
	int i;
 
	bool ret = false;
 

	
 
@@ -1372,13 +1604,13 @@ static void FeatureChangeInfo(byte *buf,
 
		/* GSF_ROAD */         RoadVehicleChangeInfo,
 
		/* GSF_SHIP */         ShipVehicleChangeInfo,
 
		/* GSF_AIRCRAFT */     AircraftVehicleChangeInfo,
 
		/* GSF_STATION */      StationChangeInfo,
 
		/* GSF_CANAL */        NULL,
 
		/* GSF_BRIDGE */       BridgeChangeInfo,
 
		/* GSF_TOWNHOUSE */    NULL,
 
		/* GSF_TOWNHOUSE */    TownHouseChangeInfo,
 
		/* GSF_GLOBALVAR */    GlobalVarChangeInfo,
 
		/* GSF_INDUSTRYTILES */NULL,
 
		/* GSF_INDUSTRIES */   NULL,
 
		/* GSF_CARGOS */       NULL,
 
		/* GSF_SOUNDFX */      SoundEffectChangeInfo,
 
	};
 
@@ -1850,12 +2082,92 @@ static void NewSpriteGroup(byte *buf, in
 
						grfmsg(8, "NewSpriteGroup: + rg->loading[%i] = subset %u", i, spriteid);
 
					}
 

	
 
					break;
 
				}
 

	
 
				case GSF_TOWNHOUSE: {
 
					byte sprites     = _cur_grffile->spriteset_numents;
 
					byte num_sprites = max((uint8)1, type);
 
					uint i;
 

	
 
					group = AllocateSpriteGroup();
 
					group->type = SGT_TILELAYOUT;
 
					group->g.layout.num_sprites = sprites;
 
					group->g.layout.dts = CallocT<DrawTileSprites>(1);
 

	
 
					/* Groundsprite */
 
					group->g.layout.dts->ground_sprite = grf_load_word(&buf);
 
					group->g.layout.dts->ground_pal    = grf_load_word(&buf);
 
					/* Remap transparent/colour modifier bits */
 
					if (HASBIT(group->g.layout.dts->ground_sprite, 14)) {
 
						CLRBIT(group->g.layout.dts->ground_sprite, 14);
 
						SETBIT(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_TRANSPARENT);
 
					}
 
					if (HASBIT(group->g.layout.dts->ground_sprite, 15)) {
 
						CLRBIT(group->g.layout.dts->ground_sprite, 15);
 
						SETBIT(group->g.layout.dts->ground_sprite, PALETTE_MODIFIER_COLOR);
 
					}
 
					if (HASBIT(group->g.layout.dts->ground_pal, 14)) {
 
						CLRBIT(group->g.layout.dts->ground_pal, 14);
 
						SETBIT(group->g.layout.dts->ground_sprite, SPRITE_MODIFIER_OPAQUE);
 
					}
 
					if (HASBIT(group->g.layout.dts->ground_pal, 15)) {
 
						/* Bit 31 set means this is a custom sprite, so rewrite it to the
 
						 * last spriteset defined. */
 
						SpriteID sprite = _cur_grffile->spriteset_start + GB(group->g.layout.dts->ground_sprite, 0, 14) * sprites;
 
						SB(group->g.layout.dts->ground_sprite, 0, SPRITE_WIDTH, sprite);
 
						CLRBIT(group->g.layout.dts->ground_pal, 15);
 
					}
 

	
 
					group->g.layout.dts->seq = CallocT<DrawTileSeqStruct>(num_sprites + 1);
 

	
 
					for (i = 0; i < num_sprites; i++) {
 
						DrawTileSeqStruct *seq = (DrawTileSeqStruct*)&group->g.layout.dts->seq[i];
 

	
 
						seq->image = grf_load_word(&buf);
 
						seq->pal   = grf_load_word(&buf);
 
						seq->delta_x = grf_load_byte(&buf);
 
						seq->delta_y = grf_load_byte(&buf);
 

	
 
						if (HASBIT(seq->image, 14)) {
 
							CLRBIT(seq->image, 14);
 
							SETBIT(seq->image, PALETTE_MODIFIER_TRANSPARENT);
 
						}
 
						if (HASBIT(seq->image, 15)) {
 
							CLRBIT(seq->image, 15);
 
							SETBIT(seq->image, PALETTE_MODIFIER_COLOR);
 
						}
 
						if (HASBIT(seq->pal, 14)) {
 
							CLRBIT(seq->pal, 14);
 
							SETBIT(seq->image, SPRITE_MODIFIER_OPAQUE);
 
						}
 
						if (HASBIT(seq->pal, 15)) {
 
							/* Bit 31 set means this is a custom sprite, so rewrite it to the
 
							 * last spriteset defined. */
 
							SpriteID sprite = _cur_grffile->spriteset_start + GB(seq->image, 0, 14) * sprites;
 
							SB(seq->image, 0, SPRITE_WIDTH, sprite);
 
							CLRBIT(seq->pal, 15);
 
						}
 

	
 
						if (type > 0) {
 
							seq->delta_z = grf_load_byte(&buf);
 
							if ((byte)seq->delta_z == 0x80) continue;
 
						}
 

	
 
						seq->size_x = grf_load_byte(&buf);
 
						seq->size_y = grf_load_byte(&buf);
 
						seq->size_z = grf_load_byte(&buf);
 
					}
 

	
 
					/* Set the terminator value. */
 
					((DrawTileSeqStruct*)group->g.layout.dts->seq)[i].delta_x = (byte)0x80;
 

	
 
					break;
 
				}
 

	
 
				/* Loading of Tile Layout and Production Callback groups would happen here */
 
				default: grfmsg(1, "NewSpriteGroup: Unsupported feature %d, skipping", feature);
 
			}
 
		}
 
	}
 

	
 
@@ -1931,13 +2243,13 @@ static void FeatureMapSpriteGroup(byte *
 
	uint8 cidcount = buf[3 + idcount];
 
	if (!check_length(len, 4 + idcount + cidcount * 3, "FeatureMapSpriteGroup")) return;
 

	
 
	grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d",
 
			feature, idcount, cidcount, wagover);
 

	
 
	if (feature > GSF_STATION) {
 
	if (feature > GSF_STATION && feature != GSF_TOWNHOUSE) {
 
		grfmsg(1, "FeatureMapSpriteGroup: Unsupported feature %d, skipping", feature);
 
		return;
 
	}
 

	
 

	
 
	if (feature == GSF_STATION) {
 
@@ -1983,12 +2295,35 @@ static void FeatureMapSpriteGroup(byte *
 
				statspec->grfid = _cur_grffile->grfid;
 
				statspec->localidx = stid;
 
				SetCustomStationSpec(statspec);
 
			}
 
		}
 
		return;
 
	} else if (feature == GSF_TOWNHOUSE) {
 
		byte *bp = &buf[4 + idcount + cidcount * 3];
 
		uint16 groupid = grf_load_word(&bp);
 

	
 
		if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
 
			grfmsg(1, "FeatureMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
 
			       groupid, _cur_grffile->spritegroups_count);
 
			return;
 
		}
 

	
 
		for (uint i = 0; i < idcount; i++) {
 
			uint8 hid = buf[3 + i];
 
			HouseSpec *hs = _cur_grffile->housespec[hid];
 

	
 
			if (hs == NULL) {
 
				grfmsg(1, "FeatureMapSpriteGroup: Too many houses defined, skipping");
 
				return;
 
			}
 

	
 
			hs->spritegroup = _cur_grffile->spritegroups[groupid];
 
			hs->grffile = _cur_grffile;
 
		}
 
		return;
 
	}
 

	
 
	// FIXME: Tropicset contains things like:
 
	// 03 00 01 19 01 00 00 00 00 - this is missing one 00 at the end,
 
	// what should we exactly do with that? --pasky
 

	
 
@@ -2145,12 +2480,13 @@ static void FeatureNewName(byte *buf, in
 
					} else {
 
						AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, id);
 
					}
 
					break;
 
				}
 

	
 
				case GSF_TOWNHOUSE:
 
				default:
 
					switch (GB(id, 8, 8)) {
 
						case 0xC4: /* Station class name */
 
							if (_cur_grffile->stations == NULL || _cur_grffile->stations[GB(id, 0, 8)] == NULL) {
 
								grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
 
							} else {
 
@@ -2164,13 +2500,21 @@ static void FeatureNewName(byte *buf, in
 
								grfmsg(1, "FeatureNewName: Attempt to name undefined station 0x%X, ignoring", GB(id, 0, 8));
 
							} else {
 
								_cur_grffile->stations[GB(id, 0, 8)]->name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
 
							}
 
							break;
 

	
 
						case 0xC9:
 
						case 0xC9: { /* House name */
 
							if (_cur_grffile->housespec == NULL || _cur_grffile->housespec[GB(id, 0, 8)] == NULL) {
 
								grfmsg(1, "FeatureNewName: Attempt to name undefined house 0x%X, ignoring.", GB(id, 0, 8));
 
							} else {
 
								_cur_grffile->housespec[GB(id, 0, 8)]->building_name = AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
 
							}
 
							break;
 
						}
 

	
 
						case 0xD0:
 
						case 0xDC:
 
							AddGRFString(_cur_grffile->grfid, id, lang, new_scheme, name, STR_UNDEFINED);
 
							break;
 

	
 
						default:
 
@@ -2179,13 +2523,12 @@ static void FeatureNewName(byte *buf, in
 
					}
 
					break;
 

	
 
#if 0
 
				case GSF_CANAL :
 
				case GSF_BRIDGE :
 
				case GSF_TOWNHOUSE :
 
					AddGRFString(_cur_spriteid, id, lang, name);
 
					switch (GB(id, 8,8)) {
 
						case 0xC9: /* House name */
 
						default:
 
							grfmsg(7, "FeatureNewName: Unsupported ID (0x%04X)", id);
 
					}
 
@@ -3475,13 +3818,13 @@ static void InitializeGRFSpecial()
 
	                   |                                        (0 << 0x13)  // tracktypecostdiff
 
	                   |                                        (0 << 0x14)  // manualconvert
 
	                   |       ((_patches.build_on_slopes ? 1 : 0) << 0x15)  // buildoncoasts
 
	                   |                                        (1 << 0x16)  // canals
 
	                   |                                        (1 << 0x17)  // newstartyear
 
	                   |                                        (0 << 0x18)  // freighttrains
 
	                   |                                        (0 << 0x19)  // newhouses
 
	                   |                                        (1 << 0x19)  // newhouses
 
	                   |                                        (1 << 0x1A)  // newbridges
 
	                   |                                        (0 << 0x1B)  // newtownnames
 
	                   |                                        (0 << 0x1C)  // moreanimations
 
	                   |    ((_patches.wagon_speed_limits ? 1 : 0) << 0x1D)  // wagonspeedlimits
 
	                   |                                        (1 << 0x1E)  // newshistory
 
	                   |                                        (0 << 0x1F); // custombridgeheads
 
@@ -3547,12 +3890,26 @@ static void ResetCustomStations()
 
		/* Free and reset the station data */
 
		free(file->stations);
 
		file->stations = NULL;
 
	}
 
}
 

	
 
static void ResetCustomHouses()
 
{
 
	GRFFile *file;
 
	uint i;
 

	
 
	for (file = _first_grffile; file != NULL; file = file->next) {
 
		if (file->housespec == NULL) continue;
 
		for (i = 0; i < HOUSE_MAX; i++) free(file->housespec[i]);
 

	
 
		free(file->housespec);
 
		file->housespec = NULL;
 
	}
 
}
 

	
 
static void ResetNewGRF()
 
{
 
	GRFFile *next;
 

	
 
	for (GRFFile *f = _first_grffile; f != NULL; f = next) {
 
		next = f->next;
 
@@ -3607,12 +3964,16 @@ static void ResetNewGRFData()
 
	// Reset price base data
 
	ResetPriceBaseMultipliers();
 

	
 
	/* Reset the curencies array */
 
	ResetCurrencies();
 

	
 
	/* Reset the house array */
 
	ResetCustomHouses();
 
	ResetHouses();
 

	
 
	// Reset station classes
 
	ResetStationClasses();
 
	ResetCustomStations();
 

	
 
	/* Reset NewGRF files */
 
	ResetNewGRF();
 
@@ -3632,12 +3993,13 @@ static void ResetNewGRFData()
 

	
 
	/* Reset misc GRF features and train list display variables */
 
	_misc_grf_features = 0;
 
	_traininfo_vehicle_pitch = 0;
 
	_traininfo_vehicle_width = 29;
 
	_have_2cc = false;
 
	_have_newhouses = false;
 
	_signal_base = 0;
 
	_coast_base = 0;
 

	
 
	InitializeSoundPool();
 
	InitializeSpriteGroupPool();
 
}
 
@@ -3835,12 +4197,47 @@ static void CalculateRefitMasks()
 
				break;
 
			}
 
		}
 
	}
 
}
 

	
 
/** Add all new houses to the house array. House properties can be set at any
 
 * time in the GRF file, so we can only add a house spec to the house array
 
 * after the file has finished loading. We also need to check the dates, due to
 
 * the TTDPatch behaviour described below that we need to emulate. */
 
static void FinaliseHouseArray()
 
{
 
	/* If there are no houses with start dates before 1930, then all houses
 
	 * with start dates of 1930 have them reset to 0. This is in order to be
 
	 * compatible with TTDPatch, where if no houses have start dates before
 
	 * 1930 and the date is before 1930, the game pretends that this is 1930.
 
	 * If there have been any houses defined with start dates before 1930 then
 
	 * the dates are left alone. */
 
	bool reset_dates = true;
 

	
 
	for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
 
		if (file->housespec == NULL) continue;
 

	
 
		for (int i = 0; i < HOUSE_MAX; i++) {
 
			HouseSpec *hs = file->housespec[i];
 
			if (hs != NULL) {
 
				SetHouseSpec(hs);
 
				if (hs->min_date < 1930) reset_dates = false;
 
			}
 
		}
 
	}
 

	
 
	if (reset_dates) {
 
		for (int i = NEW_HOUSE_OFFSET; i < HOUSE_MAX; i++) {
 
			HouseSpec *hs = GetHouseSpecs(i);
 

	
 
			if (hs->enabled && hs->min_date == 1930) hs->min_date = 0;
 
		}
 
	}
 
}
 

	
 
/* Here we perform initial decoding of some special sprites (as are they
 
 * described at http://www.ttdpatch.net/src/newgrf.txt, but this is only a very
 
 * partial implementation yet). */
 
/* XXX: We consider GRF files trusted. It would be trivial to exploit OTTD by
 
 * a crafted invalid GRF file. We should tell that to the user somehow, or
 
 * better make this more robust in the future. */
 
@@ -4000,12 +4397,24 @@ void LoadNewGRFFile(GRFConfig *config, u
 
		if (_skip_sprites > 0) _skip_sprites--;
 
	}
 
}
 

	
 
void InitDepotWindowBlockSizes();
 

	
 
static void AfterLoadGRFs()
 
{
 
	/* Pre-calculate all refit masks after loading GRF files. */
 
	CalculateRefitMasks();
 

	
 
	/* Set the block size in the depot windows based on vehicle sprite sizes */
 
	InitDepotWindowBlockSizes();
 

	
 
	/* Add all new houses to the house array. */
 
	FinaliseHouseArray();
 
}
 

	
 
void LoadNewGRF(uint load_index, uint file_index)
 
{
 
	InitializeGRFSpecial();
 

	
 
	ResetNewGRFData();
 

	
 
@@ -4030,12 +4439,9 @@ void LoadNewGRF(uint load_index, uint fi
 
				BuildCargoTranslationMap();
 
				DEBUG(sprite, 2, "Currently %i sprites are loaded", _cur_spriteid);
 
			}
 
		}
 
	}
 

	
 
	// Pre-calculate all refit masks after loading GRF files
 
	CalculateRefitMasks();
 

	
 
	/* Set the block size in the depot windows based on vehicle sprite sizes */
 
	InitDepotWindowBlockSizes();
 
	/* Call any functions that should be run after GRFs have been loaded. */
 
	AfterLoadGRFs();
 
}
src/newgrf.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef NEWGRF_H
 
#define NEWGRF_H
 

	
 
#include "station.h"
 
#include "town.h"
 
#include "newgrf_config.h"
 
#include "helpers.hpp"
 
#include "cargotype.h"
 

	
 
enum GrfLoadingStage {
 
	GLS_FILESCAN,
 
@@ -53,12 +54,13 @@ struct GRFFile {
 
	int spritegroups_count;
 
	struct SpriteGroup **spritegroups;
 

	
 
	uint sound_offset;
 

	
 
	StationSpec **stations;
 
	HouseSpec **housespec;
 

	
 
	uint32 param[0x80];
 
	uint param_end; /// one more than the highest set parameter
 

	
 
	GRFLabel *label; ///< Pointer to the first label. This is a linked list, not an array.
 

	
 
@@ -69,12 +71,13 @@ struct GRFFile {
 

	
 
extern GRFFile *_first_grffile;
 

	
 
extern SpriteID _signal_base;
 
extern SpriteID _coast_base;
 
extern bool _have_2cc;
 
extern bool _have_newhouses;
 

	
 
void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage);
 
void LoadNewGRF(uint load_index, uint file_index);
 
void ReloadNewGRFData(); // in openttd.c
 

	
 
void CDECL grfmsg(int severity, const char *str, ...);
src/newgrf_callbacks.h
Show inline comments
 
@@ -34,33 +34,77 @@ enum CallbackID {
 
	/* Refit capacity, the passed vehicle needs to have its ->cargo_type set to
 
	 * the cargo we are refitting to, returns the new cargo capacity */
 
	CBID_VEHICLE_REFIT_CAPACITY     = 0x15,
 

	
 
	CBID_TRAIN_ARTIC_ENGINE         = 0x16,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to determine whether
 
	 * the house can be built on the specified tile. */
 
	CBID_HOUSE_ALLOW_CONSTRUCTION   = 0x17,
 

	
 
	CBID_VEHICLE_CARGO_SUFFIX       = 0x19,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to determine
 
	 * the next animation frame. */
 
	CBID_HOUSE_ANIMATION_NEXT_FRAME = 0x1A,
 

	
 
	/* Called (if appropriate bit in callback mask is set) for periodically
 
	 * starting or stopping the animation. */
 
	CBID_HOUSE_ANIMATION_START_STOP = 0x1B,
 

	
 
	/* Called (if appropriate bit in callback mask is set) whenever the
 
	 * construction state of a house changes. */
 
	CBID_CONSTRUCTION_STATE_CHANGE  = 0x1C,
 

	
 
	CBID_TRAIN_ALLOW_WAGON_ATTACH   = 0x1D,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to determine the
 
	 * colour of a town building. */
 
	CBID_BUILDING_COLOUR            = 0x1E,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to decide how much
 
	 * cargo a town building can accept. */
 
	CBID_HOUSE_CARGO_ACCEPTANCE     = 0x1F, // not yet implemented
 

	
 
	/* Called (if appropriate bit in callback mask is set) to indicate
 
	 * how long the current animation frame should last. */
 
	CBID_HOUSE_ANIMATION_SPEED      = 0x20,
 

	
 
	/* Called (if appropriate bit in callback mask is set) periodically to
 
	 * determine if a house should be destroyed. */
 
	CBID_HOUSE_DESTRUCTION          = 0x21,
 

	
 
	/* This callback is called from vehicle purchase lists. It returns a value to be
 
	 * used as a custom string ID in the 0xD000 range. */
 
	CBID_VEHICLE_ADDITIONAL_TEXT    = 0x23,
 

	
 
	/* Called when building a station to customize the tile layout */
 
	CBID_STATION_TILE_LAYOUT        = 0x24,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to determine which
 
	 * cargoes a town building should accept. */
 
	CBID_HOUSE_ACCEPT_CARGO         = 0x2A, // not yet implemented
 

	
 
	/* Called to determine if a specific colour map should be used for a vehicle
 
	 * instead of the default livery */
 
	CBID_VEHICLE_COLOUR_MAPPING     = 0x2D,
 

	
 
	/* Called (if appropriate bit in callback mask is set) to determine how much
 
	 * cargo a town building produces. */
 
	CBID_HOUSE_PRODUCE_CARGO        = 0x2E, // not yet implemented
 

	
 
	/* Called when the player (or AI) tries to start or stop a vehicle. Mainly
 
	 * used for preventing a vehicle from leaving the depot. */
 
	CBID_VEHICLE_START_STOP_CHECK   = 0x31,
 

	
 
	/* Called to play a special sound effect */
 
	CBID_VEHICLE_SOUND_EFFECT       = 0x33,
 

	
 
	/* Called (if appropriate bit in callback mask set) to determine whether a
 
	 * town building can be destroyed. */
 
	CBID_HOUSE_DENY_DESTRUCTION     = 0x143,
 
};
 

	
 
/**
 
 * Callback masks for vehicles, indicates which callbacks are used by a vehicle.
 
 * Some callbacks are always used and don't have a mask.
 
 */
 
@@ -81,12 +125,29 @@ enum VehicleCallbackMask {
 
enum StationCallbackMask {
 
	CBM_STATION_AVAIL = 0, ///< Availability of station in construction window
 
	CBM_CUSTOM_LAYOUT = 1, ///< Use callback to select a tile layout to use
 
};
 

	
 
/**
 
 * Callback masks for houses.
 
 */
 
enum HouseCallbackMask {
 
	CBM_HOUSE_ALLOW_CONSTRUCTION  = 0,
 
	CBM_ANIMATION_NEXT_FRAME      = 1,
 
	CBM_ANIMATION_START_STOP      = 2,
 
	CBM_CONSTRUCTION_STATE_CHANGE = 3,
 
	CBM_BUILDING_COLOUR           = 4,
 
	CBM_CARGO_ACCEPTANCE          = 5,
 
	CBM_ANIMATION_SPEED           = 6,
 
	CBM_HOUSE_DESTRUCTION         = 7,
 
	CBM_HOUSE_ACCEPT_CARGO        = 8,
 
	CBM_HOUSE_PRODUCE_CARGO       = 9,
 
	CBM_HOUSE_DENY_DESTRUCTION    = 10,
 
};
 

	
 
/**
 
 * Result of a failed callback.
 
 */
 
enum {
 
	CALLBACK_FAILED = 0xFFFF
 
};
 

	
src/newgrf_house.cpp
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/** @file newgrf_house.cpp */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "functions.h"
 
#include "variables.h"
 
#include "debug.h"
 
#include "viewport.h"
 
#include "date.h"
 
#include "town.h"
 
#include "town_map.h"
 
#include "sound.h"
 
#include "sprite.h"
 
#include "strings.h"
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
#include "table/town_land.h"
 
#include "newgrf.h"
 
#include "newgrf_house.h"
 
#include "newgrf_spritegroup.h"
 
#include "newgrf_callbacks.h"
 
#include "newgrf_town.h"
 
#include "newgrf_sound.h"
 

	
 
static BuildingCounts    _building_counts;
 
static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
 
HouseIDMapping _house_id_mapping[HOUSE_MAX];
 

	
 
/* Since the house IDs defined by the GRF file don't necessarily correlate
 
 * to those used by the game, the IDs used for overriding old houses must be
 
 * translated when the house spec is set. */
 
static uint16 _house_overrides[NEW_HOUSE_OFFSET];
 

	
 
void AddHouseOverride(uint8 local_id, uint house_type)
 
{
 
	assert(house_type < NEW_HOUSE_OFFSET);
 
	_house_overrides[house_type] = local_id;
 
}
 

	
 
void ResetHouseOverrides()
 
{
 
	for (int i = 0; i != lengthof(_house_overrides); i++) {
 
		_house_overrides[i] = INVALID_HOUSE_ID;
 
	}
 
}
 

	
 
static HouseID GetHouseID(byte grf_local_id, uint32 grfid)
 
{
 
	const HouseIDMapping *map;
 

	
 
	for (HouseID house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
 
		map = &_house_id_mapping[house_id];
 
		if (map->house_id == grf_local_id && map->grfid == grfid) return house_id;
 
	}
 
	return INVALID_HOUSE_ID;
 
}
 

	
 
static HouseID AddHouseID(byte grf_local_id, uint32 grfid, byte substitute_id)
 
{
 
	HouseID house_id;
 
	HouseIDMapping *map;
 

	
 
	/* Look to see if this house has already been added. This is done
 
	 * separately from the loop below in case a GRF has been deleted, and there
 
	 * are any gaps in the array. */
 
	house_id = GetHouseID(grf_local_id, grfid);
 
	if (house_id != INVALID_HOUSE_ID) return house_id;
 

	
 
	/* This house hasn't been defined before, so give it an ID now. */
 
	for (house_id = NEW_HOUSE_OFFSET; house_id != lengthof(_house_id_mapping); house_id++) {
 
		map = &_house_id_mapping[house_id];
 

	
 
		if (map->house_id == 0 && map->grfid == 0) {
 
			map->house_id      = grf_local_id;
 
			map->grfid         = grfid;
 
			map->substitute_id = substitute_id;
 
			return house_id;
 
		}
 
	}
 

	
 
	return INVALID_HOUSE_ID;
 
}
 

	
 
void SetHouseSpec(const HouseSpec *hs)
 
{
 
	HouseID house_id = AddHouseID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
 

	
 
	if (house_id == INVALID_HOUSE_ID) {
 
		grfmsg(1, "SetHouseSpec: Too many houses allocated. Ignoring.");
 
		return;
 
	}
 

	
 
	memcpy(&_house_specs[house_id], hs, sizeof(*hs));
 

	
 
	/* Now add the overrides. */
 
	for (int i = 0; i != lengthof(_house_overrides); i++) {
 
		HouseSpec *overridden_hs = GetHouseSpecs(i);
 

	
 
		if (_house_overrides[i] != hs->local_id) continue;
 

	
 
		overridden_hs->override = house_id;
 
		_house_overrides[i] = INVALID_HOUSE_ID;
 
	}
 
}
 

	
 
void ResetHouseIDMapping()
 
{
 
	memset(&_house_id_mapping, 0, sizeof(_house_id_mapping));
 
}
 

	
 
void CheckHouseIDs()
 
{
 
	for (TileIndex t = 0; t < MapSize(); t++) {
 
		HouseID house_id;
 

	
 
		if (!IsTileType(t, MP_HOUSE)) continue;
 

	
 
		house_id = GetHouseType(t);
 
		if (!GetHouseSpecs(house_id)->enabled && house_id >= NEW_HOUSE_OFFSET) {
 
			/* The specs for this type of house are not available any more, so
 
			 * replace it with the substitute original house type. */
 
			SetHouseType(t, _house_id_mapping[house_id].substitute_id);
 
		}
 
	}
 

	
 
	InitializeBuildingCounts();
 
	AfterLoadCountBuildings();
 

	
 
}
 

	
 
HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid)
 
{
 
	/* Start from 1 because 0 means that no class has been assigned. */
 
	for (int i = 1; i != lengthof(_class_mapping); i++) {
 
		HouseClassMapping *map = &_class_mapping[i];
 

	
 
		if (map->class_id == grf_class_id && map->grfid == grfid) return (HouseClassID)i;
 

	
 
		if (map->class_id == 0 && map->grfid == 0) {
 
			map->class_id = grf_class_id;
 
			map->grfid    = grfid;
 
			return (HouseClassID)i;
 
		}
 
	}
 
	return HOUSE_NO_CLASS;
 
}
 

	
 
void InitializeBuildingCounts()
 
{
 
	memset(&_building_counts, 0, sizeof(_building_counts));
 
}
 

	
 
/**
 
 * IncreaseBuildingCount()
 
 * Increase the count of a building when it has been added by a town.
 
 * @param t The town that the building is being built in
 
 * @param house_id The id of the house being added
 
 */
 
void IncreaseBuildingCount(Town *t, HouseID house_id)
 
{
 
	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
 

	
 
	if (!_have_newhouses) return;
 

	
 
	/* If there are 255 buildings of this type in this town, there are also
 
	 * at least that many houses of the same class in the town, and
 
	 * therefore on the map as well. */
 
	if (t->building_counts.id_count[house_id] == 255) return;
 

	
 
	t->building_counts.id_count[house_id]++;
 
	if (_building_counts.id_count[house_id] < 255) _building_counts.id_count[house_id]++;
 

	
 
	/* Similarly, if there are 255 houses of this class in this town, there
 
	 * must be at least that number on the map too. */
 
	if (class_id == HOUSE_NO_CLASS || t->building_counts.class_count[class_id] == 255) return;
 

	
 
	t->building_counts.class_count[class_id]++;
 
	if (_building_counts.class_count[class_id] < 255) _building_counts.class_count[class_id]++;
 
}
 

	
 
/**
 
 * DecreaseBuildingCount()
 
 * Decrease the number of a building when it is deleted.
 
 * @param t The town that the building was built in
 
 * @param house_id The id of the house being removed
 
 */
 
void DecreaseBuildingCount(Town *t, HouseID house_id)
 
{
 
	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
 

	
 
	if (!_have_newhouses) return;
 

	
 
	if (t->building_counts.id_count[house_id] > 0) t->building_counts.id_count[house_id]--;
 
	if (_building_counts.id_count[house_id] > 0)   _building_counts.id_count[house_id]--;
 

	
 
	if (class_id == HOUSE_NO_CLASS) return;
 

	
 
	if (t->building_counts.class_count[class_id] > 0) t->building_counts.class_count[class_id]--;
 
	if (_building_counts.class_count[class_id] > 0)   _building_counts.class_count[class_id]--;
 
}
 

	
 
/**
 
 * AfterLoadCountBuildings()
 
 *
 
 * After a savegame has been loaded, count the number of buildings on the map.
 
 */
 
void AfterLoadCountBuildings()
 
{
 
	if (!_have_newhouses) return;
 

	
 
	for (TileIndex t = 0; t < MapSize(); t++) {
 
		if (!IsTileType(t, MP_HOUSE)) continue;
 
		IncreaseBuildingCount(GetTownByTile(t), GetHouseType(t));
 
	}
 
}
 

	
 

	
 
static uint32 HouseGetRandomBits(const ResolverObject *object)
 
{
 
	const TileIndex tile = object->u.house.tile;
 
	return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseRandomBits(tile);
 
}
 

	
 
static uint32 HouseGetTriggers(const ResolverObject *object)
 
{
 
	const TileIndex tile = object->u.house.tile;
 
	return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseTriggers(tile);
 
}
 

	
 
static void HouseSetTriggers(const ResolverObject *object, int triggers)
 
{
 
	const TileIndex tile = object->u.house.tile;
 
	if (IsTileType(tile, MP_HOUSE)) SetHouseTriggers(tile, triggers);
 
}
 

	
 
static uint32 GetNumHouses(HouseID house_id, const Town *town)
 
{
 
	uint8 map_id_count, town_id_count, map_class_count, town_class_count;
 
	HouseClassID class_id = GetHouseSpecs(house_id)->class_id;
 

	
 
	map_id_count     = _building_counts.id_count[house_id];
 
	map_class_count  = _building_counts.class_count[class_id];
 
	town_id_count    = town->building_counts.id_count[house_id];
 
	town_class_count = town->building_counts.class_count[class_id];
 

	
 
	return map_class_count << 24 | town_class_count << 16 | map_id_count << 8 | town_id_count;
 
}
 

	
 
static uint32 GetTerrainType(TileIndex tile)
 
{
 
	switch (_opt.landscape) {
 
		case LT_DESERT: return GetTropicZone(tile) == TROPICZONE_DESERT ? 1 : 2;
 
		case LT_HILLY:  return GetTileZ(tile) >= _opt.snow_line ? 4 : 0;
 
		default:        return 0;
 
	}
 
}
 

	
 
static uint32 GetGRFParameter(HouseID house_id, byte parameter)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(house_id);
 
	const GRFFile *file = hs->grffile;
 

	
 
	if (parameter >= file->param_end) return 0;
 
	return file->param[parameter];
 
}
 

	
 
/**
 
 * HouseGetVariable():
 
 *
 
 * Used by the resolver to get values for feature 07 deterministic spritegroups.
 
 */
 
static uint32 HouseGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available)
 
{
 
	const Town *town = object->u.house.town;
 
	TileIndex tile   = object->u.house.tile;
 
	HouseID house_id = object->u.house.house_id;
 

	
 
	if (object->scope == VSG_SCOPE_PARENT) {
 
		return TownGetVariable(variable, parameter, available, town);
 
	}
 

	
 
	switch (variable) {
 
		/* Construction stage. */
 
		case 0x40: return (IsTileType(tile, MP_HOUSE) ? GetHouseBuildingStage(tile) : 0) | OriginalTileRandomiser(TileX(tile), TileY(tile)) << 2;
 

	
 
		/* Building age. */
 
		case 0x41: return clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
 

	
 
		/* Town zone */
 
		case 0x42: return GetTownRadiusGroup(town, tile);
 

	
 
		/* Terrain type */
 
		case 0x43: return GetTerrainType(tile);
 

	
 
		/* Number of this type of building on the map. */
 
		case 0x44: return GetNumHouses(house_id, town);
 

	
 
		/* Whether the town is being created or just expanded. */
 
		case 0x45: return _generating_world ? 1 : 0;
 

	
 
		/* Current animation frame. */
 
		case 0x46: return IsTileType(tile, MP_HOUSE) ? GetHouseAnimationFrame(tile) : 0;
 

	
 

	
 
		/* Building counts for old houses with id = parameter. */
 
		case 0x60: return GetNumHouses(parameter, town);
 

	
 
		/* Building counts for new houses with id = parameter. */
 
		case 0x61: {
 
			const HouseSpec *hs = GetHouseSpecs(house_id);
 
			if (hs->grffile == NULL) return 0;
 

	
 
			HouseID new_house = GetHouseID(parameter, hs->grffile->grfid);
 
			return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, town);
 
		}
 

	
 
		/* Land info for nearby tiles. */
 
		case 0x62: {
 
			int8 x = GB(parameter, 0, 4);
 
			int8 y = GB(parameter, 4, 4);
 
			byte tile_type;
 

	
 
			if (x >= 8) x -= 16;
 
			if (y >= 8) y -= 16;
 

	
 
			tile += TileDiffXY(x, y);
 

	
 
			tile_type = GetTerrainType(tile) << 2 | (IsTileType(tile, MP_WATER) ? 1 : 0) << 1;
 

	
 
			return GetTileType(tile) << 24 | (TileHeight(tile) * 8) << 16 | tile_type << 8 | GetTileSlope(tile, NULL);
 
		}
 

	
 
		/* Read GRF parameter */
 
		case 0x7F: return GetGRFParameter(object->u.house.house_id, parameter);
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled house property 0x%X", variable);
 

	
 
	*available = false;
 
	return UINT_MAX;
 
}
 

	
 
static const SpriteGroup *HouseResolveReal(const ResolverObject *object, const SpriteGroup *group)
 
{
 
	/* Houses do not have 'real' groups */
 
	return NULL;
 
}
 

	
 
/**
 
 * NewHouseResolver():
 
 *
 
 * Returns a resolver object to be used with feature 07 spritegroups.
 
 */
 
static void NewHouseResolver(ResolverObject *res, HouseID house_id, TileIndex tile, Town *town)
 
{
 
	res->GetRandomBits = HouseGetRandomBits;
 
	res->GetTriggers   = HouseGetTriggers;
 
	res->SetTriggers   = HouseSetTriggers;
 
	res->GetVariable   = HouseGetVariable;
 
	res->ResolveReal   = HouseResolveReal;
 

	
 
	res->u.house.tile     = tile;
 
	res->u.house.town     = town;
 
	res->u.house.house_id = house_id;
 

	
 
	res->callback        = 0;
 
	res->callback_param1 = 0;
 
	res->callback_param2 = 0;
 
	res->last_value      = 0;
 
	res->trigger         = 0;
 
	res->reseed          = 0;
 
}
 

	
 
uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile)
 
{
 
	ResolverObject object;
 
	const SpriteGroup *group;
 

	
 
	NewHouseResolver(&object, house_id, tile, town);
 
	object.callback = callback;
 
	object.callback_param1 = param1;
 
	object.callback_param2 = 0;
 

	
 
	group = Resolve(GetHouseSpecs(house_id)->spritegroup, &object);
 
	if (group == NULL || group->type != SGT_CALLBACK) return CALLBACK_FAILED;
 

	
 
	return group->g.callback.result;
 
}
 

	
 
void DrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte stage, HouseID house_id)
 
{
 
	const DrawTileSprites *dts = group->g.layout.dts;
 
	const DrawTileSeqStruct *dtss;
 

	
 
	SpriteID image = dts->ground_sprite;
 
	SpriteID pal   = dts->ground_pal;
 

	
 
	if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal);
 

	
 
	foreach_draw_tile_seq(dtss, dts->seq) {
 
		if (GB(dtss->image, 0, SPRITE_WIDTH) == 0) continue;
 

	
 
		image = dtss->image + stage;
 
		pal   = dtss->pal;
 

	
 
		if (!HASBIT(image, SPRITE_MODIFIER_OPAQUE) && ((_display_opt & DO_TRANS_BUILDINGS))) {
 
			SETBIT(image, PALETTE_MODIFIER_TRANSPARENT);
 
			pal = PALETTE_TO_TRANSPARENT;
 
		} else if (HASBIT(image, PALETTE_MODIFIER_COLOR)) {
 
			if (pal == 0) {
 
				const HouseSpec *hs = GetHouseSpecs(house_id);
 
				if (HASBIT(hs->callback_mask, CBM_BUILDING_COLOUR)) {
 
					uint16 callback = GetHouseCallback(CBID_BUILDING_COLOUR, 0, house_id, GetTownByTile(ti->tile), ti->tile);
 
					if (callback != CALLBACK_FAILED) {
 
						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
 
						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
 
					}
 
				} else {
 
					pal = hs->random_colour[OriginalTileRandomiser(ti->x, ti->y)] + PALETTE_RECOLOR_START;
 
				}
 
			}
 
		} else {
 
			pal = PAL_NONE;
 
		}
 

	
 
		if ((byte)dtss->delta_z != 0x80) {
 
			AddSortableSpriteToDraw(
 
				image, pal,
 
				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
 
				dtss->size_x, dtss->size_y,
 
				dtss->size_z, ti->z + dtss->delta_z
 
			);
 
		} else {
 
			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y);
 
		}
 
	}
 
}
 

	
 
void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(house_id);
 
	const SpriteGroup *group;
 
	ResolverObject object;
 

	
 
	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
 

	
 
	NewHouseResolver(&object, house_id, ti->tile, GetTownByTile(ti->tile));
 

	
 
	group = Resolve(hs->spritegroup, &object);
 
	if (group == NULL || group->type != SGT_TILELAYOUT) {
 
		/* XXX: This is for debugging purposes really, and shouldn't stay. */
 
		DrawGroundSprite(SPR_SHADOW_CELL, PAL_NONE);
 
	} else {
 
		/* Limit the building stage to the number of stages supplied. */
 
		byte stage = GetHouseBuildingStage(ti->tile);
 
		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 
		DrawTileLayout(ti, group, stage, house_id);
 
	}
 
}
 

	
 
void AnimateNewHouseTile(TileIndex tile)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
	byte animation_speed = hs->animation_speed;
 
	bool frame_set_by_callback = false;
 

	
 
	if (HASBIT(hs->callback_mask, CBM_ANIMATION_SPEED)) {
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
 
	}
 

	
 
	/* An animation speed of 2 means the animation frame changes 4 ticks, and
 
	 * increasing this value by one doubles the wait. 2 is the minimum value
 
	 * allowed for animation_speed, which corresponds to 120ms, and 16 is the
 
	 * maximum, corresponding to around 33 minutes. */
 
	if (_tick_counter % (1 << animation_speed) != 0) return;
 

	
 
	byte frame      = GetHouseAnimationFrame(tile);
 
	byte num_frames = GB(hs->animation_frames, 0, 7);
 

	
 
	if (HASBIT(hs->callback_mask, CBM_ANIMATION_NEXT_FRAME)) {
 
		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, GetHouseType(tile), GetTownByTile(tile), tile);
 

	
 
		if (callback_res != CALLBACK_FAILED) {
 
			frame_set_by_callback = true;
 

	
 
			switch (callback_res & 0xFF) {
 
				case 0xFF:
 
					DeleteAnimatedTile(tile);
 
					break;
 
				case 0xFE:
 
					/* Carry on as normal. */
 
					frame_set_by_callback = false;
 
					break;
 
				default:
 
					frame = callback_res & 0xFF;
 
					break;
 
			}
 

	
 
			/* If the lower 7 bits of the upper byte of the callback
 
			 * result are not empty, it is a sound effect. */
 
			if (GB(callback_res, 8, 7) != 0) PlayHouseSound(GB(callback_res, 8, 7), tile);
 
		}
 
	}
 

	
 
	if (!frame_set_by_callback) {
 
		if (frame < num_frames) {
 
			frame++;
 
		} else if (frame == num_frames && HASBIT(hs->animation_frames, 7)) {
 
			/* This animation loops, so start again from the beginning */
 
			frame = 0;
 
		} else {
 
			/* This animation doesn't loop, so stay here */
 
			DeleteAnimatedTile(tile);
 
		}
 
	}
 

	
 
	SetHouseAnimationFrame(tile, frame);
 
	MarkTileDirtyByTile(tile);
 
}
 

	
 
void ChangeHouseAnimationFrame(TileIndex tile, uint16 callback_result)
 
{
 
	switch (callback_result & 0xFF) {
 
		case 0xFD: /* Do nothing. */         break;
 
		case 0xFE: AddAnimatedTile(tile);    break;
 
		case 0xFF: DeleteAnimatedTile(tile); break;
 
		default:
 
			SetHouseAnimationFrame(tile, callback_result & 0xFF);
 
			AddAnimatedTile(tile);
 
			break;
 
	}
 
	/* If the lower 7 bits of the upper byte of the callback
 
	 * result are not empty, it is a sound effect. */
 
	if (GB(callback_result, 8, 7) != 0) PlayHouseSound(GB(callback_result, 8, 7), tile);
 
}
 

	
 
bool CanDeleteHouse(TileIndex tile)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	/* Human players are always allowed to remove buildings, as is water and
 
	 * anyone using the scenario editor. */
 
	if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player))
 
			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
 

	
 
	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
		return (callback_res == CALLBACK_FAILED || callback_res == 0);
 
	} else {
 
		return !(hs->extra_flags & BUILDING_IS_PROTECTED);
 
	}
 
}
 

	
 
static void AnimationControl(TileIndex tile, uint16 random_bits)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
 
		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, GetHouseType(tile), GetTownByTile(tile), tile);
 

	
 
		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
 
	}
 
}
 

	
 
bool NewHouseTileLoop(TileIndex tile)
 
{
 
	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	if (GetHouseProcessingTime(tile) > 0) {
 
		DecHouseProcessingTime(tile);
 
		return true;
 
	}
 

	
 
	/* @todo: Magic with triggers goes here.  Got to implement that, one day. .. */
 

	
 
	if (HASBIT(hs->callback_mask, CBM_ANIMATION_START_STOP)) {
 
		/* If this house is marked as having a synchronised callback, all the
 
		 * tiles will have the callback called at once, rather than when the
 
		 * tile loop reaches them. This should only be enabled for the northern
 
		 * tile, or strange things will happen (here, and in TTDPatch). */
 
		if (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) {
 
			uint16 random = GB(Random(), 0, 16);
 

	
 
			if (hs->building_flags & BUILDING_HAS_1_TILE)  AnimationControl(tile, random);
 
			if (hs->building_flags & BUILDING_2_TILES_Y)   AnimationControl(TILE_ADDXY(tile, 0, 1), random);
 
			if (hs->building_flags & BUILDING_2_TILES_X)   AnimationControl(TILE_ADDXY(tile, 1, 0), random);
 
			if (hs->building_flags & BUILDING_HAS_4_TILES) AnimationControl(TILE_ADDXY(tile, 1, 1), random);
 
		} else {
 
			AnimationControl(tile, 0);
 
		}
 
	}
 

	
 
	/* Check callback 21, which determines if a house should be destroyed. */
 
	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
 
		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
 
			ClearTownHouse(GetTownByTile(tile), tile);
 
			return false;
 
		}
 
	}
 

	
 
	SetHouseProcessingTime(tile, hs->processing_time);
 
	return true;
 
}
src/newgrf_house.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/** @file newgrf_house.h */
 

	
 
#ifndef NEWGRF_HOUSE_H
 
#define NEWGRF_HOUSE_H
 

	
 
#include "town.h"
 

	
 
/**
 
 * Maps a house id stored on the map to a GRF file.
 
 * House IDs are stored on the map, so there needs to be a way to tie them to
 
 * GRF files. An array of HouseIDMapping structs is saved with the savegame so
 
 * that house GRFs can be loaded in a different order, or removed safely. The
 
 * index in the array is the house ID stored on the map.
 
 *
 
 * The substitute ID is the ID of an original house that should be used instead
 
 * if the GRF containing the new house is not available.
 
 */
 
struct HouseIDMapping {
 
	uint32 grfid;          ///< The GRF ID of the file this house belongs to
 
	uint8  house_id;       ///< The house ID within the GRF file
 
	uint8  substitute_id;  ///< The (original) house ID to use if this GRF is not available
 
};
 

	
 
/**
 
 * Makes class IDs unique to each GRF file.
 
 * Houses can be assigned class IDs which are only comparable within the GRF
 
 * file they were defined in. This mapping ensures that if two houses have the
 
 * same class as defined by the GRF file, the classes are different within the
 
 * game. An array of HouseClassMapping structs is created, and the array index
 
 * of the struct that matches both the GRF ID and the class ID is the class ID
 
 * used in the game.
 
 *
 
 * Although similar to the HouseIDMapping struct above, this serves a different
 
 * purpose. Since the class ID is not saved anywhere, this mapping does not
 
 * need to be persistent; it just needs to keep class ids unique.
 
 */
 
struct HouseClassMapping {
 
	uint32 grfid;     ////< The GRF ID of the file this class belongs to
 
	uint8  class_id;  ////< The class id within the grf file
 
};
 

	
 
extern HouseIDMapping _house_id_mapping[HOUSE_MAX]; ///< Declared in newgrf_house.cpp
 

	
 
void AddHouseOverride(uint8 local_id, uint house_type);
 
void ResetHouseOverrides();
 

	
 
void SetHouseSpec(const HouseSpec *hs);
 

	
 
void CheckHouseIDs();
 
void ResetHouseIDMapping();
 

	
 
HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid);
 

	
 
void InitializeBuildingCounts();
 
void IncreaseBuildingCount(Town *t, HouseID house_id);
 
void DecreaseBuildingCount(Town *t, HouseID house_id);
 
void AfterLoadCountBuildings();
 

	
 
void DrawNewHouseTile(TileInfo *ti, HouseID house_id);
 
void AnimateNewHouseTile(TileIndex tile);
 
void ChangeHouseAnimationFrame(TileIndex tile, uint16 callback_result);
 

	
 
uint16 GetHouseCallback(uint16 callback, uint32 param1, HouseID house_id, Town *town, TileIndex tile);
 

	
 
bool CanDeleteHouse(TileIndex tile);
 

	
 
bool NewHouseTileLoop(TileIndex tile);
 

	
 
#endif /* NEWGRF_HOUSE_H */
src/newgrf_sound.cpp
Show inline comments
 
@@ -63,6 +63,15 @@ bool PlayVehicleSound(const Vehicle *v, 
 
	if (callback == CALLBACK_FAILED) return false;
 
	if (callback >= GetNumOriginalSounds()) callback += file->sound_offset - GetNumOriginalSounds();
 

	
 
	if (callback < GetNumSounds()) SndPlayVehicleFx((SoundFx)callback, v);
 
	return true;
 
}
 

	
 
bool PlayHouseSound(uint16 sound_id, TileIndex tile)
 
{
 
	if (sound_id < GetNumOriginalSounds()) {
 
		SndPlayTileFx((SoundFx)sound_id, tile);
 
		return true;
 
	}
 
	return false;
 
}
src/newgrf_sound.h
Show inline comments
 
@@ -18,8 +18,9 @@ enum VehicleSoundEvent {
 

	
 
FileEntry *AllocateFileEntry();
 
void InitializeSoundPool();
 
FileEntry *GetSound(uint index);
 
uint GetNumSounds();
 
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event);
 
bool PlayHouseSound(uint16 sound_id, TileIndex tile);
 

	
 
#endif /* NEWGRF_SOUND_H */
src/newgrf_spritegroup.cpp
Show inline comments
 
@@ -5,12 +5,13 @@
 
#include "variables.h"
 
#include "macros.h"
 
#include "oldpool.h"
 
#include "newgrf_callbacks.h"
 
#include "newgrf_spritegroup.h"
 
#include "date.h"
 
#include "sprite.h"
 

	
 
static void SpriteGroupPoolCleanBlock(uint start_item, uint end_item);
 

	
 
static uint _spritegroup_count = 0;
 
STATIC_OLD_POOL(SpriteGroup, SpriteGroup, 9, 250, NULL, SpriteGroupPoolCleanBlock)
 

	
 
@@ -30,12 +31,17 @@ static void DestroySpriteGroup(SpriteGro
 
			break;
 

	
 
		case SGT_RANDOMIZED:
 
			free((SpriteGroup**)group->g.random.groups);
 
			break;
 

	
 
		case SGT_TILELAYOUT:
 
			free((void*)group->g.layout.dts->seq);
 
			free(group->g.layout.dts);
 
			break;
 

	
 
		default:
 
			break;
 
	}
 
}
 

	
 
static void SpriteGroupPoolCleanBlock(uint start_item, uint end_item)
src/newgrf_spritegroup.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef NEWGRF_SPRITEGROUP_H
 
#define NEWGRF_SPRITEGROUP_H
 

	
 
#include "town.h"
 

	
 
struct SpriteGroup;
 

	
 

	
 
/* 'Real' sprite groups contain a list of other result or callback sprite
 
 * groups. */
 
@@ -125,32 +126,39 @@ struct CallbackResultSpriteGroup {
 
 * sprites in the set */
 
struct ResultSpriteGroup {
 
	SpriteID sprite;
 
	byte num_sprites;
 
};
 

	
 
struct TileLayoutSpriteGroup {
 
	byte num_sprites; /* Number of sprites in the spriteset, used for loading stages */
 
	struct DrawTileSprites *dts;
 
};
 

	
 
/* List of different sprite group types */
 
enum SpriteGroupType {
 
	SGT_INVALID,
 
	SGT_REAL,
 
	SGT_DETERMINISTIC,
 
	SGT_RANDOMIZED,
 
	SGT_CALLBACK,
 
	SGT_RESULT,
 
	SGT_TILELAYOUT,
 
};
 

	
 
/* Common wrapper for all the different sprite group types */
 
struct SpriteGroup {
 
	SpriteGroupType type;
 

	
 
	union {
 
		RealSpriteGroup real;
 
		DeterministicSpriteGroup determ;
 
		RandomizedSpriteGroup random;
 
		CallbackResultSpriteGroup callback;
 
		ResultSpriteGroup result;
 
		TileLayoutSpriteGroup layout;
 
	} g;
 
};
 

	
 

	
 
SpriteGroup *AllocateSpriteGroup();
 
void InitializeSpriteGroupPool();
 
@@ -177,12 +185,17 @@ struct ResolverObject {
 
		struct {
 
			TileIndex tile;
 
			const struct Station *st;
 
			const struct StationSpec *statspec;
 
			CargoID cargo_type;
 
		} station;
 
		struct {
 
			TileIndex tile;
 
			Town *town;
 
			HouseID house_id;
 
		} house;
 
	} u;
 

	
 
	uint32 (*GetRandomBits)(const struct ResolverObject*);
 
	uint32 (*GetTriggers)(const struct ResolverObject*);
 
	void (*SetTriggers)(const struct ResolverObject*, int);
 
	uint32 (*GetVariable)(const struct ResolverObject*, byte, byte, bool*);
src/newgrf_town.cpp
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/** @file newgrf_town.cpp */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "debug.h"
 
#include "functions.h"
 
#include "town.h"
 

	
 
/** This function implements the town variables that newGRF defines.
 
 * @param variable that is queried
 
 * @param parameter unused
 
 * @param available will return false if ever the variable asked for does not exist
 
 * @param t is of course the town we are inquiring
 
 * @return the value stored in the corresponding variable*/
 
uint32 TownGetVariable(byte variable, byte parameter, bool *available, const Town *t)
 
{
 
	switch (variable) {
 
		/* Larger towns */
 
		case 0x40: return 1;
 

	
 
		/* Town index */
 
		case 0x41: return t->index;
 

	
 
		/* Town properties */
 
		case 0x80: return t->xy;
 
		case 0x81: return GB(t->xy, 8, 8);
 
		case 0x82: return t->population;
 
		case 0x83: return GB(t->population, 8, 8);
 
		case 0x8A: return t->grow_counter;
 
		case 0x92: return t->flags12;  // In original game, 0x92 and 0x93 are really one word. Since flags12 is a byte, this is to adjust
 
		case 0x93: return 0;
 
		case 0x94: return t->radius[0];
 
		case 0x95: return GB(t->radius[0], 8, 8);
 
		case 0x96: return t->radius[1];
 
		case 0x97: return GB(t->radius[1], 8, 8);
 
		case 0x98: return t->radius[2];
 
		case 0x99: return GB(t->radius[2], 8, 8);
 
		case 0x9A: return t->radius[3];
 
		case 0x9B: return GB(t->radius[3], 8, 8);
 
		case 0x9C: return t->radius[4];
 
		case 0x9D: return GB(t->radius[4], 8, 8);
 
		case 0x9E: return t->ratings[0];
 
		case 0x9F: return t->ratings[1];
 
		case 0xA0: return t->ratings[2];
 
		case 0xA1: return t->ratings[3];
 
		case 0xA2: return t->ratings[4];
 
		case 0xA3: return t->ratings[5];
 
		case 0xA4: return t->ratings[6];
 
		case 0xA5: return t->ratings[7];
 
		case 0xA6: return t->ratings[8];
 
		case 0xAE: return t->have_ratings;
 
		case 0xB2: return t->statues;
 
		case 0xB6: return t->num_houses;
 
		case 0xB9: return t->growth_rate;
 
		case 0xBA: return t->new_max_pass;
 
		case 0xBB: return GB(t->new_max_pass, 8, 8);
 
		case 0xBC: return t->new_max_mail;
 
		case 0xBD: return GB(t->new_max_mail, 8, 8);
 
		case 0xBE: return t->new_act_pass;
 
		case 0xBF: return GB(t->new_act_pass, 8, 8);
 
		case 0xC0: return t->new_act_mail;
 
		case 0xC1: return GB(t->new_act_mail, 8, 8);
 
		case 0xC2: return t->max_pass;
 
		case 0xC3: return GB(t->max_pass, 8, 8);
 
		case 0xC4: return t->max_mail;
 
		case 0xC5: return GB(t->max_mail, 8, 8);
 
		case 0xC6: return t->act_pass;
 
		case 0xC7: return GB(t->act_pass, 8, 8);
 
		case 0xC8: return t->act_mail;
 
		case 0xC9: return GB(t->act_mail, 8, 8);
 
		case 0xCA: return t->pct_pass_transported;
 
		case 0xCB: return t->pct_mail_transported;
 
		case 0xCC: return t->new_act_food;
 
		case 0xCD: return GB(t->new_act_food, 8, 8);
 
		case 0xCE: return t->new_act_water;
 
		case 0xCF: return GB(t->new_act_water, 8, 8);
 
		case 0xD0: return t->act_food;
 
		case 0xD1: return GB(t->act_food, 8, 8);
 
		case 0xD2: return t->act_water;
 
		case 0xD3: return GB(t->act_water, 8, 8);
 
		case 0xD4: return t->road_build_months;
 
		case 0xD5: return t->fund_buildings_months;
 
	}
 

	
 
	DEBUG(grf, 1, "Unhandled town property 0x%X", variable);
 

	
 
	*available = false;
 
	return (uint32)-1;
 
}
src/newgrf_town.h
Show inline comments
 
new file 100644
 
/* $Id$ */
 

	
 
/** @file newgrf_town.h */
 

	
 
#ifndef NEWGRF_TOWN_H
 
#define NEWGRF_TOWN_H
 

	
 
/* Currently there is no direct town resolver; we only need to get town
 
 * variable results from inside stations, house tiles and industry tiles. */
 

	
 
uint32 TownGetVariable(byte variable, byte parameter, bool *available, const Town *t);
 

	
 
#endif /* NEWGRF_TOWN_H */
src/openttd.cpp
Show inline comments
 
@@ -53,12 +53,13 @@
 
#include "settings.h"
 
#include "genworld.h"
 
#include "date.h"
 
#include "clear_map.h"
 
#include "fontcache.h"
 
#include "newgrf_config.h"
 
#include "newgrf_house.h"
 
#include "player_face.h"
 

	
 
#include "bridge_map.h"
 
#include "clear_map.h"
 
#include "rail_map.h"
 
#include "road_map.h"
 
@@ -674,12 +675,13 @@ static void MakeNewGameDone()
 

	
 
static void MakeNewGame(bool from_heightmap)
 
{
 
	_game_mode = GM_NORMAL;
 

	
 
	ResetGRFConfig(true);
 
	ResetHouseIDMapping();
 

	
 
	GenerateWorldSetCallback(&MakeNewGameDone);
 
	GenerateWorld(from_heightmap ? GW_HEIGHTMAP : GW_NEWGAME, 1 << _patches.map_x, 1 << _patches.map_y);
 
}
 

	
 
static void MakeNewEditorWorldDone()
 
@@ -1753,12 +1755,53 @@ bool AfterLoadGame()
 
	/* from version 38 we have optional elrails, since we cannot know the
 
	 * preference of a user, let elrails enabled; it can be disabled manually */
 
	if (CheckSavegameVersion(38)) _patches.disable_elrails = false;
 
	/* do the same as when elrails were enabled/disabled manually just now */
 
	SettingsDisableElrail(_patches.disable_elrails);
 

	
 
	/* From version 52, the map array was changed for house tiles to allow
 
	 * space for newhouses grf features. A new byte, m7, was also added. */
 
	if (CheckSavegameVersion(52)) {
 
		for (TileIndex t = 0; t < map_size; t++) {
 
			_me[t].m7 = 0;
 

	
 
			if (IsTileType(t, MP_HOUSE)) {
 
				if (GB(_m[t].m3, 6, 2) != TOWN_HOUSE_COMPLETED) {
 
					/* Move the construction stage from m3[7..6] to m5[5..4].
 
					 * The construction counter does not have to move. */
 
					SB(_m[t].m5, 3, 2, GB(_m[t].m3, 6, 2));
 
					SB(_m[t].m3, 6, 2, 0);
 

	
 
					/* The "house is completed" bit is now in m6[2]. */
 
					SetHouseCompleted(t, false);
 
				} else {
 
					/* The "lift has destination" bit has been moved from
 
					 * m5[7] to m7[0]. */
 
					SB(_me[t].m7, 0, 1, HASBIT(_m[t].m5, 7));
 
					CLRBIT(_m[t].m5, 7);
 

	
 
					/* The "lift is moving" bit has been removed, as it does
 
					 * the same job as the "lift has destination" bit. */
 
					CLRBIT(_m[t].m1, 7);
 

	
 
					/* The position of the lift goes from m1[7..0] to m6[7..2],
 
					 * making m1 totally free, now. The lift position does not
 
					 * have to be a full byte since the maximum value is 36. */
 
					SetLiftPosition(t, GB(_m[t].m1, 0, 6 ));
 

	
 
					_m[t].m1 = 0;
 
					_m[t].m3 = 0;
 
					SetHouseCompleted(t, true);
 
				}
 
			}
 
		}
 
	}
 

	
 
	/* Count the buildings after updating the map array. */
 
	AfterLoadCountBuildings();
 

	
 
	if (CheckSavegameVersion(43)) {
 
		for (TileIndex t = 0; t < map_size; t++) {
 
			if (IsTileType(t, MP_INDUSTRY)) {
 
				switch (GetIndustryGfx(t)) {
 
					case GFX_POWERPLANT_SPARKS:
 
						SetIndustryAnimationState(t, GB(_m[t].m1, 2, 5));
 
@@ -1883,12 +1926,14 @@ void ReloadNewGRFData()
 
	ResetVehiclePosHash();
 
	AfterLoadVehicles();
 
	StartupEngines();
 
	/* update station and waypoint graphics */
 
	AfterLoadWaypoints();
 
	AfterLoadStations();
 
	/* check that house ids are still valid */
 
	CheckHouseIDs();
 
	/* redraw the whole screen */
 
	MarkWholeScreenDirty();
 
}
 

	
 
HalMusicDriver *_music_driver;
 
HalSoundDriver *_sound_driver;
src/table/sprites.h
Show inline comments
 
@@ -32,13 +32,12 @@
 
 * get a proper editor. If your Operating Systems don't have any decent editors,
 
 * get a proper Operating System.
 
 *
 
 * @todo Split the "Sprites" enum into smaller chunks and document them
 
 */
 

	
 

	
 
enum Sprites {
 
	SPR_SELECT_TILE  = 752,
 
	SPR_DOT          = 774, // corner marker for lower/raise land
 
	SPR_DOT_SMALL    = 4078,
 
	SPR_WHITE_POINT  = 4079,
 

	
 
@@ -1321,12 +1320,13 @@ enum SpriteSetup {
 
 * in the bits marked by PALETTE_SPRITE_MASK.
 
 * @note Do not modify this enum. Alter SpriteSetup instead
 
 * @see SpriteSetup
 
 */
 
enum Modifiers {
 
	SPRITE_MODIFIER_USE_OFFSET    = OFFSET_BIT,
 
	SPRITE_MODIFIER_OPAQUE        = OFFSET_BIT,
 
	///when a sprite is to be displayed transparently, this bit needs to be set.
 
	PALETTE_MODIFIER_TRANSPARENT  = TRANSPARENT_BIT,
 
	///this bit is set when a recoloring process is in action
 
	PALETTE_MODIFIER_COLOR        = RECOLOR_BIT,
 

	
 
	//This is used for the GfxFillRect function
 
@@ -1415,9 +1415,8 @@ enum PaletteSprites {
 
	//XXX - const - PALETTE_CRASH               = 0x324,  //this changes stuff to the "crash color"
 
	//XXX another place where structures are colored.
 
	//I'm not sure which colors these are
 
	PALETTE_59E                 = 0x59E,
 
	PALETTE_59F                 = 0x59F,
 
};
 
#undef PALETTE_RECOLOR_SPRITE
 

	
 
#endif /* SPRITES_H */
src/table/town_land.h
Show inline comments
 
/* $Id$ */
 

	
 
/** @file town_land.h */
 

	
 
enum {
 
	HOUSE_TEMP_CHURCH    = 0x03,
 
	HOUSE_STADIUM        = 0x14,
 
	HOUSE_MODERN_STADIUM = 0x20,
 
	HOUSE_ARCT_CHURCH    = 0x3c,
 
	HOUSE_SNOW_CHURCH    = 0x3d,
 
	HOUSE_TROP_CHURCH    = 0x53,
 
	HOUSE_TOY_CHURCH     = 0x5b,
 

	
 
	HOUSE_MAX            = 110
 
};
 

	
 
/** Writes the data into the Town Tile Drawing Struct
 
 * @param s1 The first sprite of the building, mostly the ground sprite
 
 * @param s2 The second sprite of the building.
 
 * @param sx The x-position of the sprite within the tile
 
 * @param xy the y-position of the sprite within the tile
 
@@ -1787,440 +1776,375 @@ static const DrawBuildingsTileStruct _to
 
	M(0x1244, PAL_NONE,    0x0, PAL_NONE,  0,  0, 16, 16,  50, 0),
 
	M(0x1244, PAL_NONE, 0x125a, PAL_NONE,  0,  0, 16, 16,  50, 0),
 
	M(0x1244, PAL_NONE, 0x125a, PAL_NONE,  0,  0, 16, 16,  50, 0),
 
	M(0x1244, PAL_NONE, 0x125a, PAL_NONE,  0,  0, 16, 16,  50, 0),
 
};
 
#undef M
 
// 4 variants * 4 build stages
 
assert_compile(lengthof(_town_draw_tile_data) == HOUSE_MAX * 4 * 4);
 

	
 

	
 
static const StringID _town_tile_names[] = {
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_2010_OFFICE_BLOCK,
 
	STR_2011_SMALL_BLOCK_OF_FLATS,
 
	STR_2012_CHURCH,
 
	STR_2013_LARGE_OFFICE_BLOCK,
 
	STR_2013_LARGE_OFFICE_BLOCK,
 
	STR_2014_TOWN_HOUSES,
 
	STR_2015_HOTEL,
 
	STR_2015_HOTEL,
 
	STR_2016_STATUE,
 
	STR_2017_FOUNTAIN,
 
	STR_2018_PARK,
 
	STR_2018_PARK,
 
	STR_2019_OFFICE_BLOCK,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201B_MODERN_OFFICE_BUILDING,
 
	STR_201C_WAREHOUSE,
 
	STR_201D_OFFICE_BLOCK,
 
	STR_201E_STADIUM,
 
	STR_201E_STADIUM,
 
	STR_201E_STADIUM,
 
	STR_201E_STADIUM,
 
	STR_201F_OLD_HOUSES,
 
	STR_2036_COTTAGES,
 
	STR_2037_HOUSES,
 
	STR_2038_FLATS,
 
	STR_2039_TALL_OFFICE_BLOCK,
 
	STR_203A_SHOPS_AND_OFFICES,
 
	STR_203B_SHOPS_AND_OFFICES,
 
	STR_203C_THEATER,
 
	STR_203D_STADIUM,
 
	STR_203D_STADIUM,
 
	STR_203D_STADIUM,
 
	STR_203D_STADIUM,
 
	STR_203E_OFFICES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_2040_CINEMA,
 
	STR_2041_SHOPPING_MALL,
 
	STR_2041_SHOPPING_MALL,
 
	STR_2041_SHOPPING_MALL,
 
	STR_2041_SHOPPING_MALL,
 
	STR_2038_FLATS,
 
	STR_2038_FLATS,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_2012_CHURCH,
 
	STR_2012_CHURCH,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_2015_HOTEL,
 
	STR_2015_HOTEL,
 
	STR_2015_HOTEL,
 
	STR_2015_HOTEL,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_2038_FLATS,
 
	STR_2012_CHURCH,
 
	STR_203F_HOUSES,
 
	STR_2038_FLATS,
 
	STR_2038_FLATS,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_2038_FLATS,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_2012_CHURCH,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_203F_HOUSES,
 
	STR_203F_HOUSES,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_2059_IGLOO,
 
	STR_205A_TEPEES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_201A_SHOPS_AND_OFFICES,
 
	STR_200F_TALL_OFFICE_BLOCK,
 
	STR_2016_STATUE,
 
	STR_205B_TEAPOT_HOUSE,
 
	STR_205C_PIGGY_BANK,
 
};
 
assert_compile(lengthof(_town_tile_names) == HOUSE_MAX);
 

	
 
static const uint16 _housetype_flags[] = {
 
	0x1010, 0x1018, 0x100E, 0x100F, 0x7010, 0x0810, 0x100F, 0x1014,
 
	0x0000, 0x7018, 0x7010, 0x1004, 0x1008, 0x1018, 0x101C, 0x101C,
 
	0x101C, 0x7010, 0x1010, 0x1010, 0x100F, 0x0000, 0x0000, 0x0000,
 
	0x1003, 0x1001, 0x100F, 0x101C, 0x101C, 0x101C, 0x5014, 0x1018,
 
	0x700F, 0x0000, 0x0000, 0x0000, 0x7018, 0x2003, 0x0803, 0x101C,
 
	0x101E, 0x0000, 0x0000, 0x0000, 0x201C, 0x081C, 0x200F, 0x080F,
 
	0x2007, 0x0807, 0x6018, 0x0818, 0x2018, 0x0818, 0x6018, 0x0818,
 
	0x2001, 0x0801, 0x201E, 0x081E, 0x200F, 0x080F, 0x2007, 0x0807,
 
	0x201C, 0x081C, 0x201C, 0x0000, 0x081C, 0x0000, 0x601C, 0x081C,
 
	0x2018, 0x0818, 0x201C, 0x0000, 0x081C, 0x0000, 0x401E, 0x401E,
 
	0x401E, 0x4001, 0x401C, 0x400E, 0x401E, 0x401C, 0x401C, 0x4018,
 
	0x4000, 0x401C, 0x4018, 0x801F, 0x801F, 0x8003, 0x800F, 0x800F,
 
	0x800F, 0x800F, 0x801C, 0x801F, 0x0000, 0x801C, 0x8001, 0x8001,
 
	0x801C, 0x801C, 0x801C, 0x801C, 0x801F, 0x801F,
 
};
 
assert_compile(lengthof(_housetype_flags) == HOUSE_MAX);
 

	
 
static const byte _housetype_extra_flags[] = {
 
	 0,  0,  0,  0, 32, 32,  0,  8,
 
	 0,  0,  0,  0,  0,  0,  0,  0,
 
	 0,  0,  0,  0, 16,  0,  0,  0,
 
	 0,  0,  0,  0,  0,  0,  0,  0,
 
	16,  0,  0,  0,  0,  0,  0,  0,
 
	16,  0,  0,  0,  0,  0,  0,  0,
 
	 0,  0,  0,  0,  0,  0,  0,  0,
 
	 0,  0,  0,  0,  0,  0,  0,  0,
 
	 0,  0,  8,  0,  8,  0,  0,  0,
 
	 0,  0,  4,  0,  4,  0,  0,  0,
 
	 0,  0,  0,  0,  0,  0,  0,  4,
 
	 0,  0,  0,  0,  0,  0,  0,  0,
 
	 0,  0,  0,  8,  0,  0,  0,  0,
 
	 0,  0,  0,  0,  0,  0,
 
};
 
assert_compile(lengthof(_housetype_extra_flags) == HOUSE_MAX);
 

	
 
static const byte _housetype_population[] = {
 
	187,  85,  40,   5, 220, 220,  30, 140,
 
	  0,   0,   0,   0,   0, 150,  95,  95,
 
	 95, 130,   6, 110,  65,   0,   0,   0,
 
	 15,  12,  13, 100, 170, 100, 180,  35,
 
	 65,   0,   0,   0, 140,  15,  15,  35,
 
	180,   0,   0,   0,  80,  80,  16,  16,
 
	 14,  14, 135, 135, 170, 170, 210, 210,
 
	 10,  10,  25,  25,   6,   6,  17,  17,
 
	 90,  90, 140,   0, 140,   0, 105, 105,
 
	190, 190, 250,   0, 250,   0,  16,  16,
 
	 16,   7,  45,   8,  18,  90, 120, 250,
 
	  0,  80, 180,   8,  18,   7,  15,  17,
 
	 19,  21,  75,  35,   0,  85,  11,  10,
 
	 67,  86,  95,  30,  25,  18,
 
};
 
assert_compile(lengthof(_housetype_population) == HOUSE_MAX);
 

	
 
static const byte _housetype_mailamount[] = {
 
	70, 55, 20,  2, 85, 85, 12, 22,
 
	22,  0,  0,  0,  0, 65, 48, 48,
 
	48, 50, 10, 55,  5,  5,  5,  5,
 
	 6,  7,  8, 35, 50, 40, 64, 23,
 
	 5,  5,  5,  5, 65,  6,  6, 23,
 
	 5,  5,  5,  5, 20, 20,  6,  6,
 
	 6,  6, 60, 60, 70, 70, 80, 80,
 
	 5,  5, 20, 20,  2,  2,  7,  7,
 
	45, 45, 25, 25, 25, 25, 50, 50,
 
	75, 75, 60, 60, 60, 60,  6,  6,
 
	 5,  4, 15,  3,  7, 24, 25, 80,
 
	80, 23, 90,  3,  5,  3,  6,  6,
 
	 6,  6, 20,  9,  0, 18,  3,  3,
 
	22, 23, 28, 10,  8,  7,
 
};
 
assert_compile(lengthof(_housetype_mailamount) == HOUSE_MAX);
 

	
 
static const byte _housetype_remove_cost[] = {
 
	 150, 140, 100,  90, 160, 160,  80, 180,
 
	 180,  65,  65,  60,  60, 130, 110, 105,
 
	 107, 200, 145, 155, 250, 250, 250, 250,
 
	  70,  75,  71, 135, 145, 132, 155, 220,
 
	 250, 250, 250, 250, 170,  70,  70, 210,
 
	 250, 250, 250, 250, 100, 100,  70,  70,
 
	  80,  80, 150, 150, 170, 170, 200, 200,
 
	  60,  60, 100, 100,  85,  85,  80,  80,
 
	 140, 140, 160, 160, 160, 160, 130, 130,
 
	 190, 190, 140, 140, 140, 140,  80,  80,
 
	  80,  30, 130,  90,  80, 110, 120, 190,
 
	 190, 110, 180,  90,  90,  70,  80,  80,
 
	  80,  80, 160,  90,  90, 150,  60,  60,
 
	 140, 145, 165,  90,  75,  85,
 
};
 
assert_compile(lengthof(_housetype_remove_cost) == HOUSE_MAX);
 
/* 4 variants * 4 build stages */
 
assert_compile(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
 

	
 
static const uint16 _housetype_remove_ratingmod[] = {
 
	 140, 130,  90, 230, 160, 160,  80, 150,
 
	 150,  40,  40,  75,  75, 110, 100, 100,
 
	 100, 150, 110, 110, 300, 300, 300, 300,
 
	  75,  75,  75, 100, 170, 135, 180, 230,
 
	 300, 300, 300, 300, 250,  75,  75, 230,
 
	 300, 300, 300, 300,  90,  90,  70,  70,
 
	  70,  70, 120, 120, 130, 130, 140, 140,
 
	  60,  60,  80,  80, 230, 230,  80,  80,
 
	 110, 110, 160, 160, 160, 160, 105, 105,
 
	 135, 135, 200, 200, 200, 200,  80,  80,
 
	  80,  30,  95, 200,  80,  95,  95, 140,
 
	 140,  95, 150, 200,  90,  50,  75,  75,
 
	  75,  75, 130,  80,  80, 130,  45,  45,
 
	 130, 130, 130,  70,  65,  95,
 
};
 
assert_compile(lengthof(_housetype_remove_ratingmod) == HOUSE_MAX);
 

	
 

	
 
struct HousetypeYear {
 
	Year min, max;
 
/** Describes the data that defines each house in the game
 
 * @param mnd introduction year of the house
 
 * @param mxd last year it can be built
 
 * @param p   population
 
 * @param rc  cost multiplier for removing it
 
 * @param bn  building name
 
 * @param rr  rating decrease if removed
 
 * @param mg  mail generation multiplier
 
 * @param pa  passenger acceptance
 
 * @param ma  mail acceptance
 
 * @param ga  goods acceptance
 
 * @param fa  food acceptance
 
 * @param bf  building flags (size, stadium etc...)
 
 * @param ba  building availability (zone, climate...)
 
 * @see HouseSpec
 
 */
 
#define M(mnd, mxd, p, rc, bn, rr, mg, pa, ma, ga, fa, bf, ba) \
 
	{mnd, mxd, p, rc, bn, rr, mg, pa, ma, ga, fa, bf, ba, true, \
 
	 0, NULL, 0, 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, 0, 2, 0, 0, NULL}
 
static const HouseSpec _original_house_specs[] = {
 
	/**
 
	 *                                                              remove_rating_decrease
 
	 *                                                               |    mail_generation
 
	 *     min_date                                                  |    |    passenger_acceptance
 
	 *     |         max_date                                        |    |    |    mail_acceptance
 
	 *     |         |    population                                 |    |    |    |    goods_acceptance
 
	 *     |         |    |    removal_cost                          |    |    |    |    |    food_acceptance
 
	 *     |         |    |    |    building_name                    |    |    |    |    |    |
 
	 *     |         |    |    |    |                                |    |    |    |    |    |
 
	 *     |         |    |    |    |                                |    |    |    |    |    |
 
	 * +-building_flags   |    |    |                                |    |    |    |    |    |
 
	 * +-building_availability |    |                                |    |    |    |    |    |
 
	 * |   |         |    |    |    |                                |    |    |    |    |    |*/
 
	M( 1963, MAX_YEAR, 187, 150, STR_200F_TALL_OFFICE_BLOCK,      140,  70,   8,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5),
 
	M( 1957, MAX_YEAR,  85, 140, STR_2010_OFFICE_BLOCK,           130,  55,   8,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
 
	M( 1968, MAX_YEAR,  40, 100, STR_2011_SMALL_BLOCK_OF_FLATS,    90,  20,   8,   3,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,   5,  90, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
 
	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M( 1975, MAX_YEAR, 220, 160, STR_2013_LARGE_OFFICE_BLOCK,     160,  85,  10,   4,   6,   0,
 
	   BUILDING_IS_ANIMATED | TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
 
	M( 1975, MAX_YEAR, 220, 160, STR_2013_LARGE_OFFICE_BLOCK,     160,  85,  10,   4,   6,   0,
 
	   BUILDING_IS_ANIMATED | TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE  | HZ_ZON5),
 
	M(    0, MAX_YEAR,  30,  80, STR_2014_TOWN_HOUSES,             80,  12,   4,   1,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M( 1959, MAX_YEAR, 140, 180, STR_2015_HOTEL,                  150,  22,   6,   1,   2,   0,
 
	   TILE_SIZE_1x2,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON3),
 
	M( 1959, MAX_YEAR,   0, 180, STR_2015_HOTEL,                  150,  22,   6,   1,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1945, MAX_YEAR,   0,  65, STR_2016_STATUE,                  40,   0,   2,   0,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
 
	M( 1945, MAX_YEAR,   0,  65, STR_2017_FOUNTAIN,                40,   0,   2,   0,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
 
	M(    0, MAX_YEAR,   0,  60, STR_2018_PARK,                    75,   0,   2,   0,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON3),
 
	M( 1935, MAX_YEAR,   0,  60, STR_2018_PARK,                    75,   0,   2,   0,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON4),
 
	M( 1951, MAX_YEAR, 150, 130, STR_2019_OFFICE_BLOCK,           110,  65,   8,   2,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
 
	M( 1930, 1960,      95, 110, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1930, 1960,      95, 105, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1930, 1960,      95, 107, STR_201A_SHOPS_AND_OFFICES,      100,  48,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1977, MAX_YEAR, 130, 200, STR_201B_MODERN_OFFICE_BUILDING, 150,  50,  10,   3,   6,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5),
 
	M( 1983, MAX_YEAR,   6, 145, STR_201C_WAREHOUSE,              110,  10,   6,   3,   8,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5),
 
	M( 1985, MAX_YEAR, 110, 155, STR_201D_OFFICE_BLOCK,           110,  55,   6,   2,   6,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5),
 
	M(    0, MAX_YEAR,  65, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   BUILDING_IS_STADIUM | TILE_SIZE_2x2,
 
	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, MAX_YEAR,   0, 250, STR_201E_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, 1951,      15,  70, STR_201F_OLD_HOUSES,              75,   6,   3,   1,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON2 | HZ_ZON1),
 
	M(    0, 1952,      12,  75, STR_2036_COTTAGES,                75,   7,   3,   1,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON1),
 
	M( 1931, MAX_YEAR,  13,  71, STR_2037_HOUSES,                  75,   8,   3,   1,   0,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M( 1935, MAX_YEAR, 100, 135, STR_2038_FLATS,                  100,  35,   7,   2,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1963, MAX_YEAR, 170, 145, STR_2039_TALL_OFFICE_BLOCK,      170,  50,   8,   3,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, 1955,     100, 132, STR_203A_SHOPS_AND_OFFICES,      135,  40,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1973, MAX_YEAR, 180, 155, STR_203B_SHOPS_AND_OFFICES,      180,  64,   8,   3,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  35, 220, STR_203C_THEATER,                230,  23,   8,   2,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4),
 
	M( 1958, MAX_YEAR,  65, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   BUILDING_IS_STADIUM | TILE_SIZE_2x2,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1958, MAX_YEAR,   0, 250, STR_203D_STADIUM,                300,   5,   4,   0,   0,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 2000, MAX_YEAR, 140, 170, STR_203E_OFFICES,                250,  65,   8,   3,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
 
	M(    0, 1960,      15,  70, STR_203F_HOUSES,                  75,   6,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON2 | HZ_ZON1),
 
	M(    0, 1960,      15,  70, STR_203F_HOUSES,                  75,   6,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON2 | HZ_ZON1),
 
	M( 1945, MAX_YEAR,  35, 210, STR_2040_CINEMA,                 230,  23,   8,   2,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1983, MAX_YEAR, 180, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
 
	   TILE_SIZE_2x2,
 
	   HZ_TEMP | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 |HZ_ZON2),
 
	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1983, MAX_YEAR,   0, 250, STR_2041_SHOPPING_MALL,          300,   5,   8,   2,   3,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, MAX_YEAR,  80, 100, STR_2038_FLATS,                   90,  20,   5,   2,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  80, 100, STR_2038_FLATS,                   90,  20,   5,   2,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE  | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  16,  70, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  16,  70, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, 1963,      14,  80, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, 1963,      14,  80, STR_203F_HOUSES,                  70,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M( 1966, MAX_YEAR, 135, 150, STR_200F_TALL_OFFICE_BLOCK,      120,  60,   8,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
 
	M( 1966, MAX_YEAR, 135, 150, STR_200F_TALL_OFFICE_BLOCK,      120,  60,   8,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
 
	M( 1970, MAX_YEAR, 170, 170, STR_200F_TALL_OFFICE_BLOCK,      130,  70,   9,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4),
 
	M( 1970, MAX_YEAR, 170, 170, STR_200F_TALL_OFFICE_BLOCK,      130,  70,   9,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
 
	M( 1974, MAX_YEAR, 210, 200, STR_200F_TALL_OFFICE_BLOCK,      140,  80,  10,   3,   5,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
 
	M( 1974, MAX_YEAR, 210, 200, STR_200F_TALL_OFFICE_BLOCK,      140,  80,  10,   3,   5,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
 
	M(    0, MAX_YEAR,  10,  60, STR_203F_HOUSES,                  60,   5,   2,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON1),
 
	M(    0, MAX_YEAR,  10,  60, STR_203F_HOUSES,                  60,   5,   2,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON1),
 
	M(    0, MAX_YEAR,  25, 100, STR_201A_SHOPS_AND_OFFICES,       80,  20,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,  25, 100, STR_201A_SHOPS_AND_OFFICES,       80,  20,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,   6,  85, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
 
	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,   6,  85, STR_2012_CHURCH,                 230,   2,   2,   0,   0,   0,
 
	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, 1960,      90, 140, STR_201A_SHOPS_AND_OFFICES,      110,  45,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, 1960,      90, 140, STR_201A_SHOPS_AND_OFFICES,      110,  45,   6,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1972, MAX_YEAR, 140, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   0,   3,
 
	   TILE_SIZE_1x2,
 
	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1972, MAX_YEAR,   0, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1972, MAX_YEAR, 140, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   0,   3,
 
	   TILE_SIZE_1x2,
 
	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1972, MAX_YEAR,   0, 160, STR_2015_HOTEL,                  160,  25,   6,   1,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1963, MAX_YEAR, 105, 130, STR_201A_SHOPS_AND_OFFICES,      105,  50,   7,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1963, MAX_YEAR, 105, 130, STR_201A_SHOPS_AND_OFFICES,      105,  50,   7,   2,   3,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1978, MAX_YEAR, 190, 190, STR_200F_TALL_OFFICE_BLOCK,      135,  75,   9,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_BELOW | HZ_ZON5 | HZ_ZON4),
 
	M( 1978, MAX_YEAR, 190, 190, STR_200F_TALL_OFFICE_BLOCK,      135,  75,   9,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4),
 
	M( 1967, MAX_YEAR, 250, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
 
	   TILE_SIZE_2x1,
 
	   HZ_SUBARTC_BELOW| HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1967, MAX_YEAR,   0, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M( 1967, MAX_YEAR, 250, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
 
	   TILE_SIZE_2x1,
 
	   HZ_SUBARTC_ABOVE | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1967, MAX_YEAR,   0, 140, STR_200F_TALL_OFFICE_BLOCK,      200,  60,   7,   2,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   6,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,  16,  80, STR_203F_HOUSES,                  80,   5,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,   7,  30, STR_203F_HOUSES,                  30,   4,   3,   1,   0,   1,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON1),
 
	M(    0, MAX_YEAR,  45, 130, STR_2038_FLATS,                   95,  15,   6,   2,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,   8,  90, STR_2012_CHURCH,                 200,   3,   2,   0,   0,   0,
 
	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M(    0, MAX_YEAR,  18,  80, STR_203F_HOUSES,                  80,   7,   3,   1,   0,   2,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2),
 
	M( 1973, MAX_YEAR,  90, 110, STR_2038_FLATS,                   95,  24,   6,   2,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1962, MAX_YEAR, 120, 120, STR_2038_FLATS,                   95,  25,   6,   2,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1984, MAX_YEAR, 250, 190, STR_200F_TALL_OFFICE_BLOCK,      140,  80,   8,   3,   4,   0,
 
	   TILE_SIZE_2x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4),
 
	M( 1984, MAX_YEAR,   0, 190, STR_200F_TALL_OFFICE_BLOCK,      140,  80,   8,   3,   4,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_SUBTROPIC),
 
	M(    0, MAX_YEAR,  80, 110, STR_2038_FLATS,                   95,  23,   6,   2,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M( 1993, MAX_YEAR, 180, 180, STR_200F_TALL_OFFICE_BLOCK,      150,  90,   8,   3,   4,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_SUBTROPIC | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,   8,  90, STR_2012_CHURCH,                 200,   3,   2,   0,   0,   0,
 
	   BUILDING_IS_CHURCH | TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  18,  90, STR_203F_HOUSES,                  90,   5,   6,   2,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,   7,  70, STR_203F_HOUSES,                  50,   3,   3,   1,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  15,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  17,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  19,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  21,  80, STR_203F_HOUSES,                  75,   6,   3,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  75, 160, STR_200F_TALL_OFFICE_BLOCK,      130,  20,   8,   4,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  35,  90, STR_203F_HOUSES,                  80,   9,   4,   1,   2,   0,
 
	   TILE_SIZE_1x2,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,   0,  90, STR_203F_HOUSES,                  80,   0,   4,   1,   2,   0,
 
	   TILE_NO_FLAG,
 
	   HZ_NOZNS),
 
	M(    0, MAX_YEAR,  85, 150, STR_200F_TALL_OFFICE_BLOCK,      130,  18,   8,   4,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  11,  60, STR_2059_IGLOO,                   45,   3,   3,   1,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON1),
 
	M(    0, MAX_YEAR,  10,  60, STR_205A_TEPEES,                  45,   3,   3,   1,   1,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON1),
 
	M(    0, MAX_YEAR,  67, 140, STR_201A_SHOPS_AND_OFFICES,      130,  22,   8,   4,   0,   4,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  86, 145, STR_201A_SHOPS_AND_OFFICES,      130,  23,   8,   4,   0,   4,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  95, 165, STR_200F_TALL_OFFICE_BLOCK,      130,  28,   8,   4,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  30,  90, STR_2016_STATUE,                  70,  10,   4,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3),
 
	M(    0, MAX_YEAR,  25,  75, STR_205B_TEAPOT_HOUSE,            65,   8,   3,   1,   2,   0,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
	M(    0, MAX_YEAR,  18,  85, STR_205C_PIGGY_BANK,              95,   7,   3,   2,   0,   4,
 
	   TILE_SIZE_1x1,
 
	   HZ_TOYLND | HZ_ZON5 | HZ_ZON4 | HZ_ZON3 | HZ_ZON2 | HZ_ZON1),
 
};
 

	
 
static const HousetypeYear _housetype_years[] = {
 
	{ 1963, MAX_YEAR },
 
	{ 1957, MAX_YEAR },
 
	{ 1968, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1975, MAX_YEAR },
 
	{ 1975, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1959, MAX_YEAR },
 
	{ 1959, MAX_YEAR },
 
	{ 1945, MAX_YEAR },
 
	{ 1945, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1935, MAX_YEAR },
 
	{ 1951, MAX_YEAR },
 
	{ 1930,     1960 },
 
	{ 1930,     1960 },
 
	{ 1930,     1960 },
 
	{ 1977, MAX_YEAR },
 
	{ 1983, MAX_YEAR },
 
	{ 1985, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0,     1951 },
 
	{    0,     1952 },
 
	{ 1931, MAX_YEAR },
 
	{ 1935, MAX_YEAR },
 
	{ 1963, MAX_YEAR },
 
	{    0,     1955 },
 
	{ 1973, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1958, MAX_YEAR },
 
	{ 1958, MAX_YEAR },
 
	{ 1958, MAX_YEAR },
 
	{ 1958, MAX_YEAR },
 
	{ 2000, MAX_YEAR },
 
	{    0,     1960 },
 
	{    0,     1960 },
 
	{ 1945, MAX_YEAR },
 
	{ 1983, MAX_YEAR },
 
	{ 1983, MAX_YEAR },
 
	{ 1983, MAX_YEAR },
 
	{ 1983, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0,     1963 },
 
	{    0,     1963 },
 
	{ 1966, MAX_YEAR },
 
	{ 1966, MAX_YEAR },
 
	{ 1970, MAX_YEAR },
 
	{ 1970, MAX_YEAR },
 
	{ 1974, MAX_YEAR },
 
	{ 1974, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0,     1960 },
 
	{    0,     1960 },
 
	{ 1972, MAX_YEAR },
 
	{ 1972, MAX_YEAR },
 
	{ 1972, MAX_YEAR },
 
	{ 1972, MAX_YEAR },
 
	{ 1963, MAX_YEAR },
 
	{ 1963, MAX_YEAR },
 
	{ 1978, MAX_YEAR },
 
	{ 1978, MAX_YEAR },
 
	{ 1967, MAX_YEAR },
 
	{ 1967, MAX_YEAR },
 
	{ 1967, MAX_YEAR },
 
	{ 1967, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1973, MAX_YEAR },
 
	{ 1962, MAX_YEAR },
 
	{ 1984, MAX_YEAR },
 
	{ 1984, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{ 1993, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
	{    0, MAX_YEAR },
 
};
 
assert_compile(lengthof(_housetype_years) == HOUSE_MAX);
 

	
 
static const byte _housetype_cargo_passengers[] = {
 
	8,  8,  8,  2, 10, 10,  4,  6,
 
	6,  2,  2,  2,  2,  8,  6,  6,
 
	6, 10,  6,  6,  4,  4,  4,  4,
 
	3,  3,  3,  7,  8,  6,  8,  8,
 
	4,  4,  4,  4,  8,  3,  3,  8,
 
	8,  8,  8,  8,  5,  5,  3,  3,
 
	3,  3,  8,  8,  9,  9, 10, 10,
 
	2,  2,  3,  3,  2,  2,  3,  3,
 
	6,  6,  6,  6,  6,  6,  7,  7,
 
	9,  9,  7,  7,  7,  7,  3,  3,
 
	3,  3,  6,  2,  3,  6,  6,  8,
 
	8,  6,  8,  2,  6,  3,  3,  3,
 
	3,  3,  8,  4,  4,  8,  3,  3,
 
	8,  8,  8,  4,  3,  3,
 
};
 
assert_compile(lengthof(_housetype_cargo_passengers) == HOUSE_MAX);
 

	
 
static const byte _housetype_cargo_mail[] = {
 
	 3, 3, 3, 0, 4, 4, 1, 1,
 
	 1, 0, 0, 0, 0, 2, 2, 2,
 
	 2, 3, 3, 2, 0, 0, 0, 0,
 
	 1, 1, 1, 2, 3, 2, 3, 2,
 
	 0, 0, 0, 0, 3, 1, 1, 2,
 
	 2, 2, 2, 2, 2, 2, 1, 1,
 
	 1, 1, 3, 3, 3, 3, 3, 3,
 
	 1, 1, 1, 1, 0, 0, 1, 1,
 
	 2, 2, 1, 1, 1, 1, 2, 2,
 
	 3, 3, 2, 2, 2, 2, 1, 1,
 
	 1, 1, 2, 0, 1, 2, 2, 3,
 
	 3, 2, 3, 0, 2, 1, 1, 1,
 
	 1, 1, 4, 1, 1, 4, 1, 1,
 
	 4, 4, 4, 1, 1, 2,
 
};
 
assert_compile(lengthof(_housetype_cargo_mail) == HOUSE_MAX);
 

	
 
static const byte _housetype_cargo_goods[] = {
 
	 4, 4, 1, 0, 6, 6, 0, 2,
 
	 2, 0, 0, 0, 0, 4, 3, 3,
 
	 3, 6, 8, 6, 0, 0, 0, 0,
 
	 0, 0, 0, 2, 3, 3, 3, 2,
 
	 0, 0, 0, 0, 2, 0, 0, 2,
 
	 3, 3, 3, 3, 0, 0, 0, 0,
 
	 0, 0, 4, 4, 4, 4, 5, 5,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 3, 3, 0, 2, 0, 2, 3, 3,
 
	 4, 4, 2, 2, 2, 2, 0, 0,
 
	 0, 0, 1, 0, 0, 1, 1, 4,
 
	 4, 1, 4, 0, 2, 1, 2, 2,
 
	 2, 2, 2, 2, 2, 2, 1, 1,
 
	 0, 0, 2, 2, 2, 0
 
};
 
assert_compile(lengthof(_housetype_cargo_goods) == HOUSE_MAX);
 

	
 
static const byte _housetype_cargo_food[] = {
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 1, 1, 0,
 
	 0, 0, 0, 0, 2, 2, 2, 2,
 
	 2, 2, 0, 0, 0, 0, 0, 0,
 
	 1, 1, 1, 1, 0, 0, 1, 1,
 
	 0, 0, 3, 0, 3, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 2, 2,
 
	 2, 1, 0, 0, 2, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 0, 0, 0, 0, 0, 0, 0, 0,
 
	 4, 4, 0, 0, 0, 4
 
};
 
assert_compile(lengthof(_housetype_cargo_food) == HOUSE_MAX);
 

	
 
static const byte _house_more_flags[] = {
 
	  8,  8,  8,  8,  8,  8,  8, 12,
 
	  0,  8,  8,  8,  8,  8,  8,  8,
 
	  8,  8,  8,  8, 15,  0,  0,  0,
 
	  8,  8,  8,  8,  8,  8,  8,  8,
 
	 15,  0,  0,  0,  8,  8,  8,  8,
 
	 15,  0,  0,  0,  8,  8,  8,  8,
 
	  8,  8,  8,  8,  8,  8,  8,  8,
 
	  8,  8,  8,  8,  8,  8,  8,  8,
 
	  8,  8, 12,  0, 12,  0,  8,  8,
 
	  8,  8, 10,  0, 10,  0,  8,  8,
 
	  8,  8,  8,  8,  8,  8,  8, 10,
 
	  0,  8,  8,  8,  8,  8,  8,  8,
 
	  8,  8,  8, 12,  0,  8,  8,  8,
 
	  8,  8,  8,  8,  8,  8,
 
};
 
assert_compile(lengthof(_house_more_flags) == HOUSE_MAX);
 
#undef M
 
assert_compile(lengthof(_original_house_specs) == NEW_HOUSE_OFFSET);
src/town.h
Show inline comments
 
@@ -2,15 +2,78 @@
 

	
 
#ifndef TOWN_H
 
#define TOWN_H
 

	
 
#include "oldpool.h"
 
#include "player.h"
 
#include "functions.h"
 
#include "helpers.hpp"
 

	
 
enum {
 
	INVALID_TOWN = 0xFFFF,
 
	HOUSE_NO_CLASS   = 0,
 
	NEW_HOUSE_OFFSET = 110,
 
	HOUSE_MAX        = 512,
 
	INVALID_TOWN     = 0xFFFF,
 
	INVALID_HOUSE_ID = 0xFFFF,
 

	
 
	/* There can only be as many classes as there are new houses, plus one for
 
	 * NO_CLASS, as the original houses don't have classes. */
 
	HOUSE_CLASS_MAX  = HOUSE_MAX - NEW_HOUSE_OFFSET + 1,
 
};
 

	
 
enum BuildingFlags {
 
	TILE_NO_FLAG         =       0,
 
	TILE_SIZE_1x1        = 1U << 0,
 
	TILE_NOT_SLOPED      = 1U << 1,
 
	TILE_SIZE_2x1        = 1U << 2,
 
	TILE_SIZE_1x2        = 1U << 3,
 
	TILE_SIZE_2x2        = 1U << 4,
 
	BUILDING_IS_ANIMATED = 1U << 5,
 
	BUILDING_IS_CHURCH   = 1U << 6,
 
	BUILDING_IS_STADIUM  = 1U << 7,
 
	BUILDING_HAS_1_TILE  = TILE_SIZE_1x1 | TILE_SIZE_2x1 | TILE_SIZE_1x2 | TILE_SIZE_2x2,
 
	BUILDING_2_TILES_X   = TILE_SIZE_2x1 | TILE_SIZE_2x2,
 
	BUILDING_2_TILES_Y   = TILE_SIZE_1x2 | TILE_SIZE_2x2,
 
	BUILDING_HAS_4_TILES = TILE_SIZE_2x2,
 
};
 

	
 
DECLARE_ENUM_AS_BIT_SET(BuildingFlags)
 

	
 
enum HouseZones {                  ///< Bit  Value       Meaning
 
	HZ_NOZNS             = 0x0000,  ///<       0          This is just to get rid of zeros, meaning none
 
	HZ_ZON1              = 0x0001,  ///< 0..4 1,2,4,8,10  which town zones the building can be built in, Zone1 been the further suburb
 
	HZ_ZON2              = 0x0002,
 
	HZ_ZON3              = 0x0004,
 
	HZ_ZON4              = 0x0008,
 
	HZ_ZON5              = 0x0010,  ///<                  center of town
 
	HZ_ZONALL            = 0x001F,  ///<       1F         This is just to englobe all above types at once
 
	HZ_SUBARTC_ABOVE     = 0x0800,  ///< 11    800        can appear in sub-arctic climate above the snow line
 
	HZ_TEMP              = 0x1000,  ///< 12   1000        can appear in temperate climate
 
	HZ_SUBARTC_BELOW     = 0x2000,  ///< 13   2000        can appear in sub-arctic climate below the snow line
 
	HZ_SUBTROPIC         = 0x4000,  ///< 14   4000        can appear in subtropical climate
 
	HZ_TOYLND            = 0x8000   ///< 15   8000        can appear in toyland climate
 
};
 

	
 
DECLARE_ENUM_AS_BIT_SET(HouseZones)
 

	
 
enum HouseExtraFlags {
 
	NO_EXTRA_FLAG            =       0,
 
	BUILDING_IS_HISTORICAL   = 1U << 0,  ///< this house will only appear during town generation in random games, thus the historical
 
	BUILDING_IS_PROTECTED    = 1U << 1,  ///< towns and AI will not remove this house, while human players will be able tp
 
	SYNCHRONISED_CALLBACK_1B = 1U << 2,  ///< synchronized callback 1B will be performed, on multi tile houses
 
	CALLBACK_1A_RANDOM_BITS  = 1U << 3,  ///< callback 1A needs random bits
 
};
 

	
 
DECLARE_ENUM_AS_BIT_SET(HouseExtraFlags)
 

	
 
typedef uint16 HouseID;
 
typedef uint16 HouseClassID;
 

	
 
struct BuildingCounts {
 
	uint8 id_count[HOUSE_MAX];
 
	uint8 class_count[HOUSE_CLASS_MAX];
 
};
 

	
 
struct Town {
 
	TileIndex xy;
 

	
 
	// Current population of people and amount of houses.
 
@@ -75,14 +138,54 @@ struct Town {
 

	
 
	// Index in town array
 
	TownID index;
 

	
 
	// NOSAVE: UpdateTownRadius updates this given the house count.
 
	uint16 radius[5];
 

	
 
	// NOSAVE: The number of each type of building in the town.
 
	BuildingCounts building_counts;
 
};
 

	
 
struct HouseSpec {
 
	/* Standard properties */
 
	Year min_date;                     ///< introduction year of the house
 
	Year max_date;                     ///< last year it can be built
 
	byte population;                   ///< population (Zero on other tiles in multi tile house.)
 
	byte removal_cost;                 ///< cost multiplier for removing it
 
	StringID building_name;            ///< building name
 
	uint16 remove_rating_decrease;     ///< rating decrease if removed
 
	byte mail_generation;              ///< mail generation multiplier (tile based, as the acceptances below)
 
	byte passenger_acceptance;         ///< passenger acceptance, given in 1/8th unit, max is 8, as the 3 next properies
 
	byte mail_acceptance;              ///< mail acceptance
 
	byte goods_acceptance;             ///< good acceptance
 
	byte food_acceptance;              ///< food (or fizzy drink) acceptance
 
	BuildingFlags building_flags;      ///< some flags that describe the house (size, stadium etc...)
 
	HouseZones building_availability;  ///< where can it be built (climates, zones)
 
	bool enabled;                      ///< the house is still avaible (by default, true.newgrf can disable it, though)
 

	
 
	/* NewHouses properties */
 
	HouseID substitute_id;             ///< which house this one is based on
 
	struct SpriteGroup *spritegroup;   ///< pointer to the different sprites of the house
 
	HouseID override;                  ///< which house this one replaces
 
	uint16 callback_mask;              ///< House callback flags
 
	byte random_colour[4];             ///< 4 "random" colours
 
	byte probability;                  ///< Relative probability of appearing (16 is the standard value)
 
	HouseExtraFlags extra_flags;       ///< some more flags
 
	HouseClassID class_id;             ///< defines the class this house has (grf file based) @See HouseGetVariable, prop 0x44
 
	byte animation_frames;             ///< number of animation frames
 
	byte animation_speed;              ///< amount of time between each of those frames
 
	byte processing_time;              ///< Periodic refresh multiplier
 

	
 
	/* grf file related properties*/
 
	uint8 local_id;                    ///< id defined by the grf file for this house
 
	const struct GRFFile *grffile;     ///< grf file that introduced this house
 
};
 

	
 
VARDEF HouseSpec _house_specs[HOUSE_MAX];
 

	
 
uint32 GetWorldPopulation();
 

	
 
void UpdateTownVirtCoord(Town *t);
 
void InitializeTown();
 
void ShowTownViewWindow(TownID town);
 
void ExpandTown(Town *t);
 
@@ -155,12 +258,18 @@ enum {
 
bool CheckforTownRating(uint32 flags, Town *t, byte type);
 

	
 
VARDEF const Town** _town_sort;
 

	
 
DECLARE_OLD_POOL(Town, Town, 3, 8000)
 

	
 
static inline HouseSpec *GetHouseSpecs(HouseID house_id)
 
{
 
	assert(house_id < HOUSE_MAX);
 
	return &_house_specs[house_id];
 
}
 

	
 
/**
 
 * Check if a Town really exists.
 
 */
 
static inline bool IsValidTown(const Town* town)
 
{
 
	return town->xy != 0;
 
@@ -226,7 +335,12 @@ Town* CalcClosestTownFromTile(TileIndex 
 
VARDEF bool _town_sort_dirty;
 
VARDEF byte _town_sort_order;
 

	
 
VARDEF Town *_cleared_town;
 
VARDEF int _cleared_town_rating;
 

	
 
uint OriginalTileRandomiser(uint x, uint y);
 
void ResetHouses();
 

	
 
void ClearTownHouse(Town *t, TileIndex tile);
 

	
 
#endif /* TOWN_H */
src/town_cmd.cpp
Show inline comments
 
@@ -2,12 +2,13 @@
 

	
 
/** @file town_cmd.cpp */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "functions.h"
 
#include "debug.h"
 
#include "strings.h"
 
#include "road_map.h"
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
#include "map.h"
 
#include "tile.h"
 
@@ -16,12 +17,13 @@
 
#include "viewport.h"
 
#include "town.h"
 
#include "command.h"
 
#include "gfx.h"
 
#include "industry.h"
 
#include "station.h"
 
#include "vehicle.h"
 
#include "player.h"
 
#include "news.h"
 
#include "saveload.h"
 
#include "economy.h"
 
#include "gui.h"
 
#include "unmovable_map.h"
 
@@ -29,12 +31,15 @@
 
#include "variables.h"
 
#include "bridge.h"
 
#include "bridge_map.h"
 
#include "date.h"
 
#include "table/town_land.h"
 
#include "genworld.h"
 
#include "newgrf.h"
 
#include "newgrf_callbacks.h"
 
#include "newgrf_house.h"
 

	
 
/**
 
 * Called if a new block is added to the town-pool
 
 */
 
static void TownPoolNewBlock(uint start_item)
 
{
 
@@ -88,43 +93,49 @@ void DestroyTown(Town *t)
 
}
 

	
 
// Local
 
static int _grow_town_result;
 

	
 
static bool BuildTownHouse(Town *t, TileIndex tile);
 
static void ClearTownHouse(Town *t, TileIndex tile);
 
static void DoBuildTownHouse(Town *t, TileIndex tile);
 

	
 
static void TownDrawHouseLift(const TileInfo *ti)
 
{
 
	AddChildSpriteScreen(SPR_LIFT, PAL_NONE, 14, 60 - GetLiftPosition(ti->tile));
 
}
 

	
 
typedef void TownDrawTileProc(const TileInfo *ti);
 
static TownDrawTileProc * const _town_draw_tile_procs[1] = {
 
	TownDrawHouseLift
 
};
 

	
 
uint OriginalTileRandomiser(uint x, uint y)
 
{
 
	uint variant;
 
	variant  = x >> 4;
 
	variant ^= x >> 6;
 
	variant ^= y >> 4;
 
	variant -= y >> 6;
 
	variant &= 3;
 
	return variant;
 
}
 

	
 
static void DrawTile_Town(TileInfo *ti)
 
{
 
	const DrawBuildingsTileStruct *dcts;
 
	SpriteID image;
 
	SpriteID pal;
 
	HouseID house_id = GetHouseType(ti->tile);
 

	
 
	if (house_id >= NEW_HOUSE_OFFSET) {
 
		DrawNewHouseTile(ti, house_id);
 
		return;
 
	}
 

	
 
	/* Retrieve pointer to the draw town tile struct */
 
	{
 
		/* this "randomizes" on the (up to) 4 variants of a building */
 
		uint variant;
 
		variant  = ti->x >> 4;
 
		variant ^= ti->x >> 6;
 
		variant ^= ti->y >> 4;
 
		variant -= ti->y >> 6;
 
		variant &= 3;
 
		dcts = &_town_draw_tile_data[GetHouseType(ti->tile) << 4 | variant << 2 | GetHouseBuildingStage(ti->tile)];
 
	}
 
	dcts = &_town_draw_tile_data[house_id << 4 | OriginalTileRandomiser(ti->x, ti->y) << 2 | GetHouseBuildingStage(ti->tile)];
 

	
 
	if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh);
 

	
 
	image = dcts->ground.sprite;
 
	pal   = dcts->ground.pal;
 
	DrawGroundSprite(image, pal);
 
@@ -169,24 +180,29 @@ static Slope GetSlopeTileh_Town(TileInde
 
}
 

	
 
static void AnimateTile_Town(TileIndex tile)
 
{
 
	int pos, dest;
 

	
 
	if (GetHouseType(tile) >= NEW_HOUSE_OFFSET) {
 
		AnimateNewHouseTile(tile);
 
		return;
 
	}
 

	
 
	if (_tick_counter & 3) return;
 

	
 
	// If the house is not one with a lift anymore, then stop this animating.
 
	// Not exactly sure when this happens, but probably when a house changes.
 
	// Before this was just a return...so it'd leak animated tiles..
 
	// That bug seems to have been here since day 1??
 
	if (!(_housetype_extra_flags[GetHouseType(tile)] & 0x20)) {
 
	if (!(GetHouseSpecs(GetHouseType(tile))->building_flags & BUILDING_IS_ANIMATED)) {
 
		DeleteAnimatedTile(tile);
 
		return;
 
	}
 

	
 
	if (!IsLiftMoving(tile)) {
 
	if (!LiftHasDestination(tile)) {
 
		int i;
 

	
 
		/** Building has 6 floors, number 0 .. 6, where 1 is illegal.
 
		 *  This is due to the fact that the first floor is, in the graphics,
 
		 *  the height of 2 'normal' floors.
 
		 *  Furthermore, there are 6 lift positions from floor N (incl) to floor N + 1 (excl) */
 
@@ -267,100 +283,110 @@ static void MakeSingleHouseBigger(TileIn
 

	
 
	if (LiftHasDestination(tile)) return;
 

	
 
	IncHouseConstructionTick(tile);
 
	if (GetHouseConstructionTick(tile) != 0) return;
 

	
 
	IncHouseBuildingStage(tile);  /*increase construction stage of one more step*/
 
	if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) {
 
		uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
		if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res);
 
	}
 

	
 
	if (GetHouseBuildingStage(tile) == TOWN_HOUSE_COMPLETED){
 
		/*Now, construction is completed.  Can add population of building to the town*/
 
		ChangePopulation(GetTownByTile(tile), _housetype_population[GetHouseType(tile)]);
 
	if (IsHouseCompleted(tile)) {
 
		/* Now that construction is complete, we can add the population of the
 
		 * building to the town. */
 
		ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population);
 
	}
 
	MarkTileDirtyByTile(tile);
 
}
 

	
 
static void MakeTownHouseBigger(TileIndex tile)
 
{
 
	uint flags = _house_more_flags[GetHouseType(tile)];
 
	if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
 
	if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
 
	if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
 
	if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
 
	uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags;
 
	if (flags & BUILDING_HAS_1_TILE)  MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0));
 
	if (flags & BUILDING_2_TILES_Y)   MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1));
 
	if (flags & BUILDING_2_TILES_X)   MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0));
 
	if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1));
 
}
 

	
 
static void TileLoop_Town(TileIndex tile)
 
{
 
	int house;
 
	Town *t;
 
	uint32 r;
 
	HouseID house_id = GetHouseType(tile);
 
	HouseSpec *hs = GetHouseSpecs(house_id);
 

	
 
	if (GetHouseBuildingStage(tile) != TOWN_HOUSE_COMPLETED) {
 
	/* NewHouseTileLoop returns false if Callback 21 succeeded, i.e. the house
 
	 * doesn't exist any more, so don't continue here. */
 
	if (house_id >= NEW_HOUSE_OFFSET && !NewHouseTileLoop(tile)) return;
 

	
 
	if (!IsHouseCompleted(tile)) {
 
		/*Construction is not completed. See if we can go further in construction*/
 
		MakeTownHouseBigger(tile);
 
		return;
 
	}
 

	
 
	house = GetHouseType(tile);
 
	if ((_housetype_extra_flags[house] & 0x20) && !LiftHasDestination(tile) && CHANCE16(1, 2) && AddAnimatedTile(tile)) BeginLiftMovement(tile);
 
	/* If the lift has a destination, it is already an animated tile. */
 
	if ((hs->building_flags & BUILDING_IS_ANIMATED) && house_id < NEW_HOUSE_OFFSET && !LiftHasDestination(tile) && CHANCE16(1, 2)) AddAnimatedTile(tile);
 

	
 
	t = GetTownByTile(tile);
 

	
 
	r = Random();
 

	
 
	if (GB(r, 0, 8) < _housetype_population[house]) {
 
	if (GB(r, 0, 8) < hs->population) {
 
		uint amt = GB(r, 0, 8) / 8 + 1;
 
		uint moved;
 

	
 
		if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
 
		t->new_max_pass += amt;
 
		moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt);
 
		t->new_act_pass += moved;
 
	}
 

	
 
	if (GB(r, 8, 8) < _housetype_mailamount[house] ) {
 
	if (GB(r, 8, 8) < hs->mail_generation) {
 
		uint amt = GB(r, 8, 8) / 8 + 1;
 
		uint moved;
 

	
 
		if (_economy.fluct <= 0) amt = (amt + 1) >> 1;
 
		t->new_max_mail += amt;
 
		moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt);
 
		t->new_act_mail += moved;
 
	}
 

	
 
	if (_house_more_flags[house] & 8 && HASBIT(t->flags12, TOWN_IS_FUNDED) && --t->time_until_rebuild == 0) {
 
	_current_player = OWNER_TOWN;
 

	
 
	if (hs->building_flags & BUILDING_HAS_1_TILE && HASBIT(t->flags12, TOWN_IS_FUNDED) && CanDeleteHouse(tile) && --t->time_until_rebuild == 0) {
 
		t->time_until_rebuild = GB(r, 16, 6) + 130;
 

	
 
		_current_player = OWNER_TOWN;
 

	
 
		ClearTownHouse(t, tile);
 

	
 
		// rebuild with another house?
 
		if (GB(r, 24, 8) >= 12) DoBuildTownHouse(t, tile);
 
	}
 

	
 
		_current_player = OWNER_NONE;
 
	}
 
	_current_player = OWNER_NONE;
 
}
 

	
 
static void ClickTile_Town(TileIndex tile)
 
{
 
	/* not used */
 
}
 

	
 
static int32 ClearTile_Town(TileIndex tile, byte flags)
 
{
 
	int house, rating;
 
	int rating;
 
	int32 cost;
 
	Town *t;
 
	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
 
	if (!CanDeleteHouse(tile)) return CMD_ERROR;
 

	
 
	house = GetHouseType(tile);
 
	cost = _price.remove_house * _housetype_remove_cost[house] >> 8;
 
	cost = _price.remove_house * hs->removal_cost >> 8;
 

	
 
	rating = _housetype_remove_ratingmod[house];
 
	rating = hs->remove_rating_decrease;
 
	_cleared_town_rating += rating;
 
	_cleared_town = t = GetTownByTile(tile);
 

	
 
	if (IsValidPlayer(_current_player)) {
 
		if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) {
 
			SetDParam(0, t->index);
 
@@ -375,24 +401,24 @@ static int32 ClearTile_Town(TileIndex ti
 

	
 
	return cost;
 
}
 

	
 
static void GetAcceptedCargo_Town(TileIndex tile, AcceptedCargo ac)
 
{
 
	byte type = GetHouseType(tile);
 
	HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 

	
 
	ac[CT_PASSENGERS] = _housetype_cargo_passengers[type];
 
	ac[CT_MAIL]       = _housetype_cargo_mail[type];
 
	ac[CT_GOODS]      = _housetype_cargo_goods[type];
 
	ac[CT_FOOD]       = _housetype_cargo_food[type];
 
	ac[CT_PASSENGERS] = hs->passenger_acceptance;
 
	ac[CT_MAIL]       = hs->mail_acceptance;
 
	ac[CT_GOODS]      = hs->goods_acceptance;
 
	ac[CT_FOOD]       = hs->food_acceptance;
 
}
 

	
 
static void GetTileDesc_Town(TileIndex tile, TileDesc *td)
 
{
 
	td->str = _town_tile_names[GetHouseType(tile)];
 
	if (GetHouseBuildingStage(tile) != TOWN_HOUSE_COMPLETED) {
 
	td->str = GetHouseSpecs(GetHouseType(tile))->building_name;
 
	if (!IsHouseCompleted(tile)) {
 
		SetDParamX(td->dparam, 0, td->str);
 
		td->str = STR_2058_UNDER_CONSTRUCTION;
 
	}
 

	
 
	td->owner = OWNER_TOWN;
 
}
 
@@ -1183,16 +1209,17 @@ static bool CheckFree2x2Area(TileIndex t
 
}
 

	
 
static void DoBuildTownHouse(Town *t, TileIndex tile)
 
{
 
	int i;
 
	uint bitmask;
 
	int house;
 
	HouseID house;
 
	Slope slope;
 
	uint z;
 
	uint oneof = 0;
 
	HouseSpec *hs;
 

	
 
	// Above snow?
 
	slope = GetTileSlope(tile, &z);
 

	
 
	// Get the town zone type
 
	{
 
@@ -1205,66 +1232,84 @@ static void DoBuildTownHouse(Town *t, Ti
 
	}
 

	
 
	// bits 0-4 are used
 
	// bits 11-15 are used
 
	// bits 5-10 are not used.
 
	{
 
		byte houses[lengthof(_housetype_flags)];
 
		HouseID houses[HOUSE_MAX];
 
		int num = 0;
 
		uint cumulative_probs[HOUSE_MAX];
 
		uint probability_max = 0;
 

	
 
		// Generate a list of all possible houses that can be built.
 
		for (i=0; i!=lengthof(_housetype_flags); i++) {
 
			if ((~_housetype_flags[i] & bitmask) == 0)
 
				houses[num++] = (byte)i;
 
		for (i = 0; i < HOUSE_MAX; i++) {
 
			hs = GetHouseSpecs(i);
 
			if ((~hs->building_availability & bitmask) == 0 && hs->enabled) {
 
				if (_have_newhouses) {
 
					probability_max += hs->probability;
 
					cumulative_probs[num] = probability_max;
 
				}
 
				houses[num++] = (HouseID)i;
 
			}
 
		}
 

	
 
		for (;;) {
 
			house = houses[RandomRange(num)];
 
			if (_have_newhouses) {
 
				uint r = RandomRange(probability_max);
 
				for (i = 0; i < num; i++) if (cumulative_probs[i] >= r) break;
 

	
 
				house = houses[i];
 
			} else {
 
				house = houses[RandomRange(num)];
 
			}
 

	
 
			hs = GetHouseSpecs(house);
 

	
 
			if (_cur_year < _housetype_years[house].min || _cur_year > _housetype_years[house].max)
 
				continue;
 
			if (_have_newhouses) {
 
				if (hs->override != 0) hs = GetHouseSpecs(hs->override);
 

	
 
				if ((hs->extra_flags & BUILDING_IS_HISTORICAL) && !_generating_world) continue;
 

	
 
				if (HASBIT(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) {
 
					uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, house, t, tile);
 
					if (callback_res != CALLBACK_FAILED && callback_res == 0) continue;
 
				}
 
			}
 

	
 
			if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
 

	
 
			// Special houses that there can be only one of.
 
			switch (house) {
 
				case HOUSE_TEMP_CHURCH:
 
				case HOUSE_ARCT_CHURCH:
 
				case HOUSE_SNOW_CHURCH:
 
				case HOUSE_TROP_CHURCH:
 
				case HOUSE_TOY_CHURCH:
 
					SETBIT(oneof, TOWN_HAS_CHURCH);
 
					break;
 
				case HOUSE_STADIUM:
 
				case HOUSE_MODERN_STADIUM:
 
					SETBIT(oneof, TOWN_HAS_STADIUM);
 
					break;
 
				default:
 
					oneof = 0;
 
					break;
 
			if (hs->building_flags & BUILDING_IS_CHURCH) {
 
				SETBIT(oneof, TOWN_HAS_CHURCH);
 
			} else if (hs->building_flags & BUILDING_IS_STADIUM) {
 
				SETBIT(oneof, TOWN_HAS_STADIUM);
 
			} else {
 
				oneof = 0;
 
			}
 

	
 
			if (HASBITS(t->flags12 , oneof)) continue;
 

	
 
			// Make sure there is no slope?
 
			if (_housetype_extra_flags[house] & 0x12 && slope != SLOPE_FLAT) continue;
 
			if (hs->building_flags & TILE_NOT_SLOPED && slope != SLOPE_FLAT) continue;
 

	
 
			if (_housetype_extra_flags[house] & 0x10) {
 
			if (hs->building_flags & TILE_SIZE_2x2) {
 
				if (CheckFree2x2Area(tile) ||
 
						CheckFree2x2Area(tile += TileDiffXY(-1,  0)) ||
 
						CheckFree2x2Area(tile += TileDiffXY( 0, -1)) ||
 
						CheckFree2x2Area(tile += TileDiffXY( 1,  0))) {
 
					break;
 
				}
 
				tile += TileDiffXY(0, 1);
 
			} else if (_housetype_extra_flags[house] & 4) {
 
			} else if (hs->building_flags & TILE_SIZE_2x1) {
 
				if (CheckBuildHouseMode(tile + TileDiffXY(1, 0), slope, 0)) break;
 

	
 
				if (CheckBuildHouseMode(tile + TileDiffXY(-1, 0), slope, 1)) {
 
					tile += TileDiffXY(-1, 0);
 
					break;
 
				}
 
			} else if (_housetype_extra_flags[house] & 8) {
 
			} else if (hs->building_flags & TILE_SIZE_1x2) {
 
				if (CheckBuildHouseMode(tile + TileDiffXY(0, 1), slope, 2)) break;
 

	
 
				if (CheckBuildHouseMode(tile + TileDiffXY(0, -1), slope, 3)) {
 
					tile += TileDiffXY(0, -1);
 
					break;
 
				}
 
@@ -1272,33 +1317,33 @@ static void DoBuildTownHouse(Town *t, Ti
 
				break;
 
			}
 
		}
 
	}
 

	
 
	t->num_houses++;
 
	IncreaseBuildingCount(t, house);
 

	
 
	// Special houses that there can be only one of.
 
	t->flags12 |= oneof;
 

	
 
	{
 
		byte construction_counter = 0, construction_stage = 0, size_flags;
 
		byte construction_counter = 0, construction_stage = 0;
 

	
 
		if (_generating_world) {
 
			uint32 r = Random();
 

	
 
			construction_stage = TOWN_HOUSE_COMPLETED;
 
			if (CHANCE16(1, 7)) construction_stage = GB(r, 0, 2);
 

	
 
			if (construction_stage == TOWN_HOUSE_COMPLETED) {
 
				ChangePopulation(t, _housetype_population[house]);
 
				ChangePopulation(t, hs->population);
 
			} else {
 
				construction_counter = GB(r, 2, 2);
 
			}
 
		}
 
		size_flags = GB(_housetype_extra_flags[house], 2, 3);
 
		MakeTownHouse(tile, t->index, construction_counter, construction_stage, size_flags, house);
 
		MakeTownHouse(tile, t->index, construction_counter, construction_stage, house, VehicleRandomBits());
 
	}
 
}
 

	
 
static bool BuildTownHouse(Town *t, TileIndex tile)
 
{
 
	int32 r;
 
@@ -1318,66 +1363,60 @@ static void DoClearTownHouseHelper(TileI
 
{
 
	assert(IsTileType(tile, MP_HOUSE));
 
	DoClearSquare(tile);
 
	DeleteAnimatedTile(tile);
 
}
 

	
 
static void ClearTownHouse(Town *t, TileIndex tile)
 
void ClearTownHouse(Town *t, TileIndex tile)
 
{
 
	uint house = GetHouseType(tile);
 
	HouseID house = GetHouseType(tile);
 
	uint eflags;
 
	HouseSpec *hs;
 

	
 
	assert(IsTileType(tile, MP_HOUSE));
 

	
 
	// need to align the tile to point to the upper left corner of the house
 
	if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks.
 
		if (_housetype_extra_flags[house-1] & 0x04) {
 
		if (GetHouseSpecs(house-1)->building_flags & TILE_SIZE_2x1) {
 
			house--;
 
			tile += TileDiffXY(-1, 0);
 
		} else if (_housetype_extra_flags[house-1] & 0x18) {
 
		} else if (GetHouseSpecs(house-1)->building_flags & BUILDING_2_TILES_Y) {
 
			house--;
 
			tile += TileDiffXY(0, -1);
 
		} else if (_housetype_extra_flags[house-2] & 0x10) {
 
		} else if (GetHouseSpecs(house-2)->building_flags & BUILDING_HAS_4_TILES) {
 
			house-=2;
 
			tile += TileDiffXY(-1, 0);
 
		} else if (_housetype_extra_flags[house-3] & 0x10) {
 
		} else if (GetHouseSpecs(house-3)->building_flags & BUILDING_HAS_4_TILES) {
 
			house-=3;
 
			tile += TileDiffXY(-1, -1);
 
		}
 
	}
 

	
 
	hs = GetHouseSpecs(house);
 

	
 
	// Remove population from the town if the house is finished.
 
	if (GetHouseBuildingStage(tile) == TOWN_HOUSE_COMPLETED) {
 
		ChangePopulation(t, -_housetype_population[house]);
 
	if (IsHouseCompleted(tile)) {
 
		ChangePopulation(t, -hs->population);
 
	}
 

	
 
	t->num_houses--;
 
	DecreaseBuildingCount(t, house);
 

	
 
	// Clear flags for houses that only may exist once/town.
 
	switch (house) {
 
		case HOUSE_TEMP_CHURCH:
 
		case HOUSE_ARCT_CHURCH:
 
		case HOUSE_SNOW_CHURCH:
 
		case HOUSE_TROP_CHURCH:
 
		case HOUSE_TOY_CHURCH:
 
			CLRBIT(t->flags12, TOWN_HAS_CHURCH);
 
			break;
 
		case HOUSE_STADIUM:
 
		case HOUSE_MODERN_STADIUM:
 
			CLRBIT(t->flags12, TOWN_HAS_STADIUM);
 
			break;
 
		default:
 
			break;
 
	if (hs->building_flags & BUILDING_IS_CHURCH) {
 
		CLRBIT(t->flags12, TOWN_HAS_CHURCH);
 
	} else if (hs->building_flags & BUILDING_IS_STADIUM) {
 
		CLRBIT(t->flags12, TOWN_HAS_STADIUM);
 
	}
 

	
 
	// Do the actual clearing of tiles
 
	eflags = _housetype_extra_flags[house];
 
	eflags = hs->building_flags;
 
	DoClearTownHouseHelper(tile);
 
	if (eflags & 0x14) DoClearTownHouseHelper(tile + TileDiffXY(1, 0));
 
	if (eflags & 0x18) DoClearTownHouseHelper(tile + TileDiffXY(0, 1));
 
	if (eflags & 0x10) DoClearTownHouseHelper(tile + TileDiffXY(1, 1));
 
	if (eflags & BUILDING_2_TILES_X)   DoClearTownHouseHelper(tile + TileDiffXY(1, 0));
 
	if (eflags & BUILDING_2_TILES_Y)   DoClearTownHouseHelper(tile + TileDiffXY(0, 1));
 
	if (eflags & BUILDING_HAS_4_TILES) DoClearTownHouseHelper(tile + TileDiffXY(1, 1));
 
}
 

	
 
/** Rename a town (server-only).
 
 * @param tile unused
 
 * @param p1 town ID to rename
 
 * @param p2 unused
 
@@ -1919,12 +1958,43 @@ static const SaveLoad _town_desc[] = {
 
	// reserve extra space in savegame here. (currently 30 bytes)
 
	SLE_CONDNULL(30, 2, SL_MAX_VERSION),
 

	
 
	SLE_END()
 
};
 

	
 
/* Save and load the mapping between the house id on the map, and the grf file
 
 * it came from. */
 
static const SaveLoad _house_id_mapping_desc[] = {
 
	SLE_VAR(HouseIDMapping, grfid,         SLE_UINT32),
 
	SLE_VAR(HouseIDMapping, house_id,      SLE_UINT8),
 
	SLE_VAR(HouseIDMapping, substitute_id, SLE_UINT8),
 
	SLE_END()
 
};
 

	
 
static void Save_HOUSEIDS()
 
{
 
	uint i;
 

	
 
	for (i = 0; i != lengthof(_house_id_mapping); i++) {
 
		SlSetArrayIndex(i);
 
		SlObject(&_house_id_mapping[i], _house_id_mapping_desc);
 
	}
 
}
 

	
 
static void Load_HOUSEIDS()
 
{
 
	int index;
 

	
 
	ResetHouseIDMapping();
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		if ((uint)index >= lengthof(_house_id_mapping)) break;
 
		SlObject(&_house_id_mapping[index], _house_id_mapping_desc);
 
	}
 
}
 

	
 
static void Save_TOWN()
 
{
 
	Town *t;
 

	
 
	FOR_ALL_TOWNS(t) {
 
		SlSetArrayIndex(t->index);
 
@@ -1963,10 +2033,16 @@ void AfterLoadTown()
 
		UpdateTownRadius(t);
 
		UpdateTownVirtCoord(t);
 
	}
 
	_town_sort_dirty = true;
 
}
 

	
 
extern const ChunkHandler _town_chunk_handlers[] = {
 
	{ 'HIDS', Save_HOUSEIDS, Load_HOUSEIDS, CH_ARRAY },
 
	{ 'CITY', Save_TOWN,     Load_TOWN,     CH_ARRAY | CH_LAST},
 
};
 

	
 
extern const ChunkHandler _town_chunk_handlers[] = {
 
	{ 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST},
 
};
 
void ResetHouses()
 
{
 
	memset(&_house_specs, 0, sizeof(_house_specs));
 
	memcpy(&_house_specs, &_original_house_specs, sizeof(_original_house_specs));
 
}
src/town_map.h
Show inline comments
 
@@ -3,28 +3,36 @@
 
/** @file town_map.h Accessors for towns */
 

	
 
#ifndef TOWN_MAP_H
 
#define TOWN_MAP_H
 

	
 
#include "town.h"
 
#include "date.h"
 

	
 
/**
 
 * Get the index of which town this house/street is attached to.
 
 * @param t the tile
 
 * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET)
 
 * @return TownID
 
 */
 
static inline TownID GetTownIndex(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET)); // XXX incomplete
 
	return _m[t].m2;
 
}
 

	
 
/**
 
 * Set the town index for a road or house tile.
 
 * @param tile the tile
 
 * @param t the tile
 
 * @pre IsTileType(t, MP_HOUSE) or IsTileType(t, MP_STREET)
 
 * @param index the index of the town
 
 * @pre IsTileType(t, MP_STREET) || IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetTownIndex(TileIndex t, TownID index)
 
{
 
	assert(IsTileType(t, MP_STREET) || IsTileType(t, MP_HOUSE));
 
	assert(IsTileType(t, MP_HOUSE) || IsTileType(t, MP_STREET));
 
	_m[t].m2 = index;
 
}
 

	
 
/**
 
 * Gets the town associated with the house or road tile
 
 * @param t the tile to get the town of
 
@@ -32,169 +40,336 @@ static inline void SetTownIndex(TileInde
 
 */
 
static inline Town* GetTownByTile(TileIndex t)
 
{
 
	return GetTown(GetTownIndex(t));
 
}
 

	
 

	
 
static inline int GetHouseType(TileIndex t)
 
/**
 
 * Get the type of this house, which is an index into the house spec array
 
 * Since m4 is only a byte and we want to support 512 houses, we use the bit 6
 
 * of m3 as an additional bit to house type.
 
 * @param t the tile
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return house type
 
 */
 
static inline HouseID GetHouseType(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return _m[t].m4;
 
	return _m[t].m4 | (GB(_m[t].m3, 6, 1) << 8);
 
}
 

	
 
/**
 
 * Set the house type.
 
 * @param t the tile
 
 * @param house_id the new house type
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseType(TileIndex t, HouseID house_id)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	_m[t].m4 = GB(house_id, 0, 8);
 
	SB(_m[t].m3, 6, 1, GB(house_id, 8, 1));
 
}
 

	
 
/**
 
 * Check if the lift of this animated house has a destination
 
 * @param t the tile
 
 * @return has destination
 
 */
 
static inline bool LiftHasDestination(TileIndex t)
 
{
 
	return HASBIT(_m[t].m5, 7);
 
	return HASBIT(_me[t].m7, 0);
 
}
 

	
 
/**
 
 * Set the new destination of the lift for this animated house, and activate
 
 * the LiftHasDestination bit.
 
 * @param t the tile
 
 * @param dest new destination
 
 */
 
static inline void SetLiftDestination(TileIndex t, byte dest)
 
{
 
	SB(_m[t].m5, 0, 6, dest);
 
	SETBIT(_m[t].m1, 7); /* Start moving */
 
	SETBIT(_me[t].m7, 0);
 
	SB(_me[t].m7, 1, 3, dest);
 
}
 

	
 
/**
 
 * Get the current destination for this lift
 
 * @param t the tile
 
 * @return destination
 
 */
 
static inline byte GetLiftDestination(TileIndex t)
 
{
 
	return GB(_m[t].m5, 0, 6);
 
}
 

	
 
static inline bool IsLiftMoving(TileIndex t)
 
{
 
	return HASBIT(_m[t].m1, 7);
 
	return GB(_me[t].m7, 1, 3);
 
}
 

	
 
static inline void BeginLiftMovement(TileIndex t)
 
{
 
	SETBIT(_m[t].m5, 7);
 
}
 

	
 
/**
 
 * Stop the lift of this animated house from moving.
 
 * Clears the first 4 bits of m7 at once, clearing the LiftHasDestination bit
 
 * and the destination.
 
 * @param t the tile
 
 */
 
static inline void HaltLift(TileIndex t)
 
{
 
	CLRBIT(_m[t].m1, 7);
 
	CLRBIT(_m[t].m5, 7);
 
	SB(_m[t].m5, 0, 6, 0);
 

	
 
	SB(_me[t].m7, 0, 4, 0);
 
	DeleteAnimatedTile(t);
 
}
 

	
 
/**
 
 * Get the position of the lift on this animated house
 
 * @param t the tile
 
 * @return position, from 0 to 36
 
 */
 
static inline byte GetLiftPosition(TileIndex t)
 
{
 
	return GB(_m[t].m1, 0, 7);
 
	return GB(_m[t].m6, 2, 6);
 
}
 

	
 
/**
 
 * Set the position of the lift on this animated house
 
 * @param t the tile
 
 * @param pos, from 0 to 36
 
 */
 
static inline void SetLiftPosition(TileIndex t, byte pos)
 
{
 
	SB(_m[t].m6, 2, 6, pos);
 
}
 

	
 
/**
 
 * Get the current animation frame for this house
 
 * @param t the tile
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return frame number
 
 */
 
static inline byte GetHouseAnimationFrame(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return GB(_m[t].m6, 3, 5);
 
}
 

	
 
static inline void SetLiftPosition(TileIndex t, byte pos)
 
/**
 
 * Set a new animation frame for this house
 
 * @param t the tile
 
 * @param frame the new frame number
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseAnimationFrame(TileIndex t, byte frame)
 
{
 
	SB(_m[t].m1, 0, 7, pos);
 
	assert(IsTileType(t, MP_HOUSE));
 
	SB(_m[t].m6, 3, 5, frame);
 
}
 

	
 
/**
 
 * Get the completion of this house
 
 * @param t the tile
 
 * @return true if it is, false if it is not
 
 */
 
static inline bool IsHouseCompleted(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return HASBIT(_m[t].m3, 7);
 
}
 

	
 
static inline void MakeHouseTile(TileIndex t, TownID tid, byte counter, byte stage, byte type)
 
/**
 
 * Mark this house as been completed
 
 * @param t the tile
 
 * @param status
 
 */
 
static inline void SetHouseCompleted(TileIndex t, bool status)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	SB(_m[t].m3, 7, 1, !!status);
 
}
 

	
 
/**
 
 * Make the tile a house.
 
 * @param t tile index
 
 * @param tid Town index
 
 * @param counter of construction step
 
 * @param stage of construction (used for drawing)
 
 * @param type of house.  Index into house specs array
 
 * @param random_bits required for newgrf houses
 
 * @pre IsTileType(t, MP_CLEAR)
 
 */
 
static inline void MakeHouseTile(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
 
{
 
	assert(IsTileType(t, MP_CLEAR));
 

	
 
	SetTileType(t, MP_HOUSE);
 
	_m[t].m1 = 0;
 
	_m[t].m1 = random_bits;
 
	_m[t].m2 = tid;
 
	SB(_m[t].m3, 6, 2, stage);
 
	_m[t].m4 = type;
 
	SB(_m[t].m5, 0, 2, counter);
 
	_m[t].m3 = 0;
 
	SetHouseType(t, type);
 
	SetHouseCompleted(t, stage == TOWN_HOUSE_COMPLETED);
 
	_m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter);
 
	SetHouseAnimationFrame(t, 0);
 
	_me[t].m7 = GetHouseSpecs(type)->processing_time;
 

	
 
	if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(t);
 
	MarkTileDirtyByTile(t);
 
}
 

	
 
enum {
 
	TWO_BY_TWO_BIT = 2, ///< House is two tiles in X and Y directions
 
	ONE_BY_TWO_BIT = 1, ///< House is two tiles in Y direction
 
	TWO_BY_ONE_BIT = 0, ///< House is two tiles in X direction
 
};
 

	
 
static inline void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, byte size, byte type)
 
/**
 
 * Helper function for MakeHouseTile.
 
 * It is called  for each tile of a multi-tile house.
 
 * Parametes are the same.
 
 * @param t tile index
 
 * @param tid Town index
 
 * @param counter of construction step
 
 * @param stage of construction (used for drawing)
 
 * @param type of house.  Index into house specs array
 
 * @param random_bits required for newgrf houses
 
 */
 
static inline void MakeTownHouse(TileIndex t, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
 
{
 
	MakeHouseTile(t, tid, counter, stage, type);
 
	if (HASBIT(size, TWO_BY_TWO_BIT) || HASBIT(size, ONE_BY_TWO_BIT)) MakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type);
 
	if (HASBIT(size, TWO_BY_TWO_BIT) || HASBIT(size, TWO_BY_ONE_BIT)) MakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type);
 
	if (HASBIT(size, TWO_BY_TWO_BIT)) MakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type);
 
	BuildingFlags size = GetHouseSpecs(type)->building_flags;
 
	MakeHouseTile(t, tid, counter, stage, type, random_bits);
 
	if (size & BUILDING_2_TILES_Y)   MakeHouseTile(t + TileDiffXY(0, 1), tid, counter, stage, ++type, random_bits);
 
	if (size & BUILDING_2_TILES_X)   MakeHouseTile(t + TileDiffXY(1, 0), tid, counter, stage, ++type, random_bits);
 
	if (size & BUILDING_HAS_4_TILES) MakeHouseTile(t + TileDiffXY(1, 1), tid, counter, stage, ++type, random_bits);
 
}
 

	
 
/**
 
 * House Construction Scheme.
 
 *  Construction counter, for buildings under construction. Incremented on every
 
 *  periodic tile processing.
 
 *  On wraparound, the stage of building in is increased.
 
 *  (Get|Set|Inc)HouseBuildingStage are taking care of the real stages,
 
 *  GetHouseBuildingStage is taking care of the real stages,
 
 *  (as the sprite for the next phase of house building)
 
 *  (Get|Set|Inc)HouseConstructionTick is simply a tick counter between the
 
 *  (Get|Inc)HouseConstructionTick is simply a tick counter between the
 
 *  different stages
 
 */
 

	
 
/**
 
 * Gets the building stage of a house
 
 * @param tile the tile of the house to get the building stage of
 
 * Since the stage is used for determining what sprite to use,
 
 * if the house is complete (and that stage no longuer is available),
 
 * fool the system by returning the TOWN_HOUSE_COMPLETE (3),
 
 * thus showing a beautiful complete house.
 
 * @param t the tile of the house to get the building stage of
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return the building stage of the house
 
 */
 
static inline byte GetHouseBuildingStage(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return GB(_m[t].m3, 6, 2);
 
}
 

	
 
/**
 
 * Sets the building stage of a house
 
 * @param tile the tile of the house to set the building stage of
 
 * @param stage the new stage
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseBuildingStage(TileIndex t, byte stage)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	SB(_m[t].m3, 6, 2, stage);
 
}
 

	
 
/**
 
 * Increments the building stage of a house
 
 * @param tile the tile of the house to increment the building stage of
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void IncHouseBuildingStage( TileIndex t )
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	AB(_m[t].m3, 6, 2, 1);
 
	return IsHouseCompleted(t) ? (byte)TOWN_HOUSE_COMPLETED : GB(_m[t].m5, 3, 2);
 
}
 

	
 
/**
 
 * Gets the construction stage of a house
 
 * @param tile the tile of the house to get the construction stage of
 
 * @param t the tile of the house to get the construction stage of
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return the construction stage of the house
 
 */
 
static inline byte GetHouseConstructionTick(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return GB(_m[t].m5, 0, 3);
 
}
 

	
 
/**
 
 * Sets the construction stage of a house
 
 * @param tile the tile of the house to set the construction stage of
 
 * @param stage the new stage
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseConstructionTick(TileIndex t, byte stage)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	SB(_m[t].m5, 0, 3, stage);
 
	return IsHouseCompleted(t) ? 0 : GB(_m[t].m5, 0, 3);
 
}
 

	
 
/**
 
 * Sets the increment stage of a house
 
 * @param tile the tile of the house to increment the construction stage of
 
 * It is working with the whole counter + stage 5 bits, making it
 
 * easier to work:  the wraparound is automatic.
 
 * @param t the tile of the house to increment the construction stage of
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void IncHouseConstructionTick(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	AB(_m[t].m5, 0, 3, 1);
 
	AB(_m[t].m5, 0, 5, 1);
 

	
 
	if (GB(_m[t].m5, 3, 2) == TOWN_HOUSE_COMPLETED) {
 
		/* House is now completed.
 
		 * Store the year of construction as well, for newgrf house purpose */
 
		SetHouseCompleted(t, true);
 
		_m[t].m5 = clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF);
 
	}
 
}
 

	
 
/**
 
 * Get the year that this house was constructed (between 1920 and 2175).
 
 * @param t the tile of this house
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return year
 
 */
 
static inline Year GetHouseConstructionYear(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return IsHouseCompleted(t) ? _m[t].m5 + ORIGINAL_BASE_YEAR : 0;
 
}
 

	
 
/**
 
 * Get the random bits for this house.
 
 * This is required for newgrf house
 
 * @param t the tile of this house
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return random bits
 
 */
 
static inline byte GetHouseRandomBits(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return _m[t].m1;
 
}
 

	
 
/**
 
 * Set the activated triggers bits for this house.
 
 * This is required for newgrf house
 
 * @param t the tile of this house
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseTriggers(TileIndex t, byte triggers)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	SB(_m[t].m3, 0, 5, triggers);
 
}
 

	
 
/**
 
 * Get the already activated triggers bits for this house.
 
 * This is required for newgrf house
 
 * @param t the tile of this house
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return triggers
 
 */
 
static inline byte GetHouseTriggers(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return GB(_m[t].m3, 0, 5);
 
}
 

	
 
/**
 
 * Get the amount of time remaining before the tile loop processes this tile.
 
 * @param t the house tile
 
 * @pre IsTileType(t, MP_HOUSE)
 
 * @return time remaining
 
 */
 
static inline byte GetHouseProcessingTime(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	return _me[t].m7;
 
}
 

	
 
/**
 
 * Set the amount of time remaining before the tile loop processes this tile.
 
 * @param t the house tile
 
 * @param time the time to be set
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void SetHouseProcessingTime(TileIndex t, byte time)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	_me[t].m7 = time;
 
}
 

	
 
/**
 
 * Decrease the amount of time remaining before the tile loop processes this tile.
 
 * @param t the house tile
 
 * @pre IsTileType(t, MP_HOUSE)
 
 */
 
static inline void DecHouseProcessingTime(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_HOUSE));
 
	_me[t].m7--;
 
}
 

	
 
#endif /* TOWN_MAP_H */
src/void_map.h
Show inline comments
 
@@ -10,9 +10,10 @@ static inline void MakeVoid(TileIndex t)
 
	_m[t].m1 = 0;
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = 0;
 
	_m[t].m6 = 0;
 
	_me[t].m7 = 0;
 
}
 

	
 
#endif /* VOID_MAP_H */
0 comments (0 inline, 0 general)