1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
|
/* $Id$ */
/** @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 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_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
* @return the town
*/
static inline Town *GetTownByTile(TileIndex t)
{
return GetTown(GetTownIndex(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 | (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(_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)
{
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(_me[t].m7, 1, 3);
}
/**
* 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)
{
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].m6, 2, 6);
}
/**
* Set the position of the lift on this animated house
* @param t the tile
* @param pos position, 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);
}
/**
* 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)
{
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);
}
/**
* 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 = random_bits;
_m[t].m2 = tid;
_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);
}
/**
* 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)
{
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.
* GetHouseBuildingStage is taking care of the real stages,
* (as the sprite for the next phase of house building)
* (Get|Inc)HouseConstructionTick is simply a tick counter between the
* different stages
*/
/**
* Gets the building stage of a house
* 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 IsHouseCompleted(t) ? (byte)TOWN_HOUSE_COMPLETED : GB(_m[t].m5, 3, 2);
}
/**
* Gets the construction stage of a house
* @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 IsHouseCompleted(t) ? 0 : GB(_m[t].m5, 0, 3);
}
/**
* Sets the increment stage of a house
* 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, 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
* @param triggers the activated triggers
* @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 */
|