Skip to content

Commit 901b192

Browse files
committed
city: moved fire/collapse logic to city_maintenance class
1 parent b9bf38e commit 901b192

20 files changed

+232
-197
lines changed

src/building/building.cpp

+98-5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "core/object_property.h"
4040
#include "graphics/view/view.h"
4141
#include "config/config.h"
42+
#include "core/random.h"
43+
#include "sound/sound.h"
4244

4345
#include <string.h>
4446
#include <map>
@@ -52,7 +54,7 @@ void game_cheat_destroy_type(std::istream &is, std::ostream &os) {
5254
int type = atoi(args.empty() ? (pcstr)"0" : args.c_str());
5355

5456
buildings_valid_do([] (building &b) {
55-
building_destroy_by_collapse(&b);
57+
b.destroy_by_collapse();
5658
}, (e_building_type)type);
5759
};
5860

@@ -231,12 +233,18 @@ building::building() {
231233
}
232234

233235
building* building::main() {
236+
if (prev_part_building_id <= 0) {
237+
return this;
238+
}
239+
234240
building* b = this;
235241
for (int guard = 0; guard < 99; guard++) {
236-
if (b->prev_part_building_id <= 0)
242+
if (b->prev_part_building_id <= 0) {
237243
return b;
244+
}
238245
b = building_get(b->prev_part_building_id);
239246
}
247+
240248
return building_get(0);
241249
}
242250

@@ -506,10 +514,95 @@ bool building::workshop_has_resources() {
506514
return has_second_material && hase_first_resource;
507515
}
508516

517+
void building::destroy_by_collapse() {
518+
assert(is_main());
519+
state = BUILDING_STATE_RUBBLE;
520+
map_building_tiles_set_rubble(id, tile, size);
521+
figure_create_explosion_cloud(tile, size);
522+
destroy_linked_parts(false);
523+
g_sound.play_effect(SOUND_EFFECT_EXPLOSION);
524+
}
525+
526+
void building::destroy_on_fire_impl(bool plagued) {
527+
game_undo_disable();
528+
fire_risk = 0;
529+
damage_risk = 0;
530+
531+
//int was_tent = b->house_size && b->data.house.level <= HOUSE_STURDY_HUT;
532+
state = BUILDING_STATE_DELETED_BY_GAME;
533+
output_resource_first_id = RESOURCE_NONE;
534+
output_resource_second_id = RESOURCE_NONE;
535+
distance_from_entry = 0;
536+
clear_related_data();
537+
538+
int waterside_building = 0;
539+
if (type == BUILDING_DOCK || type == BUILDING_FISHING_WHARF || type == BUILDING_SHIPWRIGHT) {
540+
waterside_building = 1;
541+
}
542+
543+
map_building_tiles_remove(id, tile);
544+
unsigned int rand_int = random_short();
545+
546+
grid_area varea = map_grid_get_area(tile, size, 0);
547+
map_grid_area_foreach(varea, [plagued] (tile2i tile) {
548+
if (map_terrain_is(tile, TERRAIN_WATER)) {
549+
return;
550+
}
551+
552+
// FIXME: possible can't render image & fire animation
553+
building *ruin = building_create(BUILDING_BURNING_RUIN, tile, 0);
554+
ruin->has_plague = plagued;
555+
});
556+
557+
if (waterside_building) {
558+
map_routing_update_water();
559+
}
560+
}
561+
562+
void building::destroy_by_fire() {
563+
assert(is_main());
564+
destroy_on_fire_impl(false);
565+
destroy_linked_parts(true);
566+
g_sound.play_effect(SOUND_EFFECT_EXPLOSION);
567+
}
568+
569+
void building::destroy_linked_parts(bool on_fire) {
570+
building *part = this;
571+
for (int i = 0; i < 99; i++) {
572+
if (part->prev_part_building_id <= 0) {
573+
break;
574+
}
575+
576+
int part_id = part->prev_part_building_id;
577+
part = building_get(part_id);
578+
if (on_fire) {
579+
part->destroy_on_fire_impl(false);
580+
} else {
581+
map_building_tiles_set_rubble(part_id, part->tile, part->size);
582+
part->state = BUILDING_STATE_RUBBLE;
583+
}
584+
}
585+
586+
part = this;
587+
for (int i = 0; i < 99; i++) {
588+
part = part->next();
589+
if (part->id <= 0) {
590+
break;
591+
}
592+
593+
if (on_fire) {
594+
part->destroy_on_fire_impl(false);
595+
} else {
596+
map_building_tiles_set_rubble(part->id, part->tile, part->size);
597+
part->state = BUILDING_STATE_RUBBLE;
598+
}
599+
}
600+
}
601+
509602
void building::mark_plague(int days) {
510-
auto m = main();
511-
m->disease_days = days;
512-
m->has_plague = true;
603+
assert(is_main());
604+
disease_days = days;
605+
has_plague = true;
513606
}
514607

