1 #include "construction_clear.h"
2
3 #include "building/building.h"
4 #include "city/warning.h"
5 #include "core/config.h"
6 #include "figuretype/migrant.h"
7 #include "game/undo.h"
8 #include "graphics/window.h"
9 #include "map/aqueduct.h"
10 #include "map/bridge.h"
11 #include "map/building.h"
12 #include "map/building_tiles.h"
13 #include "map/grid.h"
14 #include "map/property.h"
15 #include "map/routing_terrain.h"
16 #include "map/terrain.h"
17 #include "map/tiles.h"
18 #include "window/popup_dialog.h"
19
20 static struct {
21 int x_start;
22 int y_start;
23 int x_end;
24 int y_end;
25 int bridge_confirmed;
26 int fort_confirmed;
27 } confirm;
28
get_deletable_building(int grid_offset)29 static building *get_deletable_building(int grid_offset)
30 {
31 int building_id = map_building_at(grid_offset);
32 if (!building_id) {
33 return 0;
34 }
35 building *b = building_main(building_get(building_id));
36 if (b->type == BUILDING_BURNING_RUIN || b->type == BUILDING_NATIVE_CROPS ||
37 b->type == BUILDING_NATIVE_HUT || b->type == BUILDING_NATIVE_MEETING) {
38 return 0;
39 }
40 if (b->state == BUILDING_STATE_DELETED_BY_PLAYER || b->is_deleted) {
41 return 0;
42 }
43 return b;
44 }
45
clear_land_confirmed(int measure_only,int x_start,int y_start,int x_end,int y_end)46 static int clear_land_confirmed(int measure_only, int x_start, int y_start, int x_end, int y_end)
47 {
48 int items_placed = 0;
49 game_undo_restore_building_state();
50 game_undo_restore_map(0);
51
52 int x_min, x_max, y_min, y_max;
53 map_grid_start_end_to_area(x_start, y_start, x_end, y_end, &x_min, &y_min, &x_max, &y_max);
54
55 int visual_feedback_on_delete = config_get(CONFIG_UI_VISUAL_FEEDBACK_ON_DELETE);
56
57 for (int y = y_min; y <= y_max; y++) {
58 for (int x = x_min; x <= x_max; x++) {
59 int grid_offset = map_grid_offset(x, y);
60 if (measure_only && visual_feedback_on_delete) {
61 building *b = get_deletable_building(grid_offset);
62 if (map_property_is_deleted(grid_offset) || (b && map_property_is_deleted(b->grid_offset))) {
63 continue;
64 }
65 map_building_tiles_mark_deleting(grid_offset);
66 if (map_terrain_is(grid_offset, TERRAIN_BUILDING)) {
67 if (b) {
68 items_placed++;
69 }
70 } else if (map_terrain_is(grid_offset, TERRAIN_ROCK | TERRAIN_ELEVATION)) {
71 continue;
72 } else if (map_terrain_is(grid_offset, TERRAIN_WATER)) { // keep the "bridge is free" bug from C3
73 continue;
74 } else if (map_terrain_is(grid_offset, TERRAIN_AQUEDUCT)
75 || map_terrain_is(grid_offset, TERRAIN_NOT_CLEAR)) {
76 items_placed++;
77 }
78 continue;
79 }
80 if (map_terrain_is(grid_offset, TERRAIN_ROCK | TERRAIN_ELEVATION)) {
81 continue;
82 }
83 if (map_terrain_is(grid_offset, TERRAIN_BUILDING)) {
84 building *b = get_deletable_building(grid_offset);
85 if (!b) {
86 continue;
87 }
88 if (b->type == BUILDING_FORT_GROUND || b->type == BUILDING_FORT) {
89 if (!measure_only && confirm.fort_confirmed != 1) {
90 continue;
91 }
92 if (!measure_only && confirm.fort_confirmed == 1) {
93 game_undo_disable();
94 }
95 }
96 if (b->house_size && b->house_population && !measure_only) {
97 figure_create_homeless(b->x, b->y, b->house_population);
98 b->house_population = 0;
99 }
100 if (b->state != BUILDING_STATE_DELETED_BY_PLAYER) {
101 items_placed++;
102 game_undo_add_building(b);
103 }
104 b->state = BUILDING_STATE_DELETED_BY_PLAYER;
105 b->is_deleted = 1;
106 building *space = b;
107 for (int i = 0; i < 9; i++) {
108 if (space->prev_part_building_id <= 0) {
109 break;
110 }
111 space = building_get(space->prev_part_building_id);
112 game_undo_add_building(space);
113 space->state = BUILDING_STATE_DELETED_BY_PLAYER;
114 }
115 space = b;
116 for (int i = 0; i < 9; i++) {
117 space = building_next(space);
118 if (space->id <= 0) {
119 break;
120 }
121 game_undo_add_building(space);
122 space->state = BUILDING_STATE_DELETED_BY_PLAYER;
123 }
124 } else if (map_terrain_is(grid_offset, TERRAIN_AQUEDUCT)) {
125 map_terrain_remove(grid_offset, TERRAIN_CLEARABLE);
126 items_placed++;
127 map_aqueduct_remove(grid_offset);
128 } else if (map_terrain_is(grid_offset, TERRAIN_WATER)) {
129 if (!measure_only && map_bridge_count_figures(grid_offset) > 0) {
130 city_warning_show(WARNING_PEOPLE_ON_BRIDGE);
131 } else if (confirm.bridge_confirmed == 1) {
132 map_bridge_remove(grid_offset, measure_only);
133 items_placed++;
134 }
135 } else if (map_terrain_is(grid_offset, TERRAIN_NOT_CLEAR)) {
136 if (map_terrain_is(grid_offset, TERRAIN_ROAD)) {
137 map_property_clear_plaza_or_earthquake(grid_offset);
138 }
139 map_terrain_remove(grid_offset, TERRAIN_CLEARABLE);
140 items_placed++;
141 }
142 }
143 }
144 if (!measure_only || !visual_feedback_on_delete) {
145 int radius;
146 if (x_max - x_min <= y_max - y_min) {
147 radius = y_max - y_min + 3;
148 } else {
149 radius = x_max - x_min + 3;
150 }
151 map_tiles_update_region_empty_land(x_min, y_min, x_max, y_max);
152 map_tiles_update_region_meadow(x_min, y_min, x_max, y_max);
153 map_tiles_update_region_rubble(x_min, y_min, x_max, y_max);
154 map_tiles_update_all_gardens();
155 map_tiles_update_area_roads(x_min, y_min, radius);
156 map_tiles_update_all_plazas();
157 map_tiles_update_area_walls(x_min, y_min, radius);
158 map_tiles_update_region_aqueducts(x_min - 3, y_min - 3, x_max + 3, y_max + 3);
159 }
160 if (!measure_only) {
161 map_routing_update_land();
162 map_routing_update_walls();
163 map_routing_update_water();
164 window_invalidate();
165 }
166 return items_placed;
167 }
168
confirm_delete_fort(int accepted)169 static void confirm_delete_fort(int accepted)
170 {
171 if (accepted == 1) {
172 confirm.fort_confirmed = 1;
173 } else {
174 confirm.fort_confirmed = -1;
175 }
176 clear_land_confirmed(0, confirm.x_start, confirm.y_start, confirm.x_end, confirm.y_end);
177 }
178
confirm_delete_bridge(int accepted)179 static void confirm_delete_bridge(int accepted)
180 {
181 if (accepted == 1) {
182 confirm.bridge_confirmed = 1;
183 } else {
184 confirm.bridge_confirmed = -1;
185 }
186 clear_land_confirmed(0, confirm.x_start, confirm.y_start, confirm.x_end, confirm.y_end);
187 }
188
building_construction_clear_land(int measure_only,int x_start,int y_start,int x_end,int y_end)189 int building_construction_clear_land(int measure_only, int x_start, int y_start, int x_end, int y_end)
190 {
191 confirm.fort_confirmed = 0;
192 confirm.bridge_confirmed = 0;
193 if (measure_only) {
194 return clear_land_confirmed(measure_only, x_start, y_start, x_end, y_end);
195 }
196
197 int x_min, x_max, y_min, y_max;
198 map_grid_start_end_to_area(x_start, y_start, x_end, y_end, &x_min, &y_min, &x_max, &y_max);
199
200 int ask_confirm_bridge = 0;
201 int ask_confirm_fort = 0;
202 for (int y = y_min; y <= y_max; y++) {
203 for (int x = x_min; x <= x_max; x++) {
204 int grid_offset = map_grid_offset(x, y);
205 int building_id = map_building_at(grid_offset);
206 if (building_id) {
207 building *b = building_get(building_id);
208 if (b->type == BUILDING_FORT || b->type == BUILDING_FORT_GROUND) {
209 ask_confirm_fort = 1;
210 }
211 }
212 if (map_is_bridge(grid_offset)) {
213 ask_confirm_bridge = 1;
214 }
215 }
216 }
217 confirm.x_start = x_start;
218 confirm.y_start = y_start;
219 confirm.x_end = x_end;
220 confirm.y_end = y_end;
221 if (ask_confirm_fort) {
222 window_popup_dialog_show(POPUP_DIALOG_DELETE_FORT, confirm_delete_fort, 2);
223 return -1;
224 } else if (ask_confirm_bridge) {
225 window_popup_dialog_show(POPUP_DIALOG_DELETE_BRIDGE, confirm_delete_bridge, 2);
226 return -1;
227 } else {
228 return clear_land_confirmed(measure_only, x_start, y_start, x_end, y_end);
229 }
230 }
231