39
39
#include " core/object_property.h"
40
40
#include " graphics/view/view.h"
41
41
#include " config/config.h"
42
+ #include " core/random.h"
43
+ #include " sound/sound.h"
42
44
43
45
#include < string.h>
44
46
#include < map>
@@ -52,7 +54,7 @@ void game_cheat_destroy_type(std::istream &is, std::ostream &os) {
52
54
int type = atoi (args.empty () ? (pcstr)" 0" : args.c_str ());
53
55
54
56
buildings_valid_do ([] (building &b) {
55
- building_destroy_by_collapse (&b );
57
+ b. destroy_by_collapse ( );
56
58
}, (e_building_type)type);
57
59
};
58
60
@@ -231,12 +233,18 @@ building::building() {
231
233
}
232
234
233
235
building* building::main () {
236
+ if (prev_part_building_id <= 0 ) {
237
+ return this ;
238
+ }
239
+
234
240
building* b = this ;
235
241
for (int guard = 0 ; guard < 99 ; guard++) {
236
- if (b->prev_part_building_id <= 0 )
242
+ if (b->prev_part_building_id <= 0 ) {
237
243
return b;
244
+ }
238
245
b = building_get (b->prev_part_building_id );
239
246
}
247
+
240
248
return building_get (0 );
241
249
}
242
250
@@ -506,10 +514,95 @@ bool building::workshop_has_resources() {
506
514
return has_second_material && hase_first_resource;
507
515
}
508
516
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
+
509
602
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 ;
513
606
}
514
607
515
608
pcstr building::cls_name () const {
0 commit comments