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