changeset 193 | 0a7025304867 |
parent 159 | 139cf78bfb28 |
child 260 | 4819bcce8389 |
192:614bba52258d | 193:0a7025304867 |
---|---|
74 |
74 |
75 /* Add a house on top of the ground? */ |
75 /* Add a house on top of the ground? */ |
76 if ((image = dcts->sprite_2) != 0) { |
76 if ((image = dcts->sprite_2) != 0) { |
77 if (!(_display_opt & DO_TRANS_BUILDINGS)) |
77 if (!(_display_opt & DO_TRANS_BUILDINGS)) |
78 image = (image & 0x3FFF) | 0x3224000; |
78 image = (image & 0x3FFF) | 0x3224000; |
79 |
79 |
80 AddSortableSpriteToDraw(image, |
80 AddSortableSpriteToDraw(image, |
81 ti->x | (dcts->subtile_xy>>4), |
81 ti->x | (dcts->subtile_xy>>4), |
82 ti->y | (dcts->subtile_xy&0xF), |
82 ti->y | (dcts->subtile_xy&0xF), |
83 (dcts->width_height>>4)+1, |
83 (dcts->width_height>>4)+1, |
84 (dcts->width_height&0xF)+1, |
84 (dcts->width_height&0xF)+1, |
85 dcts->dz, |
85 dcts->dz, |
98 |
98 |
99 static uint GetSlopeZ_Town(TileInfo *ti) |
99 static uint GetSlopeZ_Town(TileInfo *ti) |
100 { |
100 { |
101 uint z = GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; |
101 uint z = GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z; |
102 if (ti->tileh != 0) z = (z & ~7) + 4; |
102 if (ti->tileh != 0) z = (z & ~7) + 4; |
103 return (uint16) z; |
103 return (uint16) z; |
104 } |
104 } |
105 |
105 |
106 static uint GetSlopeTileh_Town(TileInfo *ti) |
106 static uint GetSlopeTileh_Town(TileInfo *ti) |
107 { |
107 { |
108 return ti->tileh; |
108 return ti->tileh; |
138 if (a == b) { |
138 if (a == b) { |
139 _map5[tile] &= 0x40; |
139 _map5[tile] &= 0x40; |
140 _map_owner[tile] &= 0x7F; |
140 _map_owner[tile] &= 0x7F; |
141 DeleteAnimatedTile(tile); |
141 DeleteAnimatedTile(tile); |
142 } |
142 } |
143 |
143 |
144 MarkTileDirtyByTile(tile); |
144 MarkTileDirtyByTile(tile); |
145 } |
145 } |
146 |
146 |
147 static void UpdateTownRadius(Town *t); |
147 static void UpdateTownRadius(Town *t); |
148 |
148 |
167 } |
167 } |
168 |
168 |
169 static void MakeSingleHouseBigger(uint tile) |
169 static void MakeSingleHouseBigger(uint tile) |
170 { |
170 { |
171 byte b; |
171 byte b; |
172 |
172 |
173 assert(IS_TILETYPE(tile, MP_HOUSE)); |
173 assert(IS_TILETYPE(tile, MP_HOUSE)); |
174 |
174 |
175 b = _map5[tile]; |
175 b = _map5[tile]; |
176 if (b & 0x80) |
176 if (b & 0x80) |
177 return; |
177 return; |
178 |
178 |
179 _map5[tile] = (b & 0xC0) | ((b+1)&7); |
179 _map5[tile] = (b & 0xC0) | ((b+1)&7); |
183 |
183 |
184 _map3_lo[tile] = _map3_lo[tile] + 0x40; |
184 _map3_lo[tile] = _map3_lo[tile] + 0x40; |
185 |
185 |
186 if ( (_map3_lo[tile] & 0xC0) == 0xC0) { |
186 if ( (_map3_lo[tile] & 0xC0) == 0xC0) { |
187 Town *t = ClosestTownFromTile(tile, (uint)-1); |
187 Town *t = ClosestTownFromTile(tile, (uint)-1); |
188 ChangePopulation(t, _housetype_population[_map2[tile]]); |
188 ChangePopulation(t, _housetype_population[_map2[tile]]); |
189 } |
189 } |
190 MarkTileDirtyByTile(tile); |
190 MarkTileDirtyByTile(tile); |
191 } |
191 } |
192 |
192 |
193 static void MakeTownHouseBigger(uint tile) |
193 static void MakeTownHouseBigger(uint tile) |
194 { |
194 { |
195 uint flags = _house_more_flags[_map2[tile]]; |
195 uint flags = _house_more_flags[_map2[tile]]; |
196 if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
196 if (flags & 8) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 0)); |
197 if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
197 if (flags & 4) MakeSingleHouseBigger(TILE_ADDXY(tile, 0, 1)); |
198 if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
198 if (flags & 2) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 0)); |
199 if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
199 if (flags & 1) MakeSingleHouseBigger(TILE_ADDXY(tile, 1, 1)); |
200 } |
200 } |
243 t->time_until_rebuild = (r & 63) + 130; |
243 t->time_until_rebuild = (r & 63) + 130; |
244 |
244 |
245 _current_player = OWNER_TOWN; |
245 _current_player = OWNER_TOWN; |
246 |
246 |
247 ClearTownHouse(t, tile); |
247 ClearTownHouse(t, tile); |
248 |
248 |
249 // rebuild with another house? |
249 // rebuild with another house? |
250 if ( (byte) (r >> 8) >= 12) { |
250 if ( (byte) (r >> 8) >= 12) { |
251 DoBuildTownHouse(t, tile); |
251 DoBuildTownHouse(t, tile); |
252 } |
252 } |
253 } |
253 } |
272 cost = _price.remove_house * _housetype_remove_cost[house] >> 8; |
272 cost = _price.remove_house * _housetype_remove_cost[house] >> 8; |
273 |
273 |
274 rating = _housetype_remove_ratingmod[house]; |
274 rating = _housetype_remove_ratingmod[house]; |
275 _cleared_town_rating += rating; |
275 _cleared_town_rating += rating; |
276 _cleared_town = t = ClosestTownFromTile(tile, (uint)-1); |
276 _cleared_town = t = ClosestTownFromTile(tile, (uint)-1); |
277 |
277 |
278 if (_current_player < MAX_PLAYERS) { |
278 if (_current_player < MAX_PLAYERS) { |
279 if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) { |
279 if (rating > t->ratings[_current_player] && !(flags & DC_NO_TOWN_RATING) && !_cheats.magic_bulldozer.value) { |
280 SET_DPARAM16(0, t->index); |
280 SET_DPARAM16(0, t->index); |
281 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
281 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
282 } |
282 } |
283 } |
283 } |
284 |
284 |
285 if (flags & DC_EXEC) { |
285 if (flags & DC_EXEC) { |
286 ChangeTownRating(t, -rating, -1000); |
286 ChangeTownRating(t, -rating, -1000); |
287 ClearTownHouse(t, tile); |
287 ClearTownHouse(t, tile); |
291 } |
291 } |
292 |
292 |
293 static void GetAcceptedCargo_Town(uint tile, AcceptedCargo *ac) |
293 static void GetAcceptedCargo_Town(uint tile, AcceptedCargo *ac) |
294 { |
294 { |
295 int type = _map2[tile]; |
295 int type = _map2[tile]; |
296 |
296 |
297 ac->type_1 = CT_PASSENGERS; |
297 ac->type_1 = CT_PASSENGERS; |
298 ac->amount_1 = _housetype_cargo_passengers[type]; |
298 ac->amount_1 = _housetype_cargo_passengers[type]; |
299 |
299 |
300 ac->type_2 = CT_GOODS; |
300 ac->type_2 = CT_GOODS; |
301 ac->amount_2 = _housetype_cargo_goods[type]; |
301 ac->amount_2 = _housetype_cargo_goods[type]; |
334 static const TileIndexDiff _roadblock_tileadd[4+3] = { |
334 static const TileIndexDiff _roadblock_tileadd[4+3] = { |
335 TILE_XY(0,-1), |
335 TILE_XY(0,-1), |
336 TILE_XY(1,0), |
336 TILE_XY(1,0), |
337 TILE_XY(0,1), |
337 TILE_XY(0,1), |
338 TILE_XY(-1,0), |
338 TILE_XY(-1,0), |
339 |
339 |
340 // Store the first 3 elements again. |
340 // Store the first 3 elements again. |
341 // Lets us rotate without using &3. |
341 // Lets us rotate without using &3. |
342 TILE_XY(0,-1), |
342 TILE_XY(0,-1), |
343 TILE_XY(1,0), |
343 TILE_XY(1,0), |
344 TILE_XY(0,1), |
344 TILE_XY(0,1), |
350 int i = t->grow_counter - 1; |
350 int i = t->grow_counter - 1; |
351 if (i < 0) { |
351 if (i < 0) { |
352 if (GrowTown(t)) { |
352 if (GrowTown(t)) { |
353 i = t->growth_rate; |
353 i = t->growth_rate; |
354 } else { |
354 } else { |
355 i = 0; |
355 i = 0; |
356 } |
356 } |
357 } |
357 } |
358 t->grow_counter = i; |
358 t->grow_counter = i; |
359 } |
359 } |
360 |
360 |
398 uint slope; |
398 uint slope; |
399 |
399 |
400 // If this assertion fails, it might be because the world contains |
400 // If this assertion fails, it might be because the world contains |
401 // land at the edges. This is not ok. |
401 // land at the edges. This is not ok. |
402 TILE_ASSERT(tile); |
402 TILE_ASSERT(tile); |
403 |
403 |
404 for(;;) { |
404 for(;;) { |
405 // Check if there already is a road at this point? |
405 // Check if there already is a road at this point? |
406 if (GetRoadBitsByTile(tile) == 0) { |
406 if (GetRoadBitsByTile(tile) == 0) { |
407 // No, try to build one in the direction. |
407 // No, try to build one in the direction. |
408 // if that fails clear the land, and if that fails exit. |
408 // if that fails clear the land, and if that fails exit. |
419 if (HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1])), dir^2) || |
419 if (HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1])), dir^2) || |
420 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3])), dir^2) || |
420 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3])), dir^2) || |
421 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1] + _roadblock_tileadd[dir+2])), dir) || |
421 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+1] + _roadblock_tileadd[dir+2])), dir) || |
422 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3] + _roadblock_tileadd[dir+2])), dir)) |
422 HASBIT(GetTownRoadMask(TILE_ADD(tile, _roadblock_tileadd[dir+3] + _roadblock_tileadd[dir+2])), dir)) |
423 return false; |
423 return false; |
424 |
424 |
425 // Otherwise allow |
425 // Otherwise allow |
426 return true; |
426 return true; |
427 } |
427 } |
428 |
428 |
429 // If the tile is not a slope in the right direction, then |
429 // If the tile is not a slope in the right direction, then |
430 // maybe terraform some. |
430 // maybe terraform some. |
431 if ((k = (dir&1)?0xC:0x9) != slope && (k^0xF) != slope) { |
431 if ((k = (dir&1)?0xC:0x9) != slope && (k^0xF) != slope) { |
432 uint32 r = Random(); |
432 uint32 r = Random(); |
433 |
433 |
445 } |
445 } |
446 |
446 |
447 static bool TerraformTownTile(uint tile, int edges, int dir) |
447 static bool TerraformTownTile(uint tile, int edges, int dir) |
448 { |
448 { |
449 int32 r; |
449 int32 r; |
450 |
450 |
451 TILE_ASSERT(tile); |
451 TILE_ASSERT(tile); |
452 |
452 |
453 r = DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); |
453 r = DoCommandByTile(tile, edges, dir, DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND); |
454 if (r == CMD_ERROR || r >= 126*16) |
454 if (r == CMD_ERROR || r >= 126*16) |
455 return false; |
455 return false; |
489 |
489 |
490 TILE_ASSERT(tile); |
490 TILE_ASSERT(tile); |
491 |
491 |
492 if (mask == 0) { |
492 if (mask == 0) { |
493 // Tile has no road. First reset the status counter |
493 // Tile has no road. First reset the status counter |
494 // to say that this is the last iteration. |
494 // to say that this is the last iteration. |
495 _grow_town_result = 0; |
495 _grow_town_result = 0; |
496 |
496 |
497 // Then check if the tile we are at belongs to the town, |
497 // Then check if the tile we are at belongs to the town, |
498 // if not, bail out. |
498 // if not, bail out. |
499 t2 = ClosestTownFromTile(tile, (uint)-1); |
499 t2 = ClosestTownFromTile(tile, (uint)-1); |
518 if (!IsRoadAllowedHere(TILE_ADD(tile,_roadblock_tileadd[a]), a)) { |
518 if (!IsRoadAllowedHere(TILE_ADD(tile,_roadblock_tileadd[a]), a)) { |
519 // A road is not allowed to continue the randomized road, |
519 // A road is not allowed to continue the randomized road, |
520 // return if the road we're trying to build is curved. |
520 // return if the road we're trying to build is curved. |
521 if ( a != (b^2)) |
521 if ( a != (b^2)) |
522 return; |
522 return; |
523 |
523 |
524 // Return if neither side of the new road is a house |
524 // Return if neither side of the new road is a house |
525 if (!IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+1]), MP_HOUSE) && |
525 if (!IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+1]), MP_HOUSE) && |
526 !IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+3]), MP_HOUSE)) |
526 !IS_TILETYPE(TILE_ADD(tile,_roadblock_tileadd[a+3]), MP_HOUSE)) |
527 return; |
527 return; |
528 |
528 |
542 if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile]&~3)==4) { |
542 if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && (_map5[tile]&~3)==4) { |
543 FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, _map5[tile]&3); |
543 FindLengthOfTunnelResult flotr = FindLengthOfTunnel(tile, _map5[tile]&3); |
544 *tile_ptr = flotr.tile; |
544 *tile_ptr = flotr.tile; |
545 return; |
545 return; |
546 } |
546 } |
547 |
547 |
548 // For any other kind of tunnel/bridge, bail out. |
548 // For any other kind of tunnel/bridge, bail out. |
549 if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) |
549 if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) |
550 return; |
550 return; |
551 |
551 |
552 // Possibly extend the road in a direction. |
552 // Possibly extend the road in a direction. |
555 if (HASBIT(mask, i)) |
555 if (HASBIT(mask, i)) |
556 return; |
556 return; |
557 |
557 |
558 // This is the tile we will reach if we extend to this direction. |
558 // This is the tile we will reach if we extend to this direction. |
559 tmptile = TILE_ADD(tile,_roadblock_tileadd[i]); |
559 tmptile = TILE_ADD(tile,_roadblock_tileadd[i]); |
560 |
560 |
561 // Don't do it if it reaches to water. |
561 // Don't do it if it reaches to water. |
562 if (IS_WATER_TILE(tmptile)) |
562 if (IS_WATER_TILE(tmptile)) |
563 return; |
563 return; |
564 |
564 |
565 // If the new tile belongs to another town, |
565 // If the new tile belongs to another town, |
567 if (ClosestTownFromTile(tmptile, (uint)-1) != t1) { |
567 if (ClosestTownFromTile(tmptile, (uint)-1) != t1) { |
568 _grow_town_result = 0; |
568 _grow_town_result = 0; |
569 return; |
569 return; |
570 } |
570 } |
571 |
571 |
572 // Build a house at the edge. 60% chance or |
572 // Build a house at the edge. 60% chance or |
573 // always ok if no road allowed. |
573 // always ok if no road allowed. |
574 if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6,10)) { |
574 if (!IsRoadAllowedHere(tmptile, i) || CHANCE16(6,10)) { |
575 // But not if there already is a house there. |
575 // But not if there already is a house there. |
576 if (!IS_TILETYPE(tmptile, MP_HOUSE)) { |
576 if (!IS_TILETYPE(tmptile, MP_HOUSE)) { |
577 // Level the land if possible |
577 // Level the land if possible |
720 do { |
720 do { |
721 if (GetRoadBitsByTile(tile) != 0) { |
721 if (GetRoadBitsByTile(tile) != 0) { |
722 return GrowTownAtRoad(t, tile); |
722 return GrowTownAtRoad(t, tile); |
723 } |
723 } |
724 offs = *ptr++; |
724 offs = *ptr++; |
725 |
725 |
726 tile = TILE_ADD(tile, offs); |
726 tile = TILE_ADD(tile, offs); |
727 } while (offs); |
727 } while (offs); |
728 |
728 |
729 // No road available, try to build a random road block by |
729 // No road available, try to build a random road block by |
730 // clearing some land and then building a road there. |
730 // clearing some land and then building a road there. |
731 tile = t->xy; |
731 tile = t->xy; |
732 ptr = _town_coord_mod; |
732 ptr = _town_coord_mod; |
733 do { |
733 do { |
734 FindLandscapeHeightByTile(&ti, tile); |
734 FindLandscapeHeightByTile(&ti, tile); |
735 |
735 |
736 // Only work with plain land that not already has a house with map5=0 |
736 // Only work with plain land that not already has a house with map5=0 |
737 if (ti.tileh == 0 && !(ti.type==MP_HOUSE && ti.map5==0)) { |
737 if (ti.tileh == 0 && !(ti.type==MP_HOUSE && ti.map5==0)) { |
738 if (DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) { |
738 if (DoCommandByTile(tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR) { |
739 DoCommandByTile(tile, GenRandomRoadBits(), 0, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); |
739 DoCommandByTile(tile, GenRandomRoadBits(), 0, DC_EXEC | DC_AUTO, CMD_BUILD_ROAD); |
740 return true; |
740 return true; |
798 restart: |
798 restart: |
799 r = Random(); |
799 r = Random(); |
800 |
800 |
801 SET_DPARAM32(0, r); |
801 SET_DPARAM32(0, r); |
802 GetString(buf1, t1->townnametype); |
802 GetString(buf1, t1->townnametype); |
803 |
803 |
804 // Check size and width |
804 // Check size and width |
805 if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130) |
805 if (strlen(buf1) >= 31 || GetStringWidth(buf1) > 130) |
806 continue; |
806 continue; |
807 |
807 |
808 FOR_ALL_TOWNS(t2) { |
808 FOR_ALL_TOWNS(t2) { |
812 if (str_eq(buf1, buf2)) |
812 if (str_eq(buf1, buf2)) |
813 goto restart; |
813 goto restart; |
814 } |
814 } |
815 } |
815 } |
816 t1->townnameparts = r; |
816 t1->townnameparts = r; |
817 |
817 |
818 return; |
818 return; |
819 } |
819 } |
820 } |
820 } |
821 |
821 |
822 static void UpdateTownMaxPass(Town *t) |
822 static void UpdateTownMaxPass(Town *t) |
866 t->exclusivity = (byte)-1; |
866 t->exclusivity = (byte)-1; |
867 t->exclusive_counter = 0; |
867 t->exclusive_counter = 0; |
868 t->statues = 0; |
868 t->statues = 0; |
869 |
869 |
870 CreateTownName(t); |
870 CreateTownName(t); |
871 |
871 |
872 UpdateTownVirtCoord(t); |
872 UpdateTownVirtCoord(t); |
873 _town_sort_dirty = true; |
873 _town_sort_dirty = true; |
874 |
874 |
875 x = (Random() & 0xF) + 8; |
875 x = (Random() & 0xF) + 8; |
876 if (_game_mode == GM_EDITOR) |
876 if (_game_mode == GM_EDITOR) |
904 int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
904 int32 CmdBuildTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
905 { |
905 { |
906 uint tile = TILE_FROM_XY(x,y); |
906 uint tile = TILE_FROM_XY(x,y); |
907 TileInfo ti; |
907 TileInfo ti; |
908 Town *t; |
908 Town *t; |
909 |
909 |
910 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
910 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
911 |
911 |
912 // Check if too close to the edge of map |
912 // Check if too close to the edge of map |
913 if (!CheckDistanceFromEdge(tile, 12)) |
913 if (!CheckDistanceFromEdge(tile, 12)) |
914 return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); |
914 return_cmd_error(STR_0237_TOO_CLOSE_TO_EDGE_OF_MAP); |
923 return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN); |
923 return_cmd_error(STR_0238_TOO_CLOSE_TO_ANOTHER_TOWN); |
924 |
924 |
925 // Allocate town struct |
925 // Allocate town struct |
926 t = AllocateTown(); |
926 t = AllocateTown(); |
927 if (t == NULL) |
927 if (t == NULL) |
928 return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
928 return_cmd_error(STR_023A_TOO_MANY_TOWNS); |
929 |
929 |
930 // Create the town |
930 // Create the town |
931 if (flags & DC_EXEC) { |
931 if (flags & DC_EXEC) { |
932 _generating_world = true; |
932 _generating_world = true; |
933 DoCreateTown(t, tile); |
933 DoCreateTown(t, tile); |
957 continue; |
957 continue; |
958 |
958 |
959 // Check not too close to a town |
959 // Check not too close to a town |
960 if (IsCloseToTown(tile, 20)) |
960 if (IsCloseToTown(tile, 20)) |
961 continue; |
961 continue; |
962 |
962 |
963 // Allocate a town struct |
963 // Allocate a town struct |
964 t = AllocateTown(); |
964 t = AllocateTown(); |
965 if (t == NULL) |
965 if (t == NULL) |
966 break; |
966 break; |
967 |
967 |
1040 |
1040 |
1041 for(i=0; i!=4; i++) { |
1041 for(i=0; i!=4; i++) { |
1042 tile += _tile_add[i]; |
1042 tile += _tile_add[i]; |
1043 |
1043 |
1044 t = ClosestTownFromTile(tile, (uint)-1); |
1044 t = ClosestTownFromTile(tile, (uint)-1); |
1045 if (t1 != t) |
1045 if (t1 != t) |
1046 return false; |
1046 return false; |
1047 |
1047 |
1048 if (GetTileSlope(tile, NULL)) |
1048 if (GetTileSlope(tile, NULL)) |
1049 return false; |
1049 return false; |
1050 |
1050 |
1061 uint bitmask; |
1061 uint bitmask; |
1062 int house; |
1062 int house; |
1063 uint slope; |
1063 uint slope; |
1064 int z; |
1064 int z; |
1065 uint oneof; |
1065 uint oneof; |
1066 |
1066 |
1067 // Above snow? |
1067 // Above snow? |
1068 slope = GetTileSlope(tile, &z); |
1068 slope = GetTileSlope(tile, &z); |
1069 |
1069 |
1070 // Get the town zone type |
1070 // Get the town zone type |
1071 { |
1071 { |
1108 continue; |
1108 continue; |
1109 |
1109 |
1110 // Make sure there is no slope? |
1110 // Make sure there is no slope? |
1111 if (_housetype_extra_flags[house]&0x12 && slope) |
1111 if (_housetype_extra_flags[house]&0x12 && slope) |
1112 continue; |
1112 continue; |
1113 |
1113 |
1114 if (_housetype_extra_flags[house]&0x10) { |
1114 if (_housetype_extra_flags[house]&0x10) { |
1115 if (CheckFree2x2Area(t,tile) || |
1115 if (CheckFree2x2Area(t,tile) || |
1116 CheckFree2x2Area(t,(tile+=TILE_XY(-1,0))) || |
1116 CheckFree2x2Area(t,(tile+=TILE_XY(-1,0))) || |
1117 CheckFree2x2Area(t,(tile+=TILE_XY(0,-1))) || |
1117 CheckFree2x2Area(t,(tile+=TILE_XY(0,-1))) || |
1118 CheckFree2x2Area(t,(tile+=TILE_XY(1,0)))) |
1118 CheckFree2x2Area(t,(tile+=TILE_XY(1,0)))) |
1119 break; |
1119 break; |
1120 tile += TILE_XY(0,1); |
1120 tile += TILE_XY(0,1); |
1121 } else if (_housetype_extra_flags[house]&4) { |
1121 } else if (_housetype_extra_flags[house]&4) { |
1122 if (CheckBuildHouseMode(t, tile+TILE_XY(1,0), slope, 0)) |
1122 if (CheckBuildHouseMode(t, tile+TILE_XY(1,0), slope, 0)) |
1123 break; |
1123 break; |
1124 |
1124 |
1125 if (CheckBuildHouseMode(t, tile+TILE_XY(-1,0), slope, 1)) { |
1125 if (CheckBuildHouseMode(t, tile+TILE_XY(-1,0), slope, 1)) { |
1126 tile += TILE_XY(-1,0); |
1126 tile += TILE_XY(-1,0); |
1127 break; |
1127 break; |
1128 } |
1128 } |
1129 } else if (_housetype_extra_flags[house]&8) { |
1129 } else if (_housetype_extra_flags[house]&8) { |
1141 |
1141 |
1142 t->num_houses++; |
1142 t->num_houses++; |
1143 |
1143 |
1144 // Special houses that there can be only one of. |
1144 // Special houses that there can be only one of. |
1145 t->flags12 |= oneof; |
1145 t->flags12 |= oneof; |
1146 |
1146 |
1147 { |
1147 { |
1148 int m3lo,m5,eflags; |
1148 int m3lo,m5,eflags; |
1149 |
1149 |
1150 // ENDING_2 |
1150 // ENDING_2 |
1151 m3lo = 0; |
1151 m3lo = 0; |
1152 m5 = 0; |
1152 m5 = 0; |
1153 if (_generating_world) { |
1153 if (_generating_world) { |
1154 uint32 r = Random(); |
1154 uint32 r = Random(); |
1155 |
1155 |
1156 // Value for map3lo |
1156 // Value for map3lo |
1157 m3lo = 0xC0; |
1157 m3lo = 0xC0; |
1158 if ((byte)r >= 220) m3lo &= (r>>8); |
1158 if ((byte)r >= 220) m3lo &= (r>>8); |
1159 |
1159 |
1160 if (m3lo == 0xC0) |
1160 if (m3lo == 0xC0) |
1161 ChangePopulation(t, _housetype_population[house]); |
1161 ChangePopulation(t, _housetype_population[house]); |
1162 |
1162 |
1163 // Initial value for map5. |
1163 // Initial value for map5. |
1164 m5 = (r >> 16) & 0x3F; |
1164 m5 = (r >> 16) & 0x3F; |
1165 } |
1165 } |
1166 |
1166 |
1167 assert(IS_TILETYPE(tile, MP_CLEAR)); |
1167 assert(IS_TILETYPE(tile, MP_CLEAR)); |
1168 |
1168 |
1169 ModifyTile(tile, |
1169 ModifyTile(tile, |
1170 MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
1170 MP_SETTYPE(MP_HOUSE) | MP_MAP2 | MP_MAP3LO | MP_MAP3HI_CLEAR | MP_MAP5 | MP_MAPOWNER, |
1171 house, /* map2 */ |
1171 house, /* map2 */ |
1172 m3lo, /* map3_lo */ |
1172 m3lo, /* map3_lo */ |
1173 0, /* map_owner */ |
1173 0, /* map_owner */ |
1174 m5 /* map5 */ |
1174 m5 /* map5 */ |
1214 } |
1214 } |
1215 |
1215 |
1216 static bool BuildTownHouse(Town *t, uint tile) |
1216 static bool BuildTownHouse(Town *t, uint tile) |
1217 { |
1217 { |
1218 int32 r; |
1218 int32 r; |
1219 |
1219 |
1220 // make sure it's possible |
1220 // make sure it's possible |
1221 if (!EnsureNoVehicle(tile)) return false; |
1221 if (!EnsureNoVehicle(tile)) return false; |
1222 if (GetTileSlope(tile, NULL) & 0x10) return false; |
1222 if (GetTileSlope(tile, NULL) & 0x10) return false; |
1223 |
1223 |
1224 r = DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); |
1224 r = DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR); |
1256 } else if (_housetype_extra_flags[house-3] & 0x10) { |
1256 } else if (_housetype_extra_flags[house-3] & 0x10) { |
1257 house-=3; |
1257 house-=3; |
1258 tile += TILE_XY(-1,-1); |
1258 tile += TILE_XY(-1,-1); |
1259 } |
1259 } |
1260 } |
1260 } |
1261 |
1261 |
1262 // Remove population from the town if the |
1262 // Remove population from the town if the |
1263 // house is finished. |
1263 // house is finished. |
1264 if ((~_map3_lo[tile] & 0xC0) == 0) { |
1264 if ((~_map3_lo[tile] & 0xC0) == 0) { |
1265 ChangePopulation(t, -_housetype_population[house]); |
1265 ChangePopulation(t, -_housetype_population[house]); |
1266 } |
1266 } |
1271 if (house == 0x5B || house == 0x53 || house == 0x3C || |
1271 if (house == 0x5B || house == 0x53 || house == 0x3C || |
1272 house == 0x3D || house == 0x03) |
1272 house == 0x3D || house == 0x03) |
1273 t->flags12 &= ~2; |
1273 t->flags12 &= ~2; |
1274 if (house == 0x14 || house == 0x20) |
1274 if (house == 0x14 || house == 0x20) |
1275 t->flags12 &= ~4; |
1275 t->flags12 &= ~4; |
1276 |
1276 |
1277 // Do the actual clearing of tiles |
1277 // Do the actual clearing of tiles |
1278 eflags = _housetype_extra_flags[house]; |
1278 eflags = _housetype_extra_flags[house]; |
1279 DoClearTownHouseHelper(tile); |
1279 DoClearTownHouseHelper(tile); |
1280 if (eflags & 0x14) DoClearTownHouseHelper(tile + TILE_XY(1,0)); |
1280 if (eflags & 0x14) DoClearTownHouseHelper(tile + TILE_XY(1,0)); |
1281 if (eflags & 0x18) DoClearTownHouseHelper(tile + TILE_XY(0,1)); |
1281 if (eflags & 0x18) DoClearTownHouseHelper(tile + TILE_XY(0,1)); |
1284 |
1284 |
1285 int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
1285 int32 CmdRenameTown(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
1286 { |
1286 { |
1287 StringID str; |
1287 StringID str; |
1288 Town *t = DEREF_TOWN(p1); |
1288 Town *t = DEREF_TOWN(p1); |
1289 |
1289 |
1290 str = AllocateName((byte*)_decode_parameters, 4); |
1290 str = AllocateName((byte*)_decode_parameters, 4); |
1291 if (str == 0) |
1291 if (str == 0) |
1292 return CMD_ERROR; |
1292 return CMD_ERROR; |
1293 |
1293 |
1294 if (flags & DC_EXEC) { |
1294 if (flags & DC_EXEC) { |
1347 void ExpandTown(Town *t) |
1347 void ExpandTown(Town *t) |
1348 { |
1348 { |
1349 int amount, n; |
1349 int amount, n; |
1350 |
1350 |
1351 _generating_world = true; |
1351 _generating_world = true; |
1352 |
1352 |
1353 amount = ((int)Random()&3) + 3; |
1353 amount = ((int)Random()&3) + 3; |
1354 t->num_houses += amount; |
1354 t->num_houses += amount; |
1355 UpdateTownRadius(t); |
1355 UpdateTownRadius(t); |
1356 |
1356 |
1357 n = amount * 4; |
1357 n = amount * 4; |
1372 |
1372 |
1373 static void TownActionAdvertise(Town *t, int action) |
1373 static void TownActionAdvertise(Town *t, int action) |
1374 { |
1374 { |
1375 static const byte _advertising_amount[3] = {0x40, 0x70, 0xA0}; |
1375 static const byte _advertising_amount[3] = {0x40, 0x70, 0xA0}; |
1376 static const byte _advertising_radius[3] = {10,15,20}; |
1376 static const byte _advertising_radius[3] = {10,15,20}; |
1377 ModifyStationRatingAround(t->xy, _current_player, |
1377 ModifyStationRatingAround(t->xy, _current_player, |
1378 _advertising_amount[action], |
1378 _advertising_amount[action], |
1379 _advertising_radius[action]); |
1379 _advertising_radius[action]); |
1380 } |
1380 } |
1381 |
1381 |
1382 static void TownActionRoadRebuild(Town *t, int action) |
1382 static void TownActionRoadRebuild(Town *t, int action) |
1383 { |
1383 { |
1384 Player *p; |
1384 Player *p; |
1385 |
1385 |
1386 t->road_build_months = 6; |
1386 t->road_build_months = 6; |
1387 |
1387 |
1388 SET_DPARAM16(0, t->index); |
1388 SET_DPARAM16(0, t->index); |
1389 |
1389 |
1390 p = DEREF_PLAYER(_current_player); |
1390 p = DEREF_PLAYER(_current_player); |
1391 SET_DPARAM16(1, p->name_1); |
1391 SET_DPARAM16(1, p->name_1); |
1392 SET_DPARAM32(2, p->name_2); |
1392 SET_DPARAM32(2, p->name_2); |
1393 |
1393 |
1394 AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING, |
1394 AddNewsItem(STR_2055_TRAFFIC_CHAOS_IN_ROAD_REBUILDING, |
1395 NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_GENERAL, 0), t->xy, 0); |
1395 NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_GENERAL, 0), t->xy, 0); |
1396 } |
1396 } |
1397 |
1397 |
1398 static bool DoBuildStatueOfCompany(uint tile) |
1398 static bool DoBuildStatueOfCompany(uint tile) |
1399 { |
1399 { |
1427 static void TownActionBuildStatue(Town *t, int action) |
1427 static void TownActionBuildStatue(Town *t, int action) |
1428 { |
1428 { |
1429 // Layouted as an outward spiral |
1429 // Layouted as an outward spiral |
1430 static const TileIndexDiff _statue_tiles[] = { |
1430 static const TileIndexDiff _statue_tiles[] = { |
1431 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
1431 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
1432 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
1432 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
1433 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1433 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1434 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1434 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1435 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1435 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1436 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1436 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1437 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1437 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1438 TILE_XY(0,1), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
1438 TILE_XY(0,1), TILE_XY(0,1), TILE_XY(1,0), TILE_XY(1,0), |
1439 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1439 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1440 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1440 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1441 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
1441 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(-1,0), TILE_XY(-1,0), |
1442 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1442 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1443 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1443 TILE_XY(-1,0), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1444 TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1444 TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), TILE_XY(0,1), |
1445 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1445 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1446 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1446 TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), TILE_XY(1,0), |
1447 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1447 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1448 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1448 TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), TILE_XY(0,-1), |
1449 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1449 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1450 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1450 TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), TILE_XY(-1,0), |
1451 0, |
1451 0, |
1452 }; |
1452 }; |
1453 int offs; |
1453 int offs; |
1655 Town *ClosestTownFromTile(uint tile, uint threshold) |
1655 Town *ClosestTownFromTile(uint tile, uint threshold) |
1656 { |
1656 { |
1657 Town *t; |
1657 Town *t; |
1658 uint dist, best = threshold; |
1658 uint dist, best = threshold; |
1659 Town *best_town = NULL; |
1659 Town *best_town = NULL; |
1660 |
1660 |
1661 FOR_ALL_TOWNS(t) { |
1661 FOR_ALL_TOWNS(t) { |
1662 if (t->xy != 0) { |
1662 if (t->xy != 0) { |
1663 dist = GetTileDist(tile, t->xy); |
1663 dist = GetTileDist(tile, t->xy); |
1664 if (dist < best) { |
1664 if (dist < best) { |
1665 best = dist; |
1665 best = dist; |
1678 // if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff |
1678 // if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff |
1679 if (t == NULL || _current_player >= MAX_PLAYERS || (_cheats.magic_bulldozer.value && add < 0) ) |
1679 if (t == NULL || _current_player >= MAX_PLAYERS || (_cheats.magic_bulldozer.value && add < 0) ) |
1680 return; |
1680 return; |
1681 |
1681 |
1682 SETBIT(t->have_ratings, _current_player); |
1682 SETBIT(t->have_ratings, _current_player); |
1683 |
1683 |
1684 rating = t->ratings[_current_player]; |
1684 rating = t->ratings[_current_player]; |
1685 |
1685 |
1686 if (add < 0) { |
1686 if (add < 0) { |
1687 if (rating > max) { |
1687 if (rating > max) { |
1688 rating += add; |
1688 rating += add; |
1689 if (rating < max) rating = max; |
1689 if (rating < max) rating = max; |
1690 } |
1690 } |
1712 // if magic_bulldozer cheat is active, town doesn't restrict your destructive actions |
1712 // if magic_bulldozer cheat is active, town doesn't restrict your destructive actions |
1713 if (t == NULL || _current_player >= MAX_PLAYERS || _cheats.magic_bulldozer.value) |
1713 if (t == NULL || _current_player >= MAX_PLAYERS || _cheats.magic_bulldozer.value) |
1714 return true; |
1714 return true; |
1715 |
1715 |
1716 /* check if you're allowed to remove the street/bridge/tunnel/industry |
1716 /* check if you're allowed to remove the street/bridge/tunnel/industry |
1717 * owned by a town no removal if rating is lower than ... depends now on |
1717 * owned by a town no removal if rating is lower than ... depends now on |
1718 * difficulty setting. Minimum town rating selected by difficulty level |
1718 * difficulty setting. Minimum town rating selected by difficulty level |
1719 */ |
1719 */ |
1720 modemod = _default_rating_settings[_opt_mod_ptr->diff.town_council_tolerance][type]; |
1720 modemod = _default_rating_settings[_opt_mod_ptr->diff.town_council_tolerance][type]; |
1721 |
1721 |
1722 if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { |
1722 if (t->ratings[_current_player] < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) { |
1783 |
1783 |
1784 |
1784 |
1785 // Save and load of towns. |
1785 // Save and load of towns. |
1786 static const byte _town_desc[] = { |
1786 static const byte _town_desc[] = { |
1787 SLE_VAR(Town,xy, SLE_UINT16), |
1787 SLE_VAR(Town,xy, SLE_UINT16), |
1788 |
1788 |
1789 SLE_CONDVAR(Town,population, SLE_FILE_U16 | SLE_VAR_U32, 0, 2), |
1789 SLE_CONDVAR(Town,population, SLE_FILE_U16 | SLE_VAR_U32, 0, 2), |
1790 SLE_CONDVAR(Town,population, SLE_UINT32, 3, 255), |
1790 SLE_CONDVAR(Town,population, SLE_UINT32, 3, 255), |
1791 |
1791 |
1792 |
1792 |
1793 SLE_VAR(Town,num_houses, SLE_UINT16), |
1793 SLE_VAR(Town,num_houses, SLE_UINT16), |