Skip to content

Commit b51cfaf

Browse files
committed
Fix rare case where houses would become corrupted and possibly crash
1 parent 5d90641 commit b51cfaf

File tree

4 files changed

+50
-34
lines changed

4 files changed

+50
-34
lines changed

src/building/destruction.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,17 @@ void building_destroy_by_rioter(building *b)
159159

160160
int building_destroy_first_of_type(building_type type)
161161
{
162-
building *b = building_first_of_type(type);
163-
if (!b) {
164-
return 0;
162+
for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
163+
if (b->state != BUILDING_STATE_IN_USE && b->state != BUILDING_STATE_MOTHBALLED) {
164+
continue;
165+
}
166+
int grid_offset = b->grid_offset;
167+
game_undo_disable();
168+
building_destroy_by_collapse(b);
169+
map_routing_update_land();
170+
return grid_offset;
165171
}
166-
int grid_offset = b->grid_offset;
167-
game_undo_disable();
168-
building_destroy_by_collapse(b);
169-
map_routing_update_land();
170-
return grid_offset;
172+
return 0;
171173
}
172174

173175
void building_destroy_last_placed(void)

src/building/house.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ void building_house_change_to_vacant_lot(building *house)
7474

7575
static void prepare_for_merge(int building_id, int num_tiles)
7676
{
77-
for (int i = 0; i < RESOURCE_MAX; i++) {
78-
merge_data.inventory[i] = 0;
77+
for (resource_type r = 0; r < RESOURCE_MAX; r++) {
78+
merge_data.inventory[r] = 0;
7979
}
8080
merge_data.population = 0;
8181
merge_data.sentiment = 0;
@@ -87,11 +87,11 @@ static void prepare_for_merge(int building_id, int num_tiles)
8787
if (house->id != building_id && house->house_size) {
8888
merge_data.population += house->house_population;
8989
merge_data.sentiment += house->house_population * house->sentiment.house_happiness;
90-
for (int inv = 0; inv < RESOURCE_MAX; inv++) {
91-
merge_data.inventory[inv] += house->resources[inv];
92-
house->house_population = 0;
93-
house->state = BUILDING_STATE_DELETED_BY_GAME;
90+
for (resource_type r = 0; r < RESOURCE_MAX; r++) {
91+
merge_data.inventory[r] += house->resources[r];
9492
}
93+
house->house_population = 0;
94+
house->state = BUILDING_STATE_DELETED_BY_GAME;
9595
}
9696
}
9797
}
@@ -108,8 +108,8 @@ static void merge(building *b)
108108
if (b->house_population) {
109109
b->sentiment.house_happiness = merge_data.sentiment / b->house_population;
110110
}
111-
for (int i = 0; i < RESOURCE_MAX; i++) {
112-
b->resources[i] += merge_data.inventory[i];
111+
for (resource_type r = 0; r < RESOURCE_MAX; r++) {
112+
b->resources[r] += merge_data.inventory[r];
113113
}
114114
map_building_tiles_remove(b->id, b->x, b->y);
115115
b->x = merge_data.x;

src/city/buildings.c

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int city_buildings_get_closest_plague(int x, int y, int *distance)
125125
// Find closest in houses
126126
for (building_type type = BUILDING_HOUSE_SMALL_TENT; type <= BUILDING_HOUSE_LUXURY_PALACE; type++) {
127127
for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
128-
if (b->has_plague && b->distance_from_entry) {
128+
if (b->state == BUILDING_STATE_IN_USE && b->has_plague && b->distance_from_entry) {
129129
int dist = calc_maximum_distance(x, y, b->x, b->y);
130130
if (b->figure_id4) {
131131
if (dist < min_occupied_dist) {
@@ -144,7 +144,7 @@ int city_buildings_get_closest_plague(int x, int y, int *distance)
144144
for (size_t i = 0 ; i < NUM_PLAGUE_BUILDINGS; i++) {
145145
building_type type = PLAGUE_BUILDINGS[i];
146146
for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
147-
if (b->has_plague && b->distance_from_entry) {
147+
if (b->state == BUILDING_STATE_IN_USE && b->has_plague && b->distance_from_entry) {
148148
int dist = calc_maximum_distance(x, y, b->x, b->y);
149149
if (b->figure_id4) {
150150
if (dist < min_occupied_dist) {
@@ -170,19 +170,21 @@ static void update_sickness_duration(int building_id)
170170
{
171171
building *b = building_get(building_id);
172172

173-
if (b->has_plague) {
174-
// Stop plague after time or if doctor heals it
175-
if (b->sickness_duration == 99) {
176-
b->sickness_duration = 0;
177-
b->has_plague = 0;
178-
b->sickness_level = 0;
179-
b->sickness_doctor_cure = 0;
180-
b->figure_id4 = 0;
181-
b->fumigation_frame = 0;
182-
b->fumigation_direction = 0;
183-
} else {
184-
b->sickness_duration += 1;
185-
}
173+
if (b->state != BUILDING_STATE_IN_USE || !b->has_plague) {
174+
return;
175+
}
176+
177+
// Stop plague after time or if doctor heals it
178+
if (b->sickness_duration == 99) {
179+
b->sickness_duration = 0;
180+
b->has_plague = 0;
181+
b->sickness_level = 0;
182+
b->sickness_doctor_cure = 0;
183+
b->figure_id4 = 0;
184+
b->fumigation_frame = 0;
185+
b->fumigation_direction = 0;
186+
} else {
187+
b->sickness_duration += 1;
186188
}
187189
}
188190

src/figuretype/migrant.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,19 @@ static int closest_house_with_room(int x, int y)
9696
return min_building_id;
9797
}
9898

99+
int house_is_valid(const building *b, int figure_id)
100+
{
101+
return b && b->state == BUILDING_STATE_IN_USE &&
102+
b->immigrant_figure_id == figure_id && b->house_size > 0 && !b->has_plague;
103+
}
104+
99105
void figure_immigrant_action(figure *f)
100106
{
101107
building *b = building_get(f->immigrant_building_id);
102108

103109
f->terrain_usage = TERRAIN_USAGE_ANY;
104110
f->cart_image_id = 0;
105-
if (b->state != BUILDING_STATE_IN_USE || b->immigrant_figure_id != f->id || !b->house_size || b->has_plague) {
111+
if (!house_is_valid(b, f->id)) {
106112
f->state = FIGURE_STATE_DEAD;
107113
return;
108114
}
@@ -278,7 +284,11 @@ void figure_homeless_action(figure *f)
278284
case FIGURE_ACTION_8_HOMELESS_GOING_TO_HOUSE:
279285
f->is_ghost = 0;
280286
figure_movement_move_ticks(f, 1);
281-
if (f->direction == DIR_FIGURE_REROUTE || f->direction == DIR_FIGURE_LOST) {
287+
if (!house_is_valid(building_get(f->immigrant_building_id), f->id)) {
288+
figure_route_remove(f);
289+
f->action_state = FIGURE_ACTION_7_HOMELESS_CREATED;
290+
f->wait_ticks = 30;
291+
} else if (f->direction == DIR_FIGURE_REROUTE || f->direction == DIR_FIGURE_LOST) {
282292
building_get(f->immigrant_building_id)->immigrant_figure_id = 0;
283293
f->state = FIGURE_STATE_DEAD;
284294
} else if (f->direction == DIR_FIGURE_AT_DESTINATION) {
@@ -291,7 +301,9 @@ void figure_homeless_action(figure *f)
291301
case FIGURE_ACTION_9_HOMELESS_ENTERING_HOUSE:
292302
f->use_cross_country = 1;
293303
f->is_ghost = 1;
294-
if (figure_movement_move_ticks_cross_country(f, 1) == 1) {
304+
if (!house_is_valid(building_get(f->immigrant_building_id), f->id)) {
305+
f->state = FIGURE_STATE_DEAD;
306+
} else if (figure_movement_move_ticks_cross_country(f, 1) == 1) {
295307
f->state = FIGURE_STATE_DEAD;
296308
building *b = building_get(f->immigrant_building_id);
297309
if (f->immigrant_building_id && building_is_house(b->type) && !b->has_plague) {

0 commit comments

Comments
 (0)