231 MarkTileDirtyByTile(tile); |
247 MarkTileDirtyByTile(tile); |
232 } |
248 } |
233 |
249 |
234 static void UpdateTownRadius(Town *t); |
250 static void UpdateTownRadius(Town *t); |
235 |
251 |
|
252 /** |
|
253 * Determines if a town is close to a tile |
|
254 * @param tile TileIndex of the tile to query |
|
255 * @param dist maximum distance to be accepted |
|
256 * @returns true if the tile correspond to the distance criteria |
|
257 */ |
236 static bool IsCloseToTown(TileIndex tile, uint dist) |
258 static bool IsCloseToTown(TileIndex tile, uint dist) |
237 { |
259 { |
238 const Town* t; |
260 const Town* t; |
239 |
261 |
240 FOR_ALL_TOWNS(t) { |
262 FOR_ALL_TOWNS(t) { |
241 if (DistanceManhattan(tile, t->xy) < dist) return true; |
263 if (DistanceManhattan(tile, t->xy) < dist) return true; |
242 } |
264 } |
243 return false; |
265 return false; |
244 } |
266 } |
245 |
267 |
|
268 /** |
|
269 * Marks the town sign as needing a repaint |
|
270 * @param t Town requesting repaint |
|
271 */ |
246 static void MarkTownSignDirty(Town *t) |
272 static void MarkTownSignDirty(Town *t) |
247 { |
273 { |
248 MarkAllViewportsDirty( |
274 MarkAllViewportsDirty( |
249 t->sign.left - 6, |
275 t->sign.left - 6, |
250 t->sign.top - 3, |
276 t->sign.top - 3, |
251 t->sign.left + t->sign.width_1 * 4 + 12, |
277 t->sign.left + t->sign.width_1 * 4 + 12, |
252 t->sign.top + 45 |
278 t->sign.top + 45 |
253 ); |
279 ); |
254 } |
280 } |
255 |
281 |
|
282 /** |
|
283 * Resize the sign(label) of the town after changes in |
|
284 * population (creation or growth or else) |
|
285 * @param t Town to update |
|
286 */ |
256 void UpdateTownVirtCoord(Town *t) |
287 void UpdateTownVirtCoord(Town *t) |
257 { |
288 { |
258 Point pt; |
289 Point pt; |
259 |
290 |
260 MarkTownSignDirty(t); |
291 MarkTownSignDirty(t); |
264 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
295 UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, |
265 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
296 _patches.population_in_label ? STR_TOWN_LABEL_POP : STR_TOWN_LABEL); |
266 MarkTownSignDirty(t); |
297 MarkTownSignDirty(t); |
267 } |
298 } |
268 |
299 |
|
300 /** |
|
301 * Change the towns population |
|
302 * @param t Town which polulation has changed |
|
303 * @param mod polulation change (can be positive or negative) |
|
304 */ |
269 static void ChangePopulation(Town *t, int mod) |
305 static void ChangePopulation(Town *t, int mod) |
270 { |
306 { |
271 t->population += mod; |
307 t->population += mod; |
272 InvalidateWindow(WC_TOWN_VIEW, t->index); |
308 InvalidateWindow(WC_TOWN_VIEW, t->index); |
273 UpdateTownVirtCoord(t); |
309 UpdateTownVirtCoord(t); |
274 |
310 |
275 if (_town_sort_order & 2) _town_sort_dirty = true; |
311 if (_town_sort_order & 2) _town_sort_dirty = true; |
276 } |
312 } |
277 |
313 |
|
314 /** |
|
315 * Determines the world population |
|
316 * Basically, count population of all towns, one by one |
|
317 * @return uint32 the calculated population of the world |
|
318 */ |
278 uint32 GetWorldPopulation() |
319 uint32 GetWorldPopulation() |
279 { |
320 { |
280 uint32 pop; |
321 uint32 pop; |
281 const Town* t; |
322 const Town* t; |
282 |
323 |
283 pop = 0; |
324 pop = 0; |
284 FOR_ALL_TOWNS(t) pop += t->population; |
325 FOR_ALL_TOWNS(t) pop += t->population; |
285 return pop; |
326 return pop; |
286 } |
327 } |
287 |
328 |
|
329 /** |
|
330 * Helper function for house completion stages progression |
|
331 * @param tile TileIndex of the house (or parts of it) to "grow" |
|
332 */ |
288 static void MakeSingleHouseBigger(TileIndex tile) |
333 static void MakeSingleHouseBigger(TileIndex tile) |
289 { |
334 { |
290 assert(IsTileType(tile, MP_HOUSE)); |
335 assert(IsTileType(tile, MP_HOUSE)); |
291 |
336 |
|
337 /* means it is completed, get out. */ |
292 if (LiftHasDestination(tile)) return; |
338 if (LiftHasDestination(tile)) return; |
293 |
339 |
|
340 /* progress in construction stages */ |
294 IncHouseConstructionTick(tile); |
341 IncHouseConstructionTick(tile); |
295 if (GetHouseConstructionTick(tile) != 0) return; |
342 if (GetHouseConstructionTick(tile) != 0) return; |
296 |
343 |
|
344 /* Check and/or */ |
297 if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) { |
345 if (HASBIT(GetHouseSpecs(GetHouseType(tile))->callback_mask, CBM_CONSTRUCTION_STATE_CHANGE)) { |
298 uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
346 uint16 callback_res = GetHouseCallback(CBID_CONSTRUCTION_STATE_CHANGE, 0, GetHouseType(tile), GetTownByTile(tile), tile); |
299 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
347 if (callback_res != CALLBACK_FAILED) ChangeHouseAnimationFrame(tile, callback_res); |
300 } |
348 } |
301 |
349 |
305 ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population); |
353 ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population); |
306 } |
354 } |
307 MarkTileDirtyByTile(tile); |
355 MarkTileDirtyByTile(tile); |
308 } |
356 } |
309 |
357 |
|
358 /** Make the house advances in its construction stages until completion |
|
359 * @param tile TileIndex of house |
|
360 */ |
310 static void MakeTownHouseBigger(TileIndex tile) |
361 static void MakeTownHouseBigger(TileIndex tile) |
311 { |
362 { |
312 uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags; |
363 uint flags = GetHouseSpecs(GetHouseType(tile))->building_flags; |
313 if (flags & BUILDING_HAS_1_TILE) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
364 if (flags & BUILDING_HAS_1_TILE) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
314 if (flags & BUILDING_2_TILES_Y) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
365 if (flags & BUILDING_2_TILES_Y) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
315 if (flags & BUILDING_2_TILES_X) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
366 if (flags & BUILDING_2_TILES_X) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
316 if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
367 if (flags & BUILDING_HAS_4_TILES) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
317 } |
368 } |
318 |
369 |
|
370 /** |
|
371 * Periodic tic handler for houses and town |
|
372 * @param tile been asked to do its stuff |
|
373 */ |
319 static void TileLoop_Town(TileIndex tile) |
374 static void TileLoop_Town(TileIndex tile) |
320 { |
375 { |
321 Town *t; |
376 Town *t; |
322 uint32 r; |
377 uint32 r; |
323 HouseID house_id = GetHouseType(tile); |
378 HouseID house_id = GetHouseType(tile); |
332 MakeTownHouseBigger(tile); |
387 MakeTownHouseBigger(tile); |
333 return; |
388 return; |
334 } |
389 } |
335 |
390 |
336 /* If the lift has a destination, it is already an animated tile. */ |
391 /* If the lift has a destination, it is already an animated tile. */ |
337 if ((hs->building_flags & BUILDING_IS_ANIMATED) && house_id < NEW_HOUSE_OFFSET && !LiftHasDestination(tile) && CHANCE16(1, 2)) AddAnimatedTile(tile); |
392 if ((hs->building_flags & BUILDING_IS_ANIMATED) && |
|
393 house_id < NEW_HOUSE_OFFSET && |
|
394 !LiftHasDestination(tile) && |
|
395 CHANCE16(1, 2)) |
|
396 AddAnimatedTile(tile); |
338 |
397 |
339 t = GetTownByTile(tile); |
398 t = GetTownByTile(tile); |
340 |
399 |
341 r = Random(); |
400 r = Random(); |
342 |
401 |
360 t->new_act_mail += moved; |
419 t->new_act_mail += moved; |
361 } |
420 } |
362 |
421 |
363 _current_player = OWNER_TOWN; |
422 _current_player = OWNER_TOWN; |
364 |
423 |
365 if (hs->building_flags & BUILDING_HAS_1_TILE && HASBIT(t->flags12, TOWN_IS_FUNDED) && CanDeleteHouse(tile) && --t->time_until_rebuild == 0) { |
424 if (hs->building_flags & BUILDING_HAS_1_TILE && |
|
425 HASBIT(t->flags12, TOWN_IS_FUNDED) && |
|
426 CanDeleteHouse(tile) && |
|
427 --t->time_until_rebuild == 0) { |
366 t->time_until_rebuild = GB(r, 16, 8) + 192; |
428 t->time_until_rebuild = GB(r, 16, 8) + 192; |
367 |
429 |
368 ClearTownHouse(t, tile); |
430 ClearTownHouse(t, tile); |
369 |
431 |
370 /* Rebuild with another house? */ |
432 /* Rebuild with another house? */ |