515608
pcstr building::cls_name() const {

src/building/building.h

+7
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ class building {
294294
bool common_spawn_goods_output_cartpusher(bool only_one = true, bool only_full_loads = true, int min_carry = 100, int max_carry = 800);
295295
bool workshop_has_resources();
296296

297+
void destroy_by_collapse();
298+
void destroy_by_fire();
299+
297300
void mark_plague(int days);
298301

299302
public:
@@ -368,6 +371,10 @@ class building {
368371
_ptr = (building_impl *)&_ptr_buffer;
369372
return _ptr;
370373
}
374+
375+
private:
376+
void destroy_on_fire_impl(bool plagued);
377+
void destroy_linked_parts(bool on_fire);
371378
};
372379

373380
#define BUILDING_METAINFO(type, clsid) static constexpr e_building_type TYPE = type; static constexpr pcstr CLSID = #clsid;

src/building/building_architect_post.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void console_command_collapse(std::istream &is, std::ostream &) {
4646

4747
int step = std::max<int>(1, (int)buildings.size() / count);
4848
for (int i = 0; i < buildings.size(); i += step) {
49-
building_destroy_by_collapse(buildings[i]);
49+
buildings[i]->destroy_by_collapse();
5050
}
5151
}
5252

src/building/building_burning_ruin.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ bool building_burning_ruin::update() {
142142
int grid_offset = tile().grid_offset();
143143
int next_building_id = map_building_at(grid_offset + map_grid_direction_delta(dir));
144144
if (next_building_id && !building_get(next_building_id)->fire_proof) {
145-
building_destroy_by_fire(building_get(next_building_id));
145+
building_get(next_building_id)->destroy_by_fire();
146146
return true;
147147
}
148148
}

src/building/building_debug_properties.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ void game_debug_show_properties_object(pcstr prefix, building *b) {
1616
ImGui::TableSetColumnIndex(1);
1717

1818
if (common_open) {
19-
game_debug_show_property("Untype/Destroy", [b] { building_destroy_by_collapse(b); });
19+
game_debug_show_property("Untype/Destroy", [b] { b->destroy_by_collapse(); });
2020
game_debug_show_property("id", b->id, true);
2121
game_debug_show_property("state", token::find_name(e_building_state_tokens, b->state));
2222
game_debug_show_property("size", b->size);

src/building/building_firehouse.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void console_command_startfire(std::istream &is, std::ostream &) {
3434

3535
int step = std::max<int>(1, (int)buildings.size() / count);
3636
for (int i = 0; i < buildings.size(); i += step) {
37-
building_destroy_by_fire(buildings[i]);
37+
buildings[i]->main()->destroy_by_fire();
3838
}
3939
}
4040

src/building/building_granary.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ void building_granary_storageyard_curse(int big) {
450450
if (big) {
451451
city_message_disable_sound_for_next_message();
452452
city_message_post(false, MESSAGE_FIRE, max_building->type, max_building->tile.grid_offset());
453-
building_destroy_by_fire(max_building);
453+
max_building->destroy_by_fire();
454454
map_routing_update_land();
455455
} else {
456456
if (max_building->type == BUILDING_STORAGE_YARD) {

src/building/building_house.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,15 @@ void building_house::on_create(int orientation) {
955955
}
956956
}
957957

958-
void building_house::on_place_checks() {
958+
void building_house::on_destroy() {
959+
g_city.population.remove_home_removed(house_population());
960+
961+
auto &d = runtime_data();
962+
d.population = 0;
963+
d.hsize = 0;
964+
}
965+
966+
void building_house::on_place_checks() {
959967
if (type() != BUILDING_HOUSE_VACANT_LOT) {
960968
return;
961969
}

src/building/building_house.h

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class building_house : public building_impl {
7777

7878
virtual void on_create(int orientation) override;
7979
//virtual void on_place(int orientation, int variant) override;
80+
virtual void on_destroy() override;
8081
virtual void on_place_checks() override;
8182
virtual e_sound_channel_city sound_channel() const override { return SOUND_CHANNEL_CITY_STATUE; }
8283
virtual void on_undo() override;

src/building/destruction.cpp

+2-97
Original file line numberDiff line numberDiff line change
@@ -21,94 +21,6 @@
2121
#include <core/random.h>
2222
#include <string.h>
2323

24-
static void destroy_on_fire(building* b, bool plagued) {
25-
game_undo_disable();
26-
b->fire_risk = 0;
27-
b->damage_risk = 0;
28-
29-
auto house = b->dcast_house();
30-
if (house) {
31-
auto &housed = house->runtime_data();
32-
if (housed.population > 0) {
33-
g_city.population.remove_home_removed(housed.population);
34-
housed.population = 0;
35-
housed.hsize = 0;
36-
}
37-
}
38-
39-
//int was_tent = b->house_size && b->data.house.level <= HOUSE_STURDY_HUT;
40-
b->state = BUILDING_STATE_DELETED_BY_GAME;
41-
b->output_resource_first_id = RESOURCE_NONE;
42-
b->output_resource_second_id = RESOURCE_NONE;
43-
b->distance_from_entry = 0;
44-
b->clear_related_data();
45-
46-
int waterside_building = 0;
47-
if (b->type == BUILDING_DOCK || b->type == BUILDING_FISHING_WHARF || b->type == BUILDING_SHIPWRIGHT) {
48-
waterside_building = 1;
49-
}
50-
51-
map_building_tiles_remove(b->id, b->tile);
52-
unsigned int rand_int = random_short();
53-
54-
grid_area varea = map_grid_get_area(b->tile, b->size, 0);
55-
map_grid_area_foreach(varea, [plagued] (tile2i tile) {
56-
if (map_terrain_is(tile, TERRAIN_WATER)) {
57-
return;
58-
}
59-
60-
// FIXME: possible can't render image & fire animation
61-
building *ruin = building_create(BUILDING_BURNING_RUIN, tile, 0);
62-
ruin->has_plague = plagued;
63-
});
64-
65-
if (waterside_building) {
66-
map_routing_update_water();
67-
}
68-
}
69-
70-
static void destroy_linked_parts(building* b, bool on_fire) {
71-
building* part = b;
72-
for (int i = 0; i < 99; i++) {
73-
if (part->prev_part_building_id <= 0) {
74-
break;
75-
}
76-
77-
int part_id = part->prev_part_building_id;
78-
part = building_get(part_id);
79-
if (on_fire) {
80-
destroy_on_fire(part, false);
81-
} else {
82-
map_building_tiles_set_rubble(part_id, part->tile, part->size);
83-
part->state = BUILDING_STATE_RUBBLE;
84-
}
85-
}
86-
87-
part = b;
88-
for (int i = 0; i < 99; i++) {
89-
part = part->next();
90-
if (part->id <= 0) {
91-
break;
92-
}
93-
94-
if (on_fire) {
95-
destroy_on_fire(part, false);
96-
} else {
97-
map_building_tiles_set_rubble(part->id, part->tile, part->size);
98-
part->state = BUILDING_STATE_RUBBLE;
99-
}
100-
}
101-
}
102-
103-
void building_destroy_by_collapse(building* b) {
104-
b = b->main();
105-
b->state = BUILDING_STATE_RUBBLE;
106-
map_building_tiles_set_rubble(b->id, b->tile, b->size);
107-
figure_create_explosion_cloud(b->tile, b->size);
108-
destroy_linked_parts(b, false);
109-
g_sound.play_effect(SOUND_EFFECT_EXPLOSION);
110-
}
111-
11224
void building_destroy_by_poof(building* b, bool clouds) {
11325
b = b->main();
11426
if (clouds) {
@@ -127,16 +39,9 @@ void building_destroy_by_poof(building* b, bool clouds) {
12739
} while (true);
12840
}
12941

130-
void building_destroy_by_fire(building* b) {
131-
b = b->main();
132-
destroy_on_fire(b, false);
133-
destroy_linked_parts(b, true);
134-
g_sound.play_effect(SOUND_EFFECT_EXPLOSION);
135-
}
136-
13742
void building_destroy_by_rioter(building* b) {
13843
b = b->main();
139-
destroy_on_fire(b, false);
44+
b->destroy_by_fire();
14045
}
14146

14247
int building_destroy_first_of_type(e_building_type type) {
@@ -186,7 +91,7 @@ void building_destroy_by_enemy(tile2i tile) {
18691
building* b = building_get(building_id);
18792
if (b->state == BUILDING_STATE_VALID) {
18893
g_city.ratings.monument_building_destroyed(b->type);
189-
building_destroy_by_collapse(b);
94+
b->destroy_by_collapse();
19095
}
19196
} else {
19297
if (map_terrain_is(tile, TERRAIN_WALL)) {

src/building/destruction.h

-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22

33
#include "building/building.h"
44

5-
void building_destroy_by_collapse(building* b);
6-
75
void building_destroy_by_poof(building* b, bool clouds);
86

9-
void building_destroy_by_fire(building* b);
10-
117
void building_destroy_by_rioter(building* b);
128

139
int building_destroy_first_of_type(e_building_type type);

0 commit comments

Comments
 (0)