author | truelight |
Wed, 15 Dec 2004 22:06:47 +0000 | |
changeset 678 | f62cae2abc0c |
parent 543 | 946badd71033 |
child 679 | 04ca2cd69420 |
permissions | -rw-r--r-- |
0 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
507
04b5403aaf6b
(svn r815) Include strings.h only in the files which need it.
tron
parents:
497
diff
changeset
|
3 |
#include "table/strings.h" |
0 | 4 |
#include "viewport.h" |
5 |
#include "town.h" |
|
6 |
#include "command.h" |
|
7 |
#include "pathfind.h" |
|
8 |
#include "gfx.h" |
|
9 |
#include "industry.h" |
|
10 |
#include "station.h" |
|
11 |
#include "player.h" |
|
12 |
#include "news.h" |
|
13 |
#include "saveload.h" |
|
14 |
#include "economy.h" |
|
15 |
#include "gui.h" |
|
543
946badd71033
(svn r942) -Merged branch/network back into the trunk
truelight
parents:
534
diff
changeset
|
16 |
#include "network.h" |
0 | 17 |
|
483
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
18 |
enum { |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
19 |
TOWN_HAS_CHURCH = 0x02, |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
20 |
TOWN_HAS_STADIUM = 0x04 |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
21 |
}; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
22 |
|
0 | 23 |
// Local |
24 |
static int _grow_town_result; |
|
25 |
||
26 |
static bool BuildTownHouse(Town *t, uint tile); |
|
27 |
static void ClearTownHouse(Town *t, uint tile); |
|
28 |
static void DoBuildTownHouse(Town *t, uint tile); |
|
29 |
||
30 |
typedef struct DrawTownTileStruct { |
|
31 |
uint32 sprite_1; |
|
32 |
uint32 sprite_2; |
|
33 |
||
482 | 34 |
byte subtile_x:4; |
35 |
byte subtile_y:4; |
|
36 |
byte width:4; |
|
37 |
byte height:4; |
|
0 | 38 |
byte dz; |
39 |
byte proc; |
|
40 |
} DrawTownTileStruct; |
|
41 |
||
42 |
#include "table/town_land.h" |
|
43 |
||
44 |
||
45 |
static void TownDrawTileProc1(TileInfo *ti) |
|
46 |
{ |
|
47 |
AddChildSpriteScreen(0x5A3, 0xE, 0x3C - (_map_owner[ti->tile]&0x7F)); |
|
48 |
} |
|
49 |
||
50 |
typedef void TownDrawTileProc(TileInfo *ti); |
|
51 |
static TownDrawTileProc * const _town_draw_tile_procs[1] = { |
|
52 |
TownDrawTileProc1 |
|
53 |
}; |
|
54 |
||
55 |
||
56 |
static void DrawTile_Town(TileInfo *ti) |
|
57 |
{ |
|
58 |
const DrawTownTileStruct *dcts; |
|
59 |
byte z; |
|
60 |
uint32 image; |
|
61 |
||
62 |
/* Retrieve pointer to the draw town tile struct */ |
|
63 |
{ |
|
480
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
64 |
/* this "randomizes" on the (up to) 4 variants of a building */ |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
65 |
byte gfx = _map2[ti->tile]; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
66 |
byte stage = _map3_lo[ti->tile] >> 6; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
67 |
uint variant; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
68 |
variant = ti->x >> 4; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
69 |
variant ^= ti->x >> 6; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
70 |
variant ^= ti->y >> 4; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
71 |
variant -= ti->y >> 6; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
72 |
variant &= 3; |
2e915fd96ac3
(svn r756) Demystify and explain some piece of code regarding which house sprite to draw
tron
parents:
473
diff
changeset
|
73 |
dcts = &_town_draw_tile_data[gfx << 4 | variant << 2 | stage]; |
0 | 74 |
} |
75 |
||
76 |
z = ti->z; |
|
77 |
||
78 |
/* Add bricks below the house? */ |
|
79 |
if (ti->tileh) { |
|
80 |
AddSortableSpriteToDraw(0x3DD + ti->tileh, ti->x, ti->y, 16, 16, 7, z); |
|
81 |
AddChildSpriteScreen(dcts->sprite_1, 0x1F, 1); |
|
82 |
z += 8; |
|
83 |
} else { |
|
84 |
/* Else draw regular ground */ |
|
85 |
DrawGroundSprite(dcts->sprite_1); |
|
86 |
} |
|
87 |
||
88 |
/* Add a house on top of the ground? */ |
|
89 |
if ((image = dcts->sprite_2) != 0) { |
|
497
4d1c889526ee
(svn r787) Invert the sense of the DO_TRANS_BUILDINGS flag to be consistent with its own name and all other DO_* flags.
tron
parents:
483
diff
changeset
|
90 |
if (_display_opt & DO_TRANS_BUILDINGS) |
0 | 91 |
image = (image & 0x3FFF) | 0x3224000; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
92 |
|
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
93 |
AddSortableSpriteToDraw(image, |
482 | 94 |
ti->x + dcts->subtile_x, |
95 |
ti->y + dcts->subtile_y, |
|
96 |
dcts->width + 1, |
|
97 |
dcts->height + 1, |
|
0 | 98 |
dcts->dz, |
99 |
z); |
|
100 |
||
497
4d1c889526ee
(svn r787) Invert the sense of the DO_TRANS_BUILDINGS flag to be consistent with its own name and all other DO_* flags.
tron
parents:
483
diff
changeset
|
101 |
if (_display_opt & DO_TRANS_BUILDINGS) |
0 | 102 |
return; |
103 |
} |
|
104 |
||
105 |
{ |
|
106 |
int proc; |
|
107 |
if ((proc=dcts->proc-1) >= 0 ) |
|
108 |
_town_draw_tile_procs[proc](ti); |
|
109 |
} |
|
110 |
} |
|
111 |
||
112 |
static uint GetSlopeZ_Town(TileInfo *ti) |
|
113 |
{ |
|
114 |
uint z = GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; |
|
115 |
if (ti->tileh != 0) z = (z & ~7) + 4; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
116 |
return (uint16) z; |
0 | 117 |
} |
118 |
||
39 | 119 |
static uint GetSlopeTileh_Town(TileInfo *ti) |
120 |
{ |
|
121 |
return ti->tileh; |
|
122 |
} |
|
123 |
||
0 | 124 |
static void AnimateTile_Town(uint tile) |
125 |
{ |
|
126 |
int old; |
|
127 |
int i; |
|
128 |
int a,b; |
|
129 |
||
130 |
if (_tick_counter & 3) |
|
131 |
return; |
|
132 |
||
133 |
if (_map2[tile] != 4 && _map2[tile] != 5) |
|
134 |
return; |
|
135 |
||
136 |
if (!((old=_map_owner[tile])&0x80)) { |
|
137 |
_map_owner[tile] |= 0x80; |
|
138 |
||
139 |
do { |
|
140 |
i = (Random()&7) - 1; |
|
141 |
} while (i < 0 || i == 1 || i*6==old); |
|
142 |
||
143 |
_map5[tile] = (_map5[tile] & ~0x3F) | i; |
|
144 |
} |
|
145 |
||
146 |
a = _map_owner[tile]&0x7F; |
|
147 |
b = (_map5[tile]&0x3F) * 6; |
|
148 |
a += (a < b) ? 1 : -1; |
|
149 |
_map_owner[tile] = (_map_owner[tile]&0x80)|a; |
|
150 |
||
151 |
if (a == b) { |
|
152 |
_map5[tile] &= 0x40; |
|
153 |
_map_owner[tile] &= 0x7F; |
|
154 |
DeleteAnimatedTile(tile); |
|
155 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
156 |
|
0 | 157 |
MarkTileDirtyByTile(tile); |
158 |
} |
|
159 |
||
160 |
static void UpdateTownRadius(Town *t); |
|
161 |
||
162 |
static bool IsCloseToTown(uint tile, uint dist) |
|
163 |
{ |
|
164 |
Town *t; |
|
165 |
||
166 |
FOR_ALL_TOWNS(t) { |
|
167 |
if (t->xy != 0 && GetTileDist(tile, t->xy) < dist) |
|
168 |
return true; |
|
169 |
} |
|
170 |
return false; |
|
171 |
} |
|
172 |
||
173 |
||
174 |
static void ChangePopulation(Town *t, int mod) |
|
175 |
{ |
|
176 |
t->population += mod; |
|
177 |
InvalidateWindow(WC_TOWN_VIEW, t->index); |
|
178 |
||
179 |
if (_town_sort_order & 2) _town_sort_dirty = true; |
|
180 |
} |
|
181 |
||
182 |
static void MakeSingleHouseBigger(uint tile) |
|
183 |
{ |
|
184 |
byte b; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
185 |
|
0 | 186 |
assert(IS_TILETYPE(tile, MP_HOUSE)); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
187 |
|
0 | 188 |
b = _map5[tile]; |
189 |
if (b & 0x80) |
|
190 |
return; |
|
191 |
||
192 |
_map5[tile] = (b & 0xC0) | ((b+1)&7); |
|
193 |
||
194 |
if ((_map5[tile]&7) != 0) |
|
195 |
return; |
|
196 |
||
197 |
_map3_lo[tile] = _map3_lo[tile] + 0x40; |
|
198 |
||
199 |
if ( (_map3_lo[tile] & 0xC0) == 0xC0) { |
|
200 |
Town *t = ClosestTownFromTile(tile, (uint)-1); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
201 |
ChangePopulation(t, _housetype_population[_map2[tile]]); |
0 | 202 |
} |
203 |
MarkTileDirtyByTile(tile); |
|
204 |
} |
|
205 |
||
206 |
static void MakeTownHouseBigger(uint tile) |
|
207 |
{ |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
208 |
uint flags = _house_more_flags[_map2[tile]]; |
0 | 209 |
if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
210 |
if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
|
211 |
if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
|
212 |
if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
|
213 |
} |
|
214 |
||
215 |
static void TileLoop_Town(uint tile) |
|
216 |
{ |
|
217 |
int house; |
|
218 |
Town *t; |
|
219 |
uint32 r; |
|
220 |
||
221 |
if ((_map3_lo[tile] & 0xC0) != 0xC0) { |
|
222 |
MakeTownHouseBigger(tile); |
|
223 |
return; |
|
224 |
} |
|
225 |
||
226 |
house = _map2[tile]; |
|
227 |
if (_housetype_extra_flags[house] & 0x20 && |
|
228 |
!(_map5[tile] & 0x80) && |
|
229 |
CHANCE16(1,2) && |
|
230 |
AddAnimatedTile(tile)) { |
|
231 |
_map5[tile] = (_map5[tile] & 0x40)|0x80; |
|
232 |
} |
|
233 |
||
234 |
t = ClosestTownFromTile(tile, (uint)-1); |
|
235 |
||
236 |
r = Random(); |
|
237 |
||
238 |
if ( (byte)r < _housetype_population[house] ) { |
|
239 |
uint amt = ((byte)r >> 3) + 1, moved; |
|
240 |
if (_economy.fluct <= 0) amt = (amt + 1) >> 1; |
|
241 |
t->new_max_pass += amt; |
|
242 |
moved = MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt); |
|
243 |
t->new_act_pass += moved; |
|
244 |
} |
|
245 |
||
246 |
if ( (byte)(r>>8) < _housetype_mailamount[house] ) { |
|
247 |
uint amt = ((byte)(r>>8) >> 3) + 1, moved; |
|
248 |
if (_economy.fluct <= 0) amt = (amt + 1) >> 1; |
|
249 |
t->new_max_mail += amt; |
|
250 |
moved = MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt); |
|
251 |
t->new_act_mail += moved; |
|
252 |
} |
|
253 |
||
254 |
if (_house_more_flags[house]&8 && (t->flags12&1) && --t->time_until_rebuild == 0) { |
|
255 |
r>>=16; |
|
256 |
t->time_until_rebuild = (r & 63) + 130; |
|
257 |
||
258 |
_current_player = OWNER_TOWN; |
|
259 |
||
260 |
ClearTownHouse(t, tile); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
261 |
|
0 | 262 |
// rebuild with another house? |
263 |
if ( (byte) (r >> 8) >= 12) { |
|
264 |
DoBuildTownHouse(t, tile); |
|
265 |
} |
|
314 | 266 |
|
267 |
_current_player = OWNER_NONE; |
|
0 | 268 |
} |
269 |
} |
|
270 |
||
271 |
static void ClickTile_Town(uint tile) |
|
272 |
{ |
|
273 |
/* not used */ |
|
274 |
} |
|
275 |
||
276 |
static int32 ClearTile_Town(uint tile, byte flags) |
|
277 |
{ |
|
278 |
int house, rating; |
|
279 |
int32 cost; |
|
280 |
Town *t; |
|
281 |
||
282 |
// safety checks |
|
283 |
if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
|
284 |
if (flags&DC_AUTO && !(flags&DC_AI_BUILDING)) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
|
285 |
||
286 |
house = _map2[tile]; |
|
287 |
cost = _price.remove_house * _housetype_remove_cost[house] >> 8; |
|
288 |
||
289 |
rating = _housetype_remove_ratingmod[house]; |
|
290 |
_cleared_town_rating += rating; |
|
291 |
_cleared_town = t = ClosestTownFromTile(tile, (uint)-1); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
292 |
|
0 | 293 |
if (_current_player < MAX_PLAYERS) { |
294 |
if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
295 |
SetDParam(0, t->index); |
0 | 296 |
return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
297 |
} |
0 | 298 |
} |
299 |
||
300 |
if (flags & DC_EXEC) { |
|
301 |
ChangeTownRating(t, -rating, -1000); |
|
302 |
ClearTownHouse(t, tile); |
|
303 |
} |
|
304 |
||
305 |
return cost; |
|
306 |
} |
|
307 |
||
473
77f0ef57e7cf
(svn r724) Remove restriction that a tile can only accept 3 cargo types.
tron
parents:
470
diff
changeset
|
308 |
static void GetAcceptedCargo_Town(uint tile, AcceptedCargo ac) |
0 | 309 |
{ |
310 |
int type = _map2[tile]; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
311 |
|
473
77f0ef57e7cf
(svn r724) Remove restriction that a tile can only accept 3 cargo types.
tron
parents:
470
diff
changeset
|
312 |
ac[CT_PASSENGERS] = _housetype_cargo_passengers[type]; |
77f0ef57e7cf
(svn r724) Remove restriction that a tile can only accept 3 cargo types.
tron
parents:
470
diff
changeset
|
313 |
ac[CT_MAIL] = _housetype_cargo_mail[type]; |
77f0ef57e7cf
(svn r724) Remove restriction that a tile can only accept 3 cargo types.
tron
parents:
470
diff
changeset
|
314 |
ac[CT_GOODS] = _housetype_cargo_goods[type]; |
77f0ef57e7cf
(svn r724) Remove restriction that a tile can only accept 3 cargo types.
tron
parents:
470
diff
changeset
|
315 |
ac[CT_FOOD] = _housetype_cargo_food[type]; |
0 | 316 |
} |
317 |
||
318 |
static void GetTileDesc_Town(uint tile, TileDesc *td) |
|
319 |
{ |
|
320 |
td->str = _town_tile_names[_map2[tile]]; |
|
321 |
if ((_map3_lo[tile] & 0xC0) != 0xC0) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
322 |
SetDParamX(td->dparam, 0, td->str); |
0 | 323 |
td->str = STR_2058_UNDER_CONSTRUCTION; |
324 |
} |
|
325 |
||
326 |
td->owner = OWNER_TOWN; |
|
327 |
} |
|
328 |
||
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
121
diff
changeset
|
329 |
static uint32 GetTileTrackStatus_Town(uint tile, TransportType mode) |
0 | 330 |
{ |
331 |
/* not used */ |
|
332 |
return 0; |
|
333 |
} |
|
334 |
||
335 |
static void ChangeTileOwner_Town(uint tile, byte old_player, byte new_player) |
|
336 |
{ |
|
337 |
/* not used */ |
|
338 |
} |
|
339 |
||
340 |
||
341 |
static const TileIndexDiff _roadblock_tileadd[4+3] = { |
|
342 |
TILE_XY(0,-1), |
|
343 |
TILE_XY(1,0), |
|
344 |
TILE_XY(0,1), |
|
345 |
TILE_XY(-1,0), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
346 |
|
0 | 347 |
// Store the first 3 elements again. |
348 |
// Lets us rotate without using &3. |
|
349 |
TILE_XY(0,-1), |
|
350 |
TILE_XY(1,0), |
|
351 |
TILE_XY(0,1), |
|
352 |
}; |
|
353 |
||
354 |
static void TownTickHandler(Town *t) |
|
355 |
{ |
|
356 |
if (t->flags12&1) { |
|
357 |
int i = t->grow_counter - 1; |
|
358 |
if (i < 0) { |
|
359 |
if (GrowTown(t)) { |
|
360 |
i = t->growth_rate; |
|
361 |
} else { |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
362 |
i = 0; |
0 | 363 |
} |
364 |
} |
|
365 |
t->grow_counter = i; |
|
366 |
} |
|
367 |
||
368 |
UpdateTownRadius(t); |
|
369 |
} |
|
370 |
||
371 |
void OnTick_Town() |
|
372 |
{ |
|
373 |
uint i; |
|
374 |
Town *t; |
|
375 |
||
376 |
if (_game_mode == GM_EDITOR) |
|
377 |
return; |
|
378 |
||
379 |
i = _cur_town_ctr; |
|
380 |
t = DEREF_TOWN(i); |
|
381 |
if (++i == lengthof(_towns)) i = 0; |
|
382 |
_cur_town_ctr = i; |
|
383 |
||
384 |
if (t->xy != 0) |
|
385 |
TownTickHandler(t); |
|
386 |
||
387 |
} |
|
388 |
||
389 |
static byte GetTownRoadMask(TileIndex tile) |
|
390 |
{ |
|
516
035c53a7da94
(svn r831) Remove station-specific roadbits magic. Tron already fixed road stations so that they don't give out roadbits in r780.
pasky
parents:
515
diff
changeset
|
391 |
byte b = GetRoadBitsByTile(tile); |
0 | 392 |
byte r=0; |
393 |
if (b&1) r|=10; |
|
394 |
if (b&2) r|=5; |
|
395 |
if (b&4) r|=9; |
|
396 |
if (b&8) r|=6; |
|
397 |
if (b&16) r|=3; |
|
398 |
if (b&32) r|=12; |
|
399 |
return r; |
|
400 |
} |
|
401 |
||
402 |
static bool IsRoadAllowedHere(uint tile, int dir) |
|
403 |
{ |
|
404 |
uint k; |
|
405 |
uint slope; |
|
406 |
||
407 |
// If this assertion fails, it might be because the world contains |
|
408 |
// land at the edges. This is not ok. |
|
409 |
TILE_ASSERT(tile); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
410 |
|
0 | 411 |
for(;;) { |
412 |
// Check if there already is a road at this point? |
|
516
035c53a7da94
(svn r831) Remove station-specific roadbits magic. Tron already fixed road stations so that they don't give out roadbits in r780.
pasky
parents:
515
diff
changeset
|
413 |
if (GetRoadBitsByTile(tile) == 0) { |
0 | 414 |
// No, try to build one in the direction. |
415 |
// if that fails clear the land, and if that fails exit. |
|
416 |
// This is to make sure that we can build a road here later. |
|
417 |
if (DoCommandByTile(tile, (dir&1)?0xA:0x5, 0, DC_AUTO, CMD_BUILD_ROAD) == CMD_ERROR && |
|
418 |
DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) |
|
419 |
return false; |
|
420 |
} |
|
421 |
||
422 |
slope = GetTileSlope(tile, NULL); |
|
423 |
if (slope == 0) { |
|
465
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
424 |
no_slope: |
0 | 425 |
// Tile has no slope |
426 |
// Disallow the road if any neighboring tile has a road. |
|
427 |
if (HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1])), dir^2) || |
|
428 |
HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3])), dir^2) || |
|
429 |
HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1] + _roadblock_tileadd[dir+2])), dir) || |
|
430 |
HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3] + _roadblock_tileadd[dir+2])), dir)) |
|
431 |
return false; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
432 |
|
0 | 433 |
// Otherwise allow |
434 |
return true; |
|
435 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
436 |
|
0 | 437 |
// If the tile is not a slope in the right direction, then |
438 |
// maybe terraform some. |
|
439 |
if ((k = (dir&1)?0xC:0x9) != slope && (k^0xF) != slope) { |
|
440 |
uint32 r = Random(); |
|
441 |
||
442 |
if (CHANCE16I(1,8, r) && !_generating_world) { |
|
465
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
443 |
int32 res; |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
444 |
|
0 | 445 |
if (CHANCE16I(1,16,r)) |
465
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
446 |
res = DoCommandByTile(tile, slope, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
447 |
CMD_TERRAFORM_LAND); |
0 | 448 |
else |
465
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
449 |
res = DoCommandByTile(tile, slope^0xF, 1, DC_EXEC | DC_AUTO | DC_NO_WATER, |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
450 |
CMD_TERRAFORM_LAND); |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
451 |
if (res == CMD_ERROR && CHANCE16I(1,3,r)) |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
452 |
// We can consider building on the slope, though. |
21f9985e12d1
(svn r694) Make the town sometimes build streets on slopes.
pasky
parents:
314
diff
changeset
|
453 |
goto no_slope; |
0 | 454 |
} |
455 |
return false; |
|
456 |
} |
|
457 |
||
458 |
tile = TILE_ADD(tile, _roadblock_tileadd[dir]); |
|
459 |
} |
|
460 |
} |
|
461 |
||
462 |
static bool TerraformTownTile(uint tile, int edges, int dir) |
|
463 |
{ |
|
464 |
int32 r; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
465 |
|
0 | 466 |
TILE_ASSERT(tile); |
467 |
||
468 |
r = DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); |
|
469 |
if (r == CMD_ERROR || r >= 126*16) |
|
470 |
return false; |
|
471 |
DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_TERRAFORM_LAND); |
|
472 |
return true; |
|
473 |
} |
|
474 |
||
475 |
static void LevelTownLand(uint tile) |
|
476 |
{ |
|
477 |
TileInfo ti; |
|
478 |
||
479 |
TILE_ASSERT(tile); |
|
480 |
||
481 |
// Don't terraform if land is plain or if there's a house there. |
|
482 |
FindLandscapeHeightByTile(&ti, tile); |
|
483 |
if (ti.tileh == 0 || ti.type == MP_HOUSE) |
|
484 |
return; |
|
485 |
||
486 |
// First try up, then down |
|
487 |
if (!TerraformTownTile(tile, ~ti.tileh & 0xF, 1)) { |
|
488 |
TerraformTownTile(tile, ti.tileh & 0xF, 0); |
|
489 |
} |
|
490 |
} |
|
491 |
||
492 |
#define IS_WATER_TILE(t) (IS_TILETYPE((t), MP_WATER) && _map5[(t)] == 0) |
|
493 |
||
494 |
static void GrowTownInTile(uint *tile_ptr, uint mask, int block, Town *t1) |
|
495 |
{ |
|
496 |
Town *t2; |
|
497 |
uint16 r; |
|
498 |
int a,b,rcmd; |
|
499 |
uint tmptile; |
|
500 |
TileInfo ti; |
|
501 |
int i; |
|
502 |
int j; |
|
503 |
uint tile = *tile_ptr; |
|
504 |
||
505 |
TILE_ASSERT(tile); |
|
506 |
||
507 |
if (mask == 0) { |
|
508 |
// Tile has no road. First reset the status counter |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
509 |
// to say that this is the last iteration. |
0 | 510 |
_grow_town_result = 0; |
511 |
||
512 |
// Then check if the tile we are at belongs to the town, |
|
513 |
// if not, bail out. |
|
514 |
t2 = ClosestTownFromTile(tile, (uint)-1); |
|
515 |
if (t2 != t1) |
|
516 |
return; |
|
517 |
||
518 |
// Remove hills etc |
|
519 |
LevelTownLand(tile); |
|
520 |
||
521 |
// Is a road allowed here? |
|
522 |
if (!IsRoadAllowedHere(tile, block)) |
|
523 |
return; |
|
524 |
||
525 |
// Randomize new road block numbers |
|
526 |
a = block; |
|
527 |
b = block ^ 2; |
|
528 |
r = (uint16)Random(); |
|
529 |
if (r <= 0x4000) do { |
|
530 |
a = (int)Random() & 3; |
|
531 |
} while(a == b); |
|
532 |
||
533 |
if (!IsRoadAllowedHere(TILE_ADD(tile,_roadblock_tileadd[a]), a)) { |
|
534 |
// A road is not allowed to continue the randomized road, |
|
535 |
// return if the road we're trying to build is curved. |
|
536 |
if ( a != (b^2)) |
|
537 |
return; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
538 |
|
0 | 539 |
// Return if neither side of the new road is a house |
540 |
if (!IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+1]), MP_HOUSE) && |
|
541 |
!IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+3]), MP_HOUSE)) |
|
542 |
return; |
|
543 |
||
544 |
// That means that the road is only allowed if there is a house |
|
545 |
// at any side of the new road. |
|
546 |
} |
|
547 |
rcmd = (1 << a) + (1 << b); |
|
548 |
||
549 |
} else if (block < 5 && !HASBIT(mask,block^2)) { |
|
550 |
// Continue building on a partial road. |
|
551 |
// Always OK. |
|
552 |
_grow_town_result = 0; |
|
553 |
rcmd = 1 << (block^2); |
|
554 |
} else { |
|
555 |
||
556 |
// Reached a tunnel? Then continue at the other side of it. |
|
557 |
if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile]&~3)==4) { |
|
159
139cf78bfb28
(svn r160) -Codechange: made GetTileTrackStatus more readable (blathijs)
truelight
parents:
121
diff
changeset
|
558 |
FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, _map5[tile]&3); |
0 | 559 |
*tile_ptr = flotr.tile; |
560 |
return; |
|
561 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
562 |
|
0 | 563 |
// For any other kind of tunnel/bridge, bail out. |
564 |
if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) |
|
565 |
return; |
|
566 |
||
567 |
// Possibly extend the road in a direction. |
|
568 |
// Randomize a direction and if it has a road, bail out. |
|
569 |
i = (int)Random() & 3; |
|
570 |
if (HASBIT(mask, i)) |
|
571 |
return; |
|
572 |
||
573 |
// This is the tile we will reach if we extend to this direction. |
|
574 |
tmptile = TILE_ADD(tile,_roadblock_tileadd[i]); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
575 |
|
0 | 576 |
// Don't do it if it reaches to water. |
577 |
if (IS_WATER_TILE(tmptile)) |
|
578 |
return; |
|
579 |
||
580 |
// If the new tile belongs to another town, |
|
581 |
// then stop the search altogether. |
|
582 |
if (ClosestTownFromTile(tmptile, (uint)-1) != t1) { |
|
583 |
_grow_town_result = 0; |
|
584 |
return; |
|
585 |
} |
|
586 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
587 |
// Build a house at the edge. 60% chance or |
0 | 588 |
// always ok if no road allowed. |
589 |
if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6,10)) { |
|
590 |
// But not if there already is a house there. |
|
591 |
if (!IS_TILETYPE(tmptile, MP_HOUSE)) { |
|
592 |
// Level the land if possible |
|
593 |
LevelTownLand(tmptile); |
|
594 |
||
595 |
// And build a house. |
|
596 |
// Set result to -1 if we managed to build it. |
|
597 |
if (BuildTownHouse(t1, tmptile)) |
|
598 |
_grow_town_result = -1; |
|
599 |
} |
|
600 |
return; |
|
601 |
} |
|
602 |
||
603 |
_grow_town_result = 0; |
|
604 |
rcmd = 1 << i; |
|
605 |
} |
|
606 |
||
607 |
FindLandscapeHeightByTile(&ti, tile); |
|
608 |
||
609 |
// Return if a water tile |
|
610 |
if (ti.type == MP_WATER && ti.map5==0) |
|
611 |
return; |
|
612 |
||
613 |
// Determine direction of slope, |
|
614 |
// and build a road if not a special slope. |
|
615 |
if ((i=0,ti.tileh != 3) && |
|
616 |
(i++,ti.tileh != 9) && |
|
617 |
(i++,ti.tileh != 12) && |
|
618 |
(i++,ti.tileh != 6)) { |
|
619 |
build_road_and_exit: |
|
620 |
if (DoCommandByTile(tile, rcmd, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD) != CMD_ERROR) |
|
621 |
_grow_town_result = -1; |
|
622 |
return; |
|
623 |
} |
|
624 |
||
625 |
tmptile = tile; |
|
626 |
||
627 |
// Now it contains the direction of the slope |
|
628 |
j = -11; // max 11 tile long bridges |
|
629 |
do { |
|
630 |
if (++j == 0) |
|
631 |
goto build_road_and_exit; |
|
632 |
tmptile = TILE_MASK(tmptile + _tileoffs_by_dir[i]); |
|
633 |
} while (IS_WATER_TILE(tmptile)); |
|
634 |
||
635 |
// no water tiles in between? |
|
636 |
if (j == -10) |
|
637 |
goto build_road_and_exit; |
|
638 |
||
639 |
// Quit if it selecting an appropiate bridge type fails a large number of times. |
|
640 |
j = 22; |
|
641 |
{ |
|
642 |
int32 bridge_len = GetBridgeLength(tile, tmptile); |
|
643 |
do { |
|
644 |
byte bridge_type = RandomRange(MAX_BRIDGES - 1); |
|
645 |
if (CheckBridge_Stuff(bridge_type, bridge_len)) { |
|
646 |
if (DoCommandByTile(tile, tmptile, 0x8000 + bridge_type, DC_EXEC | DC_AUTO, CMD_BUILD_BRIDGE) != CMD_ERROR) |
|
647 |
_grow_town_result = -1; |
|
648 |
||
649 |
// obviously, if building any bridge would fail, there is no need to try other bridge-types |
|
650 |
return; |
|
651 |
} |
|
652 |
} while(--j != 0); |
|
653 |
} |
|
654 |
} |
|
655 |
#undef IS_WATER_TILE |
|
656 |
||
657 |
||
658 |
// Returns true if a house was built, or no if the build failed. |
|
659 |
static int GrowTownAtRoad(Town *t, uint tile) |
|
660 |
{ |
|
661 |
uint mask; |
|
662 |
int block = 5; // special case |
|
663 |
||
664 |
TILE_ASSERT(tile); |
|
665 |
||
666 |
// Number of times to search. |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
667 |
_grow_town_result = 10 + t->num_houses * 4 / 9; |
0 | 668 |
|
669 |
do { |
|
670 |
// Get a bitmask of the road blocks on a tile |
|
671 |
mask = GetTownRoadMask(tile); |
|
672 |
||
673 |
// Try to grow the town from this point |
|
674 |
GrowTownInTile(&tile,mask,block,t); |
|
675 |
||
676 |
// Exclude the source position from the bitmask |
|
677 |
// and return if no more road blocks available |
|
678 |
CLRBIT(mask, (block ^ 2)); |
|
679 |
if (mask == 0) |
|
680 |
return _grow_town_result; |
|
681 |
||
682 |
// Select a random bit from the blockmask, walk a step |
|
683 |
// and continue the search from there. |
|
684 |
do block = Random() & 3; while (!HASBIT(mask,block)); |
|
685 |
tile += _roadblock_tileadd[block]; |
|
686 |
||
687 |
// Max number of times is checked. |
|
688 |
} while (--_grow_town_result >= 0); |
|
689 |
||
690 |
return (_grow_town_result == -2); |
|
691 |
} |
|
692 |
||
693 |
// Generate a random road block |
|
694 |
// The probability of a straight road |
|
695 |
// is somewhat higher than a curved. |
|
696 |
static int GenRandomRoadBits() |
|
697 |
{ |
|
698 |
uint32 r = Random(); |
|
699 |
int a = r&3, b = (r >> 8) & 3; |
|
700 |
if (a == b) b ^= 2; |
|
701 |
return (1<<a)+(1<<b); |
|
702 |
} |
|
703 |
||
704 |
// Grow the town |
|
705 |
// Returns true if a house was built, or no if the build failed. |
|
706 |
bool GrowTown(Town *t) |
|
707 |
{ |
|
708 |
uint tile; |
|
709 |
const TileIndexDiff *ptr; |
|
710 |
int offs; |
|
711 |
TileInfo ti; |
|
260
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
712 |
byte old_player; |
0 | 713 |
|
714 |
static const TileIndexDiff _town_coord_mod[] = { |
|
715 |
TILE_XY(-1,0), |
|
716 |
TILE_XY(1,1), |
|
717 |
TILE_XY(1,-1), |
|
718 |
TILE_XY(-1,-1), |
|
719 |
TILE_XY(-1,0), |
|
720 |
TILE_XY(0,2), |
|
721 |
TILE_XY(2,0), |
|
722 |
TILE_XY(0,-2), |
|
723 |
TILE_XY(-1,-1), |
|
724 |
TILE_XY(-2,2), |
|
725 |
TILE_XY(2,2), |
|
726 |
TILE_XY(2,-2), |
|
727 |
0, |
|
728 |
}; |
|
729 |
||
730 |
// Current player is a town |
|
260
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
731 |
old_player = _current_player; |
0 | 732 |
_current_player = OWNER_TOWN; |
733 |
||
734 |
// Find a road that we can base the construction on. |
|
735 |
tile = t->xy; |
|
736 |
ptr = _town_coord_mod; |
|
737 |
do { |
|
516
035c53a7da94
(svn r831) Remove station-specific roadbits magic. Tron already fixed road stations so that they don't give out roadbits in r780.
pasky
parents:
515
diff
changeset
|
738 |
if (GetRoadBitsByTile(tile) != 0) { |
260
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
739 |
int r = GrowTownAtRoad(t, tile); |
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
740 |
_current_player = old_player; |
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
741 |
return r; |
0 | 742 |
} |
743 |
offs = *ptr++; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
744 |
|
0 | 745 |
tile = TILE_ADD(tile, offs); |
746 |
} while (offs); |
|
747 |
||
748 |
// No road available, try to build a random road block by |
|
749 |
// clearing some land and then building a road there. |
|
750 |
tile = t->xy; |
|
751 |
ptr = _town_coord_mod; |
|
752 |
do { |
|
753 |
FindLandscapeHeightByTile(&ti, tile); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
754 |
|
0 | 755 |
// Only work with plain land that not already has a house with map5=0 |
756 |
if (ti.tileh == 0 && !(ti.type==MP_HOUSE && ti.map5==0)) { |
|
757 |
if (DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) { |
|
758 |
DoCommandByTile(tile, GenRandomRoadBits(), 0, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); |
|
260
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
759 |
_current_player = old_player; |
0 | 760 |
return true; |
761 |
} |
|
762 |
} |
|
763 |
offs = *ptr++; |
|
764 |
tile = TILE_ADD(tile, offs); |
|
765 |
} while (offs != 0); |
|
766 |
||
260
4819bcce8389
(svn r266) -Fix: hopefully fixed the desync problem nicely (and reverted the
truelight
parents:
193
diff
changeset
|
767 |
_current_player = old_player; |
0 | 768 |
return false; |
769 |
} |
|
770 |
||
771 |
static void UpdateTownRadius(Town *t) |
|
772 |
{ |
|
773 |
static const uint16 _town_radius_data[23][5] = { |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
774 |
{ 4, 0, 0, 0, 0}, // 0 |
0 | 775 |
{16, 0, 0, 0, 0}, |
776 |
{25, 0, 0, 0, 0}, |
|
777 |
{36, 0, 0, 0, 0}, |
|
778 |
{49, 0, 4, 0, 0}, |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
779 |
{64, 0, 4, 0, 0}, // 20 |
0 | 780 |
{64, 0, 9, 0, 1}, |
781 |
{64, 0, 9, 0, 4}, |
|
782 |
{64, 0, 16, 0, 4}, |
|
783 |
{81, 0, 16, 0, 4}, |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
784 |
{81, 0, 16, 0, 4}, // 40 |
0 | 785 |
{81, 0, 25, 0, 9}, |
786 |
{81, 36, 25, 0, 9}, |
|
787 |
{81, 36, 25, 16, 9}, |
|
788 |
{81, 49, 0, 25, 9}, |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
789 |
{81, 64, 0, 25, 9}, // 60 |
0 | 790 |
{81, 64, 0, 36, 9}, |
791 |
{81, 64, 0, 36, 16}, |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
792 |
{100, 81, 0, 49, 16}, |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
793 |
{100, 81, 0, 49, 25}, |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
794 |
{121, 81, 0, 49, 25}, // 80 |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
795 |
{121, 81, 0, 49, 25}, |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
796 |
{121, 81, 0, 49, 36}, // 88 |
0 | 797 |
}; |
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
798 |
|
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
799 |
if (t->num_houses < 92) { |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
800 |
memcpy(t->radius, _town_radius_data[t->num_houses / 4], sizeof(t->radius)); |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
801 |
} else { |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
802 |
int mass = t->num_houses / 8; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
803 |
// At least very roughly extrapolate. Empirical numbers dancing between |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
804 |
// overwhelming by cottages and skyscrapers outskirts. |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
805 |
t->radius[0] = mass * mass; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
806 |
// Actually we are proportional to sqrt() but that's right because |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
807 |
// we are covering an area. |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
808 |
t->radius[1] = mass * 7; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
809 |
t->radius[2] = 0; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
810 |
t->radius[3] = mass * 4; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
811 |
t->radius[4] = mass * 3; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
812 |
//debug("%d (->%d): %d %d %d %d\n", t->num_houses, mass, t->radius[0], t->radius[1], t->radius[3], t->radius[4]); |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
813 |
} |
0 | 814 |
} |
815 |
||
816 |
static void UpdateTownVirtCoord(Town *t) |
|
817 |
{ |
|
818 |
Point pt = RemapCoords2(GET_TILE_X(t->xy)*16, GET_TILE_Y(t->xy)*16); |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
819 |
SetDParam(0, t->townnameparts); |
0 | 820 |
UpdateViewportSignPos(&t->sign, pt.x, pt.y - 24, t->townnametype); |
821 |
} |
|
822 |
||
823 |
static void CreateTownName(Town *t1) |
|
824 |
{ |
|
825 |
Town *t2; |
|
826 |
char buf1[64]; |
|
827 |
char buf2[64]; |
|
828 |
uint32 r; |
|
829 |
||
830 |
t1->townnametype = SPECSTR_TOWNNAME_START + _opt.town_name; |
|
831 |
||
832 |
for(;;) { |
|
833 |
restart: |
|
834 |
r = Random(); |
|
835 |
||
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
836 |
SetDParam(0, r); |
0 | 837 |
GetString(buf1, t1->townnametype); |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
838 |
|
0 | 839 |
// Check size and width |
840 |
if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130) |
|
841 |
continue; |
|
842 |
||
843 |
FOR_ALL_TOWNS(t2) { |
|
844 |
if (t2->xy != 0) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
845 |
SetDParam(0, t2->townnameparts); |
0 | 846 |
GetString(buf2, t2->townnametype); |
847 |
if (str_eq(buf1, buf2)) |
|
848 |
goto restart; |
|
849 |
} |
|
850 |
} |
|
851 |
t1->townnameparts = r; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
852 |
|
0 | 853 |
return; |
854 |
} |
|
855 |
} |
|
856 |
||
857 |
static void UpdateTownMaxPass(Town *t) |
|
858 |
{ |
|
859 |
t->max_pass = t->population >> 3; |
|
860 |
t->max_mail = t->population >> 4; |
|
861 |
} |
|
862 |
||
863 |
static void DoCreateTown(Town *t, TileIndex tile) |
|
864 |
{ |
|
865 |
int x, i; |
|
866 |
||
867 |
// clear the town struct |
|
868 |
i = t->index; |
|
869 |
memset(t, 0, sizeof(Town)); |
|
870 |
t->index = i; |
|
871 |
||
872 |
t->xy = tile; |
|
873 |
t->num_houses = 0; |
|
874 |
t->time_until_rebuild = 10; |
|
875 |
UpdateTownRadius(t); |
|
876 |
t->flags12 = 0; |
|
877 |
t->population = 0; |
|
878 |
t->grow_counter = 0; |
|
879 |
t->growth_rate = 250; |
|
880 |
t->new_max_pass = 0; |
|
881 |
t->new_max_mail = 0; |
|
882 |
t->new_act_pass = 0; |
|
883 |
t->new_act_mail = 0; |
|
884 |
t->max_pass = 0; |
|
885 |
t->max_mail = 0; |
|
886 |
t->act_pass = 0; |
|
887 |
t->act_mail = 0; |
|
888 |
||
889 |
t->pct_pass_transported = 0; |
|
890 |
t->pct_mail_transported = 0; |
|
891 |
t->fund_buildings_months = 0; |
|
892 |
t->new_act_food = 0; |
|
4
cad62d5f9708
(svn r5) -Fix: townname generation of TTDLX savegames. All work
darkvater
parents:
0
diff
changeset
|
893 |
t->new_act_water = 0; |
0 | 894 |
t->act_food = 0; |
4
cad62d5f9708
(svn r5) -Fix: townname generation of TTDLX savegames. All work
darkvater
parents:
0
diff
changeset
|
895 |
t->act_water = 0; |
0 | 896 |
|
897 |
for(i = 0; i != MAX_PLAYERS; i++) |
|
898 |
t->ratings[i] = 500; |
|
899 |
||
900 |
t->have_ratings = 0; |
|
121
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
901 |
t->exclusivity = (byte)-1; |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
902 |
t->exclusive_counter = 0; |
0 | 903 |
t->statues = 0; |
904 |
||
905 |
CreateTownName(t); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
906 |
|
0 | 907 |
UpdateTownVirtCoord(t); |
908 |
_town_sort_dirty = true; |
|
909 |
||
910 |
x = (Random() & 0xF) + 8; |
|
911 |
if (_game_mode == GM_EDITOR) |
|
912 |
x = _new_town_size * 16 + 3; |
|
913 |
||
914 |
t->num_houses += x; |
|
915 |
UpdateTownRadius(t); |
|
916 |
||
917 |
i = x * 4; |
|
918 |
do { |
|
919 |
GrowTown(t); |
|
920 |
} while (--i); |
|
921 |
||
922 |
t->num_houses -= x; |
|
923 |
UpdateTownRadius(t); |
|
924 |
UpdateTownMaxPass(t); |
|
925 |
} |
|
926 |
||
927 |
static Town *AllocateTown() |
|
928 |
{ |
|
929 |
Town *t; |
|
930 |
FOR_ALL_TOWNS(t) { |
|
931 |
if (t->xy == 0) { |
|
543
946badd71033
(svn r942) -Merged branch/network back into the trunk
truelight
parents:
534
diff
changeset
|
932 |
if (t->index > _total_towns) _total_towns = t->index; |
0 | 933 |
return t; |
934 |
} |
|
935 |
} |
|
936 |
return NULL; |
|
937 |
} |
|
938 |
||
939 |
int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
940 |
{ |
|
941 |
uint tile = TILE_FROM_XY(x,y); |
|
942 |
TileInfo ti; |
|
943 |
Town *t; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
944 |
|
0 | 945 |
SET_EXPENSES_TYPE(EXPENSES_OTHER); |
946 |
||
947 |
// Check if too close to the edge of map |
|
948 |
if (!CheckDistanceFromEdge(tile, 12)) |
|
949 |
return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); |
|
950 |
||
951 |
// Can only build on clear flat areas. |
|
952 |
FindLandscapeHeightByTile(&ti, tile); |
|
953 |
if (ti.type != MP_CLEAR || ti.tileh != 0) |
|
954 |
return_cmd_error(STR_0239_SITE_UNSUITABLE); |
|
955 |
||
956 |
// Check distance to all other towns. |
|
957 |
if (IsCloseToTown(tile, 20)) |
|
958 |
return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN); |
|
959 |
||
960 |
// Allocate town struct |
|
961 |
t = AllocateTown(); |
|
962 |
if (t == NULL) |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
963 |
return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
0 | 964 |
|
965 |
// Create the town |
|
966 |
if (flags & DC_EXEC) { |
|
967 |
_generating_world = true; |
|
968 |
DoCreateTown(t, tile); |
|
969 |
_generating_world = false; |
|
970 |
} |
|
971 |
return 0; |
|
972 |
} |
|
973 |
||
974 |
Town *CreateRandomTown() |
|
975 |
{ |
|
976 |
uint tile; |
|
977 |
TileInfo ti; |
|
978 |
Town *t; |
|
979 |
int n; |
|
980 |
||
981 |
// Try 20 times. |
|
982 |
n = 20; |
|
983 |
do { |
|
984 |
// Generate a tile index not too close from the edge |
|
985 |
tile = TILE_MASK(Random()); |
|
986 |
if (!CheckDistanceFromEdge(tile, 20)) |
|
987 |
continue; |
|
988 |
||
989 |
// Make sure the tile is plain |
|
990 |
FindLandscapeHeightByTile(&ti, tile); |
|
991 |
if (ti.type != MP_CLEAR || ti.tileh != 0) |
|
992 |
continue; |
|
993 |
||
994 |
// Check not too close to a town |
|
995 |
if (IsCloseToTown(tile, 20)) |
|
996 |
continue; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
997 |
|
0 | 998 |
// Allocate a town struct |
999 |
t = AllocateTown(); |
|
1000 |
if (t == NULL) |
|
1001 |
break; |
|
1002 |
||
1003 |
DoCreateTown(t, tile); |
|
1004 |
return t; |
|
1005 |
} while (--n); |
|
1006 |
return NULL; |
|
1007 |
} |
|
1008 |
||
1009 |
static const byte _num_initial_towns[3] = { |
|
1010 |
11, 23, 46 |
|
1011 |
}; |
|
1012 |
||
1013 |
void GenerateTowns() |
|
1014 |
{ |
|
1015 |
uint n; |
|
1016 |
n = _num_initial_towns[_opt.diff.number_towns] + (Random()&7); |
|
1017 |
do CreateRandomTown(); while (--n); |
|
1018 |
} |
|
1019 |
||
1020 |
static bool CheckBuildHouseMode(Town *t1, uint tile, uint tileh, int mode) { |
|
1021 |
Town *t2 = ClosestTownFromTile(tile, (uint)-1); |
|
1022 |
int b; |
|
1023 |
uint slope; |
|
1024 |
||
1025 |
static const byte _masks[8] = { |
|
1026 |
0xC,0x3,0x9,0x6, |
|
1027 |
0x3,0xC,0x6,0x9, |
|
1028 |
}; |
|
1029 |
||
1030 |
if (t2 != t1) |
|
1031 |
return false; |
|
1032 |
||
1033 |
slope = GetTileSlope(tile, NULL); |
|
1034 |
if (slope & 0x10) |
|
1035 |
return false; |
|
1036 |
||
1037 |
b = 0; |
|
1038 |
if ((slope & 0xF && ~slope & _masks[mode])) b = ~b; |
|
1039 |
if ((tileh & 0xF && ~tileh & _masks[mode+4])) b = ~b; |
|
1040 |
if (b) |
|
1041 |
return false; |
|
1042 |
||
1043 |
return DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR) != CMD_ERROR; |
|
1044 |
} |
|
1045 |
||
1046 |
int GetTownRadiusGroup(Town *t, uint tile) |
|
1047 |
{ |
|
1048 |
uint dist; |
|
1049 |
int i,smallest; |
|
1050 |
||
1051 |
dist = GetTileDistAdv(tile, t->xy); |
|
1052 |
if (t->fund_buildings_months && dist <= 25) |
|
1053 |
return 4; |
|
1054 |
||
1055 |
smallest = 0; |
|
1056 |
for(i=0; i!=lengthof(t->radius); i++) { |
|
1057 |
if (dist < t->radius[i]) |
|
1058 |
smallest = i; |
|
1059 |
} |
|
1060 |
||
1061 |
return smallest; |
|
1062 |
} |
|
1063 |
||
1064 |
static bool CheckFree2x2Area(Town *t1, uint tile) |
|
1065 |
{ |
|
1066 |
Town *t; |
|
1067 |
int i; |
|
1068 |
||
1069 |
static const TileIndexDiff _tile_add[4] = { |
|
1070 |
TILE_XY(0,0), |
|
1071 |
TILE_XY(0,1) - TILE_XY(0,0), |
|
1072 |
TILE_XY(1,0) - TILE_XY(0,1), |
|
1073 |
TILE_XY(1,1) - TILE_XY(1,0), |
|
1074 |
}; |
|
1075 |
||
1076 |
for(i=0; i!=4; i++) { |
|
1077 |
tile += _tile_add[i]; |
|
1078 |
||
1079 |
t = ClosestTownFromTile(tile, (uint)-1); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1080 |
if (t1 != t) |
0 | 1081 |
return false; |
1082 |
||
1083 |
if (GetTileSlope(tile, NULL)) |
|
1084 |
return false; |
|
1085 |
||
1086 |
if (DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_FORCETEST, CMD_LANDSCAPE_CLEAR) == CMD_ERROR) |
|
1087 |
return false; |
|
1088 |
} |
|
1089 |
||
1090 |
return true; |
|
1091 |
} |
|
1092 |
||
1093 |
static void DoBuildTownHouse(Town *t, uint tile) |
|
1094 |
{ |
|
1095 |
int i; |
|
1096 |
uint bitmask; |
|
1097 |
int house; |
|
1098 |
uint slope; |
|
1099 |
int z; |
|
1100 |
uint oneof; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1101 |
|
0 | 1102 |
// Above snow? |
1103 |
slope = GetTileSlope(tile, &z); |
|
1104 |
||
1105 |
// Get the town zone type |
|
1106 |
{ |
|
1107 |
uint rad = GetTownRadiusGroup(t, tile); |
|
1108 |
||
1109 |
int land = _opt.landscape; |
|
1110 |
if (land == LT_HILLY && z >= _opt.snow_line) |
|
1111 |
land = -1; |
|
1112 |
||
1113 |
bitmask = (1 << rad) + (1 << (land + 12)); |
|
1114 |
} |
|
1115 |
||
1116 |
// bits 0-4 are used |
|
1117 |
// bits 11-15 are used |
|
1118 |
// bits 5-10 are not used. |
|
1119 |
{ |
|
1120 |
byte houses[lengthof(_housetype_flags)]; |
|
1121 |
int num = 0; |
|
1122 |
||
1123 |
// Generate a list of all possible houses that can be built. |
|
1124 |
for(i=0; i!=lengthof(_housetype_flags); i++) { |
|
1125 |
if ((~_housetype_flags[i] & bitmask) == 0) |
|
1126 |
houses[num++] = (byte)i; |
|
1127 |
} |
|
1128 |
||
1129 |
for(;;) { |
|
1130 |
house = houses[RandomRange(num)]; |
|
1131 |
||
1132 |
if (_cur_year < _housetype_years[house].min || _cur_year > _housetype_years[house].max) |
|
1133 |
continue; |
|
1134 |
||
1135 |
// Special houses that there can be only one of. |
|
483
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1136 |
switch (house) { |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1137 |
case HOUSE_TEMP_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1138 |
case HOUSE_ARCT_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1139 |
case HOUSE_SNOW_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1140 |
case HOUSE_TROP_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1141 |
case HOUSE_TOY_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1142 |
oneof = TOWN_HAS_CHURCH; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1143 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1144 |
case HOUSE_STADIUM: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1145 |
case HOUSE_MODERN_STADIUM: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1146 |
oneof = TOWN_HAS_STADIUM; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1147 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1148 |
default: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1149 |
oneof = 0; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1150 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1151 |
} |
0 | 1152 |
|
1153 |
if (t->flags12 & oneof) |
|
1154 |
continue; |
|
1155 |
||
1156 |
// Make sure there is no slope? |
|
1157 |
if (_housetype_extra_flags[house]&0x12 && slope) |
|
1158 |
continue; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1159 |
|
0 | 1160 |
if (_housetype_extra_flags[house]&0x10) { |
1161 |
if (CheckFree2x2Area(t,tile) || |
|
1162 |
CheckFree2x2Area(t,(tile+=TILE_XY(-1,0))) || |
|
1163 |
CheckFree2x2Area(t,(tile+=TILE_XY(0,-1))) || |
|
1164 |
CheckFree2x2Area(t,(tile+=TILE_XY(1,0)))) |
|
1165 |
break; |
|
1166 |
tile += TILE_XY(0,1); |
|
1167 |
} else if (_housetype_extra_flags[house]&4) { |
|
1168 |
if (CheckBuildHouseMode(t, tile+TILE_XY(1,0), slope, 0)) |
|
1169 |
break; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1170 |
|
0 | 1171 |
if (CheckBuildHouseMode(t, tile+TILE_XY(-1,0), slope, 1)) { |
1172 |
tile += TILE_XY(-1,0); |
|
1173 |
break; |
|
1174 |
} |
|
1175 |
} else if (_housetype_extra_flags[house]&8) { |
|
1176 |
if (CheckBuildHouseMode(t, tile+TILE_XY(0,1), slope, 2)) |
|
1177 |
break; |
|
1178 |
||
1179 |
if (CheckBuildHouseMode(t, tile+TILE_XY(0,-1), slope, 3)) { |
|
1180 |
tile += TILE_XY(0,-1); |
|
1181 |
break; |
|
1182 |
} |
|
1183 |
} else |
|
1184 |
break; |
|
1185 |
} |
|
1186 |
} |
|
1187 |
||
1188 |
t->num_houses++; |
|
1189 |
||
1190 |
// Special houses that there can be only one of. |
|
1191 |
t->flags12 |= oneof; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1192 |
|
0 | 1193 |
{ |
1194 |
int m3lo,m5,eflags; |
|
1195 |
||
1196 |
// ENDING_2 |
|
1197 |
m3lo = 0; |
|
1198 |
m5 = 0; |
|
1199 |
if (_generating_world) { |
|
1200 |
uint32 r = Random(); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1201 |
|
0 | 1202 |
// Value for map3lo |
1203 |
m3lo = 0xC0; |
|
1204 |
if ((byte)r >= 220) m3lo &= (r>>8); |
|
1205 |
||
1206 |
if (m3lo == 0xC0) |
|
1207 |
ChangePopulation(t, _housetype_population[house]); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1208 |
|
0 | 1209 |
// Initial value for map5. |
1210 |
m5 = (r >> 16) & 0x3F; |
|
1211 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1212 |
|
0 | 1213 |
assert(IS_TILETYPE(tile, MP_CLEAR)); |
1214 |
||
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1215 |
ModifyTile(tile, |
0 | 1216 |
MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
1217 |
house, /* map2 */ |
|
1218 |
m3lo, /* map3_lo */ |
|
1219 |
0, /* map_owner */ |
|
1220 |
m5 /* map5 */ |
|
1221 |
); |
|
1222 |
||
1223 |
eflags = _housetype_extra_flags[house]; |
|
1224 |
||
1225 |
if (eflags&0x18) { |
|
1226 |
assert(IS_TILETYPE(tile + TILE_XY(0,1), MP_CLEAR)); |
|
1227 |
ModifyTile(tile + TILE_XY(0,1), |
|
1228 |
MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
|
1229 |
++house, /* map2 */ |
|
1230 |
m3lo, /* map3_lo */ |
|
1231 |
0, /* map_owner */ |
|
1232 |
m5 /* map5 */ |
|
1233 |
); |
|
1234 |
} |
|
1235 |
||
1236 |
if (eflags&0x14) { |
|
1237 |
assert(IS_TILETYPE(tile + TILE_XY(1,0), MP_CLEAR)); |
|
1238 |
ModifyTile(tile + TILE_XY(1,0), |
|
1239 |
MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
|
1240 |
++house, /* map2 */ |
|
1241 |
m3lo, /* map3_lo */ |
|
1242 |
0, /* map_owner */ |
|
1243 |
m5 /* map5 */ |
|
1244 |
); |
|
1245 |
} |
|
1246 |
||
1247 |
if (eflags&0x10) { |
|
1248 |
assert(IS_TILETYPE(tile + TILE_XY(1,1), MP_CLEAR)); |
|
1249 |
ModifyTile(tile + TILE_XY(1,1), |
|
1250 |
MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
|
1251 |
++house, /* map2 */ |
|
1252 |
m3lo, /* map3_lo */ |
|
1253 |
0, /* map_owner */ |
|
1254 |
m5 /* map5 */ |
|
1255 |
); |
|
1256 |
} |
|
1257 |
} |
|
1258 |
||
1259 |
// ENDING |
|
1260 |
} |
|
1261 |
||
1262 |
static bool BuildTownHouse(Town *t, uint tile) |
|
1263 |
{ |
|
1264 |
int32 r; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1265 |
|
0 | 1266 |
// make sure it's possible |
1267 |
if (!EnsureNoVehicle(tile)) return false; |
|
1268 |
if (GetTileSlope(tile, NULL) & 0x10) return false; |
|
1269 |
||
1270 |
r = DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); |
|
1271 |
if (r == CMD_ERROR) return false; |
|
1272 |
||
1273 |
DoBuildTownHouse(t, tile); |
|
1274 |
return true; |
|
1275 |
} |
|
1276 |
||
1277 |
||
1278 |
static void DoClearTownHouseHelper(uint tile) |
|
1279 |
{ |
|
1280 |
assert(IS_TILETYPE(tile, MP_HOUSE)); |
|
1281 |
DoClearSquare(tile); |
|
1282 |
DeleteAnimatedTile(tile); |
|
1283 |
} |
|
1284 |
||
1285 |
static void ClearTownHouse(Town *t, uint tile) { |
|
1286 |
uint house = _map2[tile]; |
|
1287 |
uint eflags; |
|
1288 |
||
1289 |
assert(IS_TILETYPE(tile, MP_HOUSE)); |
|
1290 |
||
1291 |
// need to align the tile to point to the upper left corner of the house |
|
1292 |
if (house >= 3) { // house id 0,1,2 MUST be single tile houses, or this code breaks. |
|
1293 |
if (_housetype_extra_flags[house-1] & 0x04) { |
|
1294 |
house--; |
|
1295 |
tile += TILE_XY(-1,0); |
|
1296 |
} else if (_housetype_extra_flags[house-1] & 0x18) { |
|
1297 |
house--; |
|
1298 |
tile += TILE_XY(0,-1); |
|
1299 |
} else if (_housetype_extra_flags[house-2] & 0x10) { |
|
1300 |
house-=2; |
|
1301 |
tile += TILE_XY(-1,0); |
|
1302 |
} else if (_housetype_extra_flags[house-3] & 0x10) { |
|
1303 |
house-=3; |
|
1304 |
tile += TILE_XY(-1,-1); |
|
1305 |
} |
|
1306 |
} |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1307 |
|
0 | 1308 |
// Remove population from the town if the |
1309 |
// house is finished. |
|
1310 |
if ((~_map3_lo[tile] & 0xC0) == 0) { |
|
1311 |
ChangePopulation(t, -_housetype_population[house]); |
|
1312 |
} |
|
1313 |
||
1314 |
t->num_houses--; |
|
1315 |
||
1316 |
// Clear flags for houses that only may exist once/town. |
|
483
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1317 |
switch (house) { |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1318 |
case HOUSE_TEMP_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1319 |
case HOUSE_ARCT_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1320 |
case HOUSE_SNOW_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1321 |
case HOUSE_TROP_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1322 |
case HOUSE_TOY_CHURCH: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1323 |
t->flags12 &= ~TOWN_HAS_CHURCH; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1324 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1325 |
case HOUSE_STADIUM: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1326 |
case HOUSE_MODERN_STADIUM: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1327 |
t->flags12 &= ~TOWN_HAS_STADIUM; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1328 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1329 |
default: |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1330 |
break; |
d8374ce6b365
(svn r764) Enumerate the houses only one per town can exist and use the enums instead of magic numbers to check for these
tron
parents:
482
diff
changeset
|
1331 |
} |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1332 |
|
0 | 1333 |
// Do the actual clearing of tiles |
1334 |
eflags = _housetype_extra_flags[house]; |
|
1335 |
DoClearTownHouseHelper(tile); |
|
1336 |
if (eflags & 0x14) DoClearTownHouseHelper(tile + TILE_XY(1,0)); |
|
1337 |
if (eflags & 0x18) DoClearTownHouseHelper(tile + TILE_XY(0,1)); |
|
1338 |
if (eflags & 0x10) DoClearTownHouseHelper(tile + TILE_XY(1,1)); |
|
1339 |
} |
|
1340 |
||
1341 |
int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1342 |
{ |
|
1343 |
StringID str; |
|
1344 |
Town *t = DEREF_TOWN(p1); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1345 |
|
543
946badd71033
(svn r942) -Merged branch/network back into the trunk
truelight
parents:
534
diff
changeset
|
1346 |
str = AllocateNameUnique((byte*)_decode_parameters, 4); |
0 | 1347 |
if (str == 0) |
1348 |
return CMD_ERROR; |
|
1349 |
||
1350 |
if (flags & DC_EXEC) { |
|
1351 |
StringID old_str = t->townnametype; |
|
1352 |
t->townnametype = str; |
|
1353 |
DeleteName(old_str); |
|
1354 |
||
1355 |
UpdateTownVirtCoord(t); |
|
1356 |
_town_sort_dirty = true; |
|
1357 |
UpdateAllStationVirtCoord(); |
|
1358 |
MarkWholeScreenDirty(); |
|
1359 |
} else { |
|
1360 |
DeleteName(str); |
|
1361 |
} |
|
1362 |
return 0; |
|
1363 |
} |
|
1364 |
||
1365 |
// Called from GUI |
|
1366 |
void DeleteTown(Town *t) |
|
1367 |
{ |
|
1368 |
Industry *i; |
|
1369 |
uint tile; |
|
1370 |
||
1371 |
// Delete town authority window |
|
1372 |
// and remove from list of sorted towns |
|
1373 |
DeleteWindowById(WC_TOWN_VIEW, t->index); |
|
1374 |
_town_sort_dirty = true; |
|
1375 |
||
1376 |
// Delete all industries belonging to the town |
|
1377 |
for(i=_industries; i != endof(_industries); i++) { |
|
1378 |
if (i->xy && i->town == t) |
|
1379 |
DeleteIndustry(i); |
|
1380 |
} |
|
1381 |
||
1382 |
// Go through all tiles and delete those belonging to the town |
|
1383 |
tile = 0; |
|
1384 |
do { |
|
1385 |
if (IS_TILETYPE(tile, MP_HOUSE)) { |
|
1386 |
if (ClosestTownFromTile(tile, (uint)-1) == t) { |
|
1387 |
DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
|
1388 |
} |
|
1389 |
} else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) || IS_TILETYPE(tile, MP_STREET)) { |
|
1390 |
if (_map_owner[tile] == OWNER_TOWN && ClosestTownFromTile(tile, (uint)-1) == t) { |
|
1391 |
DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
|
1392 |
} |
|
1393 |
} |
|
1394 |
} while (++tile != TILES_X * TILES_Y); |
|
1395 |
||
1396 |
t->xy = 0; |
|
1397 |
DeleteName(t->townnametype); |
|
1398 |
||
1399 |
MarkWholeScreenDirty(); |
|
1400 |
} |
|
1401 |
||
1402 |
// Called from GUI |
|
1403 |
void ExpandTown(Town *t) |
|
1404 |
{ |
|
1405 |
int amount, n; |
|
1406 |
||
1407 |
_generating_world = true; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1408 |
|
0 | 1409 |
amount = ((int)Random()&3) + 3; |
1410 |
t->num_houses += amount; |
|
1411 |
UpdateTownRadius(t); |
|
1412 |
||
1413 |
n = amount * 4; |
|
1414 |
do GrowTown(t); while (--n); |
|
1415 |
||
1416 |
t->num_houses -= amount; |
|
1417 |
UpdateTownRadius(t); |
|
1418 |
||
1419 |
UpdateTownMaxPass(t); |
|
1420 |
_generating_world = false; |
|
1421 |
} |
|
1422 |
||
1423 |
const byte _town_action_costs[8] = { |
|
1424 |
2, 4, 9, 35, 48, 53, 117, 175 |
|
1425 |
}; |
|
1426 |
||
1427 |
typedef void TownActionProc(Town *t, int action); |
|
1428 |
||
1429 |
static void TownActionAdvertise(Town *t, int action) |
|
1430 |
{ |
|
1431 |
static const byte _advertising_amount[3] = {0x40, 0x70, 0xA0}; |
|
1432 |
static const byte _advertising_radius[3] = {10,15,20}; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1433 |
ModifyStationRatingAround(t->xy, _current_player, |
0 | 1434 |
_advertising_amount[action], |
1435 |
_advertising_radius[action]); |
|
1436 |
} |
|
1437 |
||
1438 |
static void TownActionRoadRebuild(Town *t, int action) |
|
1439 |
{ |
|
1440 |
Player *p; |
|
1441 |
||
1442 |
t->road_build_months = 6; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1443 |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
1444 |
SetDParam(0, t->index); |
0 | 1445 |
|
1446 |
p = DEREF_PLAYER(_current_player); |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
1447 |
SetDParam(1, p->name_1); |
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
1448 |
SetDParam(2, p->name_2); |
0 | 1449 |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1450 |
AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING, |
0 | 1451 |
NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_GENERAL, 0), t->xy, 0); |
1452 |
} |
|
1453 |
||
1454 |
static bool DoBuildStatueOfCompany(uint tile) |
|
1455 |
{ |
|
1456 |
TileInfo ti; |
|
1457 |
byte old; |
|
1458 |
int32 r; |
|
1459 |
||
1460 |
FindLandscapeHeightByTile(&ti, tile); |
|
1461 |
if (ti.tileh != 0) |
|
1462 |
return false; |
|
1463 |
||
1464 |
if (ti.type != MP_HOUSE && ti.type != MP_CLEAR && ti.type != MP_TREES) |
|
1465 |
return false; |
|
1466 |
||
1467 |
||
1468 |
old = _current_player; |
|
1469 |
_current_player = OWNER_NONE; |
|
1470 |
r = DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
|
1471 |
_current_player = old; |
|
1472 |
||
1473 |
if (r == CMD_ERROR) |
|
1474 |
return false; |
|
1475 |
||
1476 |
ModifyTile(tile, MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5, |
|
1477 |
2 /* map5 */ |
|
1478 |
); |
|
1479 |
||
1480 |
return true; |
|
1481 |
} |
|
1482 |
||
1483 |
static void TownActionBuildStatue(Town *t, int action) |
|
1484 |
{ |
|
1485 |
// Layouted as an outward spiral |
|
1486 |
static const TileIndexDiff _statue_tiles[] = { |
|
1487 |
TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1488 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
0 | 1489 |
TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1490 |
TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
|
1491 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
|
1492 |
TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
|
1493 |
TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
|
1494 |
TILE_XY(0,1), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
|
1495 |
TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1496 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
0 | 1497 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
1498 |
TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
|
1499 |
TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
|
1500 |
TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
|
1501 |
TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
|
1502 |
TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
|
1503 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1504 |
TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
0 | 1505 |
TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1506 |
TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
|
1507 |
0, |
|
1508 |
}; |
|
1509 |
int offs; |
|
1510 |
uint tile = t->xy; |
|
1511 |
const TileIndexDiff *p = _statue_tiles; |
|
1512 |
||
1513 |
SETBIT(t->statues, _current_player); |
|
1514 |
||
1515 |
do { |
|
1516 |
if (DoBuildStatueOfCompany(tile)) |
|
1517 |
return; |
|
1518 |
offs = *p++; |
|
1519 |
tile = TILE_ADD(tile, offs); |
|
1520 |
} while (offs); |
|
1521 |
} |
|
1522 |
||
1523 |
static void TownActionFundBuildings(Town *t, int action) |
|
1524 |
{ |
|
1525 |
t->grow_counter = 1; |
|
1526 |
t->flags12 |= 1; |
|
1527 |
t->fund_buildings_months = 3; |
|
1528 |
} |
|
1529 |
||
1530 |
static void TownActionBuyRights(Town *t, int action) |
|
1531 |
{ |
|
121
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1532 |
t->exclusive_counter = 12; |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1533 |
t->exclusivity = _current_player; |
0 | 1534 |
|
1535 |
ModifyStationRatingAround(t->xy, _current_player, 130, 17); |
|
1536 |
} |
|
1537 |
||
1538 |
static void TownActionBribe(Town *t, int action) |
|
1539 |
{ |
|
1540 |
if (!RandomRange(15)) { |
|
1541 |
GoodsEntry *ge; |
|
1542 |
Station *st; |
|
1543 |
int i, rating; |
|
1544 |
||
1545 |
// set as unwanted for 6 months |
|
1546 |
t->unwanted[_current_player] = 6; |
|
1547 |
||
1548 |
// set all close by station ratings to 0 |
|
1549 |
FOR_ALL_STATIONS(st) { |
|
1550 |
if (st->town == t && st->owner == _current_player) { |
|
1551 |
for (i=0, ge = st->goods; i != NUM_CARGO; i++, ge++) |
|
1552 |
ge->rating = 0; |
|
1553 |
} |
|
1554 |
} |
|
1555 |
||
1556 |
// only show errormessage to the executing player. All errors are handled command.c |
|
1557 |
// but this is special, because it can only 'fail' on a DC_EXEC |
|
1558 |
if (!_networking || (_current_player == _local_player)) |
|
1559 |
ShowErrorMessage(STR_BRIBE_FAILED_2, STR_BRIBE_FAILED, 0, 0); |
|
1560 |
||
1561 |
/* decrease by a lot! |
|
1562 |
* ChangeTownRating is only for stuff in demolishing. Bribe failure should |
|
1563 |
* be independent of any cheat settings |
|
1564 |
* ChangeTownRating(c, -1000, -50); |
|
1565 |
*/ |
|
1566 |
rating = t->ratings[_current_player]; |
|
1567 |
if (rating > -50) |
|
1568 |
t->ratings[_current_player] = -50; |
|
1569 |
} else { |
|
1570 |
ChangeTownRating(t, 200, 800); |
|
1571 |
} |
|
1572 |
} |
|
1573 |
||
1574 |
static TownActionProc * const _town_action_proc[] = { |
|
1575 |
TownActionAdvertise, |
|
1576 |
TownActionAdvertise, |
|
1577 |
TownActionAdvertise, |
|
1578 |
TownActionRoadRebuild, |
|
1579 |
TownActionBuildStatue, |
|
1580 |
TownActionFundBuildings, |
|
1581 |
TownActionBuyRights, |
|
1582 |
TownActionBribe |
|
1583 |
}; |
|
1584 |
||
1585 |
// p1 = town |
|
1586 |
// p2 = action |
|
1587 |
int32 CmdDoTownAction(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
|
1588 |
{ |
|
1589 |
int32 cost; |
|
1590 |
||
1591 |
SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1592 |
||
1593 |
cost = (_price.build_industry >> 8) * _town_action_costs[p2]; |
|
1594 |
||
1595 |
if (flags & DC_EXEC) { |
|
1596 |
_town_action_proc[p2](DEREF_TOWN(p1), p2); |
|
1597 |
InvalidateWindow(WC_TOWN_AUTHORITY, p1); |
|
1598 |
} |
|
1599 |
||
1600 |
return cost; |
|
1601 |
} |
|
1602 |
||
1603 |
static void UpdateTownGrowRate(Town *t) |
|
1604 |
{ |
|
1605 |
int n; |
|
1606 |
Station *st; |
|
1607 |
byte m; |
|
1608 |
Player *p; |
|
1609 |
||
1610 |
// Reset player ratings if they're low |
|
1611 |
FOR_ALL_PLAYERS(p) { |
|
1612 |
if (p->is_active && t->ratings[p->index] <= 200) { |
|
1613 |
t->ratings[p->index] += 5; |
|
1614 |
} |
|
1615 |
} |
|
1616 |
||
1617 |
n = 0; |
|
1618 |
FOR_ALL_STATIONS(st) { |
|
1619 |
if (GetTileDistAdv(st->xy, t->xy) <= t->radius[0]) { |
|
1620 |
if (st->time_since_load <= 20 || st->time_since_unload <= 20) { |
|
1621 |
n++; |
|
1622 |
if (st->owner < MAX_PLAYERS && t->ratings[st->owner] <= 1000-12) |
|
1623 |
t->ratings[st->owner] += 12; |
|
1624 |
} else { |
|
1625 |
if (st->owner < MAX_PLAYERS && t->ratings[st->owner] >= -1000+15) |
|
1626 |
t->ratings[st->owner] -= 15; |
|
1627 |
} |
|
1628 |
} |
|
1629 |
} |
|
1630 |
||
1631 |
t->flags12 &= ~1; |
|
1632 |
||
1633 |
if (t->fund_buildings_months != 0) { |
|
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
1634 |
static const byte _grow_count_values[6] = { |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
1635 |
60, 60, 60, 50, 40, 30 |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
1636 |
}; |
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
1637 |
m = _grow_count_values[min(n, 5)]; |
0 | 1638 |
t->fund_buildings_months--; |
1639 |
} else if (n == 0) { |
|
1640 |
m = 160; |
|
1641 |
if (!CHANCE16(1, 12)) |
|
1642 |
return; |
|
1643 |
} else { |
|
1644 |
static const byte _grow_count_values[5] = { |
|
1645 |
210, 150, 110, 80, 50 |
|
1646 |
}; |
|
1647 |
m = _grow_count_values[min(n, 5) - 1]; |
|
1648 |
} |
|
1649 |
||
1650 |
if (_opt.landscape == LT_HILLY) { |
|
468
3a36baf27955
(svn r698) Merge a town growth fix from TTDPatch - in arctic and desert climate, require food (and possibly water) only if the population is more than 90, so that the town gets chance to actually accept it. (By Marcin?)
pasky
parents:
466
diff
changeset
|
1651 |
if (GET_TILEHEIGHT(t->xy) >= _opt.snow_line && t->act_food == 0 && t->population > 90) |
0 | 1652 |
return; |
1653 |
} else if (_opt.landscape == LT_DESERT) { |
|
468
3a36baf27955
(svn r698) Merge a town growth fix from TTDPatch - in arctic and desert climate, require food (and possibly water) only if the population is more than 90, so that the town gets chance to actually accept it. (By Marcin?)
pasky
parents:
466
diff
changeset
|
1654 |
if (GetMapExtraBits(t->xy) == 1 && (t->act_food==0 || t->act_water==0) && t->population > 60) |
0 | 1655 |
return; |
1656 |
} |
|
1657 |
||
470
08b29b012837
(svn r703) Attempt to improve the town growth algorithm - now it scales over 76 houses, is slightly exponential and travels further for larger towns.
pasky
parents:
468
diff
changeset
|
1658 |
t->growth_rate = m / (t->num_houses / 50 + 1); |
0 | 1659 |
if (m <= t->grow_counter) |
1660 |
t->grow_counter = m; |
|
1661 |
||
1662 |
t->flags12 |= 1; |
|
1663 |
} |
|
1664 |
||
1665 |
static void UpdateTownAmounts(Town *t) |
|
1666 |
{ |
|
1667 |
// Using +1 here to prevent overflow and division by zero |
|
1668 |
t->pct_pass_transported = t->new_act_pass * 256 / (t->new_max_pass + 1); |
|
1669 |
||
1670 |
t->max_pass = t->new_max_pass; t->new_max_pass = 0; |
|
1671 |
t->act_pass = t->new_act_pass; t->new_act_pass = 0; |
|
1672 |
t->act_food = t->new_act_food; t->new_act_food = 0; |
|
4
cad62d5f9708
(svn r5) -Fix: townname generation of TTDLX savegames. All work
darkvater
parents:
0
diff
changeset
|
1673 |
t->act_water = t->new_act_water; t->new_act_water = 0; |
0 | 1674 |
|
1675 |
// Using +1 here to prevent overflow and division by zero |
|
1676 |
t->pct_mail_transported = t->new_act_mail * 256 / (t->new_max_mail + 1); |
|
1677 |
t->max_mail = t->new_max_mail; t->new_max_mail = 0; |
|
1678 |
t->act_mail = t->new_act_mail; t->new_act_mail = 0; |
|
1679 |
||
1680 |
InvalidateWindow(WC_TOWN_VIEW, t->index); |
|
1681 |
} |
|
1682 |
||
1683 |
static void UpdateTownUnwanted(Town *t) |
|
1684 |
{ |
|
1685 |
Player *p; |
|
1686 |
||
1687 |
FOR_ALL_PLAYERS(p) { |
|
1688 |
if (t->unwanted[p->index] > 0) |
|
1689 |
t->unwanted[p->index]--; |
|
1690 |
} |
|
1691 |
} |
|
1692 |
||
1693 |
bool CheckIfAuthorityAllows(uint tile) |
|
1694 |
{ |
|
1695 |
Town *t; |
|
1696 |
||
1697 |
if (_current_player >= MAX_PLAYERS) |
|
1698 |
return true; |
|
1699 |
||
1700 |
t = ClosestTownFromTile(tile, _patches.dist_local_authority); |
|
1701 |
if (t == NULL) |
|
1702 |
return true; |
|
1703 |
||
1704 |
if (t->ratings[_current_player] > -200) |
|
1705 |
return true; |
|
1706 |
||
1707 |
_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
1708 |
SetDParam(0, t->index); |
0 | 1709 |
|
1710 |
return false; |
|
1711 |
} |
|
1712 |
||
1713 |
||
1714 |
Town *ClosestTownFromTile(uint tile, uint threshold) |
|
1715 |
{ |
|
1716 |
Town *t; |
|
1717 |
uint dist, best = threshold; |
|
1718 |
Town *best_town = NULL; |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1719 |
|
0 | 1720 |
FOR_ALL_TOWNS(t) { |
1721 |
if (t->xy != 0) { |
|
1722 |
dist = GetTileDist(tile, t->xy); |
|
1723 |
if (dist < best) { |
|
1724 |
best = dist; |
|
1725 |
best_town = t; |
|
1726 |
} |
|
1727 |
} |
|
1728 |
} |
|
1729 |
||
1730 |
return best_town; |
|
1731 |
} |
|
1732 |
||
1733 |
void ChangeTownRating(Town *t, int add, int max) |
|
1734 |
{ |
|
1735 |
int rating; |
|
1736 |
||
1737 |
// if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff |
|
1738 |
if (t == NULL || _current_player >= MAX_PLAYERS || (_cheats.magic_bulldozer.value && add < 0) ) |
|
1739 |
return; |
|
1740 |
||
1741 |
SETBIT(t->have_ratings, _current_player); |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1742 |
|
0 | 1743 |
rating = t->ratings[_current_player]; |
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1744 |
|
0 | 1745 |
if (add < 0) { |
1746 |
if (rating > max) { |
|
1747 |
rating += add; |
|
1748 |
if (rating < max) rating = max; |
|
1749 |
} |
|
1750 |
} else { |
|
1751 |
if (rating < max) { |
|
1752 |
rating += add; |
|
1753 |
if (rating > max) rating = max; |
|
1754 |
} |
|
1755 |
} |
|
1756 |
t->ratings[_current_player] = rating; |
|
1757 |
} |
|
1758 |
||
1759 |
/* penalty for removing town-owned stuff */ |
|
1760 |
static const int _default_rating_settings [3][3] = { |
|
1761 |
// ROAD_REMOVE, TUNNELBRIDGE_REMOVE, INDUSTRY_REMOVE |
|
1762 |
{ 0, 128, 384}, // Permissive |
|
1763 |
{ 48, 192, 480}, // Neutral |
|
1764 |
{ 96, 384, 768}, // Hostile |
|
1765 |
}; |
|
1766 |
||
1767 |
bool CheckforTownRating(uint tile, uint32 flags, Town *t, byte type) |
|
1768 |
{ |
|
1769 |
int modemod; |
|
1770 |
||
1771 |
// if magic_bulldozer cheat is active, town doesn't restrict your destructive actions |
|
1772 |
if (t == NULL || _current_player >= MAX_PLAYERS || _cheats.magic_bulldozer.value) |
|
1773 |
return true; |
|
1774 |
||
1775 |
/* check if you're allowed to remove the street/bridge/tunnel/industry |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1776 |
* owned by a town no removal if rating is lower than ... depends now on |
0 | 1777 |
* difficulty setting. Minimum town rating selected by difficulty level |
1778 |
*/ |
|
1779 |
modemod = _default_rating_settings[_opt_mod_ptr->diff.town_council_tolerance][type]; |
|
1780 |
||
1781 |
if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { |
|
534
306bc86eb23e
(svn r901) Small step in the process to clean up the DPARAM mess:
tron
parents:
516
diff
changeset
|
1782 |
SetDParam(0, t->index); |
0 | 1783 |
_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
1784 |
return false; |
|
1785 |
} |
|
1786 |
||
1787 |
return true; |
|
1788 |
} |
|
1789 |
||
1790 |
void TownsMonthlyLoop() |
|
1791 |
{ |
|
1792 |
Town *t; |
|
1793 |
||
1794 |
FOR_ALL_TOWNS(t) if (t->xy != 0) { |
|
1795 |
if (t->road_build_months != 0) |
|
1796 |
t->road_build_months--; |
|
1797 |
||
121
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1798 |
if (t->exclusive_counter != 0) |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1799 |
if(--t->exclusive_counter==0) |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1800 |
t->exclusivity = (byte)-1; |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1801 |
|
0 | 1802 |
UpdateTownGrowRate(t); |
1803 |
UpdateTownAmounts(t); |
|
1804 |
UpdateTownUnwanted(t); |
|
1805 |
} |
|
1806 |
} |
|
1807 |
||
1808 |
void InitializeTowns() |
|
1809 |
{ |
|
1810 |
Subsidy *s; |
|
1811 |
int i; |
|
1812 |
||
1813 |
memset(_towns, 0, sizeof(_towns)); |
|
1814 |
for(i=0; i!=lengthof(_towns); i++) |
|
1815 |
_towns[i].index = i; |
|
1816 |
||
1817 |
memset(_subsidies, 0, sizeof(_subsidies)); |
|
1818 |
for (s=_subsidies; s != endof(_subsidies); s++) |
|
1819 |
s->cargo_type = 0xFF; |
|
1820 |
||
1821 |
_cur_town_ctr = 0; |
|
1822 |
_town_sort_dirty = true; |
|
1823 |
_total_towns = 0; |
|
1824 |
} |
|
1825 |
||
1826 |
const TileTypeProcs _tile_type_town_procs = { |
|
1827 |
DrawTile_Town, /* draw_tile_proc */ |
|
1828 |
GetSlopeZ_Town, /* get_slope_z_proc */ |
|
1829 |
ClearTile_Town, /* clear_tile_proc */ |
|
1830 |
GetAcceptedCargo_Town, /* get_accepted_cargo_proc */ |
|
1831 |
GetTileDesc_Town, /* get_tile_desc_proc */ |
|
1832 |
GetTileTrackStatus_Town, /* get_tile_track_status_proc */ |
|
1833 |
ClickTile_Town, /* click_tile_proc */ |
|
1834 |
AnimateTile_Town, /* animate_tile_proc */ |
|
1835 |
TileLoop_Town, /* tile_loop_clear */ |
|
1836 |
ChangeTileOwner_Town, /* change_tile_owner_clear */ |
|
1837 |
NULL, /* get_produced_cargo_proc */ |
|
1838 |
NULL, /* vehicle_enter_tile_proc */ |
|
1839 |
NULL, /* vehicle_leave_tile_proc */ |
|
39 | 1840 |
GetSlopeTileh_Town, /* get_slope_tileh_proc */ |
0 | 1841 |
}; |
1842 |
||
1843 |
||
1844 |
// Save and load of towns. |
|
1845 |
static const byte _town_desc[] = { |
|
1846 |
SLE_VAR(Town,xy, SLE_UINT16), |
|
193
0a7025304867
(svn r194) -Codechange: stripping trailing-spaces. Please keep this that way!
truelight
parents:
159
diff
changeset
|
1847 |
|
0 | 1848 |
SLE_CONDVAR(Town,population, SLE_FILE_U16 | SLE_VAR_U32, 0, 2), |
1849 |
SLE_CONDVAR(Town,population, SLE_UINT32, 3, 255), |
|
1850 |
||
1851 |
||
1852 |
SLE_VAR(Town,num_houses, SLE_UINT16), |
|
1853 |
SLE_VAR(Town,townnametype,SLE_UINT16), |
|
1854 |
SLE_VAR(Town,townnameparts,SLE_UINT32), |
|
1855 |
||
1856 |
SLE_VAR(Town,flags12, SLE_UINT8), |
|
1857 |
SLE_VAR(Town,statues, SLE_UINT8), |
|
1858 |
||
1859 |
// sort_index_obsolete was stored here in savegame format 0 - 1 |
|
1860 |
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 1, 0, 1), |
|
1861 |
||
1862 |
SLE_VAR(Town,have_ratings,SLE_UINT8), |
|
1863 |
SLE_ARR(Town,ratings, SLE_INT16, 8), |
|
1864 |
// failed bribe attempts are stored since savegame format 4 |
|
1865 |
SLE_CONDARR(Town,unwanted, SLE_INT8, 8, 4,255), |
|
1866 |
||
1867 |
SLE_VAR(Town,max_pass, SLE_UINT16), |
|
1868 |
SLE_VAR(Town,max_mail, SLE_UINT16), |
|
1869 |
SLE_VAR(Town,new_max_pass,SLE_UINT16), |
|
1870 |
SLE_VAR(Town,new_max_mail,SLE_UINT16), |
|
1871 |
SLE_VAR(Town,act_pass, SLE_UINT16), |
|
1872 |
SLE_VAR(Town,act_mail, SLE_UINT16), |
|
1873 |
SLE_VAR(Town,new_act_pass,SLE_UINT16), |
|
1874 |
SLE_VAR(Town,new_act_mail,SLE_UINT16), |
|
1875 |
||
1876 |
SLE_VAR(Town,pct_pass_transported,SLE_UINT8), |
|
1877 |
SLE_VAR(Town,pct_mail_transported,SLE_UINT8), |
|
1878 |
||
1879 |
SLE_VAR(Town,act_food, SLE_UINT16), |
|
4
cad62d5f9708
(svn r5) -Fix: townname generation of TTDLX savegames. All work
darkvater
parents:
0
diff
changeset
|
1880 |
SLE_VAR(Town,act_water, SLE_UINT16), |
0 | 1881 |
SLE_VAR(Town,new_act_food,SLE_UINT16), |
4
cad62d5f9708
(svn r5) -Fix: townname generation of TTDLX savegames. All work
darkvater
parents:
0
diff
changeset
|
1882 |
SLE_VAR(Town,new_act_water,SLE_UINT16), |
0 | 1883 |
|
1884 |
SLE_VAR(Town,time_until_rebuild, SLE_UINT8), |
|
1885 |
SLE_VAR(Town,grow_counter, SLE_UINT8), |
|
1886 |
SLE_VAR(Town,growth_rate, SLE_UINT8), |
|
1887 |
SLE_VAR(Town,fund_buildings_months, SLE_UINT8), |
|
1888 |
SLE_VAR(Town,road_build_months, SLE_UINT8), |
|
1889 |
||
121
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1890 |
SLE_VAR(Town,exclusivity, SLE_UINT8), |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1891 |
SLE_VAR(Town,exclusive_counter, SLE_UINT8), |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1892 |
// reserve extra space in savegame here. (currently 30 bytes) |
c2f18f4d8be1
(svn r122) Change: exclusive transport rights are now stored per town instead of per station
dominik
parents:
39
diff
changeset
|
1893 |
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 30, 2, 255), |
0 | 1894 |
|
1895 |
SLE_END() |
|
1896 |
}; |
|
1897 |
||
1898 |
static void Save_TOWN() |
|
1899 |
{ |
|
1900 |
Town *t; |
|
1901 |
||
1902 |
FOR_ALL_TOWNS(t) if (t->xy != 0) { |
|
1903 |
SlSetArrayIndex(t->index); |
|
1904 |
SlObject(t, _town_desc); |
|
1905 |
} |
|
1906 |
} |
|
1907 |
||
1908 |
static void Load_TOWN() |
|
1909 |
{ |
|
1910 |
int index; |
|
1911 |
while ((index = SlIterateArray()) != -1) { |
|
1912 |
Town *t = DEREF_TOWN(index); |
|
1913 |
SlObject(t, _town_desc); |
|
543
946badd71033
(svn r942) -Merged branch/network back into the trunk
truelight
parents:
534
diff
changeset
|
1914 |
if (index > _total_towns) _total_towns = index; |
0 | 1915 |
} |
1916 |
} |
|
1917 |
||
1918 |
void AfterLoadTown() |
|
1919 |
{ |
|
1920 |
Town *t; |
|
1921 |
FOR_ALL_TOWNS(t) { |
|
1922 |
if (t->xy != 0) { |
|
1923 |
UpdateTownRadius(t); |
|
1924 |
UpdateTownVirtCoord(t); |
|
1925 |
} |
|
1926 |
} |
|
1927 |
_town_sort_dirty = true; |
|
1928 |
} |
|
1929 |
||
1930 |
||
1931 |
const ChunkHandler _town_chunk_handlers[] = { |
|
1932 |
{ 'CITY', Save_TOWN, Load_TOWN, CH_ARRAY | CH_LAST}, |
|
1933 |
}; |
|
1934 |
||
1935 |