1
1
#include " catch/catch.hpp"
2
2
#include " map_helpers.h"
3
+ #include " monster_helpers.h"
3
4
#include " player_helpers.h"
4
5
#include " activity_scheduling_helper.h"
5
6
8
9
#include " calendar.h"
9
10
#include " character.h"
10
11
#include " flag.h"
12
+ #include " game.h"
11
13
#include " itype.h"
12
14
#include " iuse_actor.h"
13
15
#include " map.h"
14
16
#include " monster.h"
15
17
#include " point.h"
16
18
19
+ static const activity_id ACT_AIM ( " ACT_AIM" );
17
20
static const activity_id ACT_BOLTCUTTING ( " ACT_BOLTCUTTING" );
18
21
static const activity_id ACT_CRACKING ( " ACT_CRACKING" );
19
22
static const activity_id ACT_HACKSAW ( " ACT_HACKSAW" );
@@ -27,6 +30,8 @@ static const bionic_id bio_ears( "bio_ears" );
27
30
static const efftype_id effect_pet ( " pet" );
28
31
static const efftype_id effect_tied ( " tied" );
29
32
33
+ static const field_type_str_id field_fd_smoke ( " fd_smoke" );
34
+
30
35
static const furn_str_id furn_test_f_boltcut1 ( " test_f_boltcut1" );
31
36
static const furn_str_id furn_test_f_boltcut2 ( " test_f_boltcut2" );
32
37
static const furn_str_id furn_test_f_boltcut3 ( " test_f_boltcut3" );
@@ -38,8 +43,10 @@ static const furn_str_id furn_test_f_oxytorch2( "test_f_oxytorch2" );
38
43
static const furn_str_id furn_test_f_oxytorch3 ( " test_f_oxytorch3" );
39
44
static const furn_str_id furn_test_f_prying1 ( " test_f_prying1" );
40
45
46
+ static const itype_id itype_book_binder ( " book_binder" );
41
47
static const itype_id itype_glass_shard ( " glass_shard" );
42
48
static const itype_id itype_oxyacetylene ( " oxyacetylene" );
49
+ static const itype_id itype_tent_kit ( " tent_kit" );
43
50
static const itype_id itype_test_2x4 ( " test_2x4" );
44
51
static const itype_id itype_test_battery_disposable ( " test_battery_disposable" );
45
52
static const itype_id itype_test_boltcutter ( " test_boltcutter" );
@@ -54,11 +61,13 @@ static const itype_id itype_test_rag( "test_rag" );
54
61
static const itype_id itype_test_rock ( " test_rock" );
55
62
static const itype_id itype_test_shears ( " test_shears" );
56
63
static const itype_id itype_test_shears_off ( " test_shears_off" );
64
+ static const itype_id itype_water_clean ( " water_clean" );
57
65
58
66
static const json_character_flag json_flag_SUPER_HEARING ( " SUPER_HEARING" );
59
67
60
68
static const mtype_id mon_test_non_shearable ( " mon_test_non_shearable" );
61
69
static const mtype_id mon_test_shearable ( " mon_test_shearable" );
70
+ static const mtype_id mon_zombie ( " mon_zombie" );
62
71
63
72
static const proficiency_id proficiency_prof_safecracking ( " prof_safecracking" );
64
73
@@ -68,8 +77,11 @@ static const quality_id qual_SAW_M( "SAW_M" );
68
77
static const quality_id qual_SHEAR ( " SHEAR" );
69
78
static const quality_id qual_WELD ( " WELD" );
70
79
80
+ static const recipe_id recipe_water_clean ( " water_clean" );
81
+
71
82
static const skill_id skill_traps ( " traps" );
72
83
84
+ static const ter_str_id ter_t_wall ( " t_wall" );
73
85
static const ter_str_id ter_test_t_boltcut1 ( " test_t_boltcut1" );
74
86
static const ter_str_id ter_test_t_boltcut2 ( " test_t_boltcut2" );
75
87
static const ter_str_id ter_test_t_hacksaw1 ( " test_t_hacksaw1" );
@@ -1654,3 +1666,214 @@ TEST_CASE( "prying", "[activity][prying]" )
1654
1666
}
1655
1667
}
1656
1668
}
1669
+
1670
+ /* *
1671
+ * Helper method to create activity stubs that aren't meant to be processed.
1672
+ * The activities here still need to be able to pass activity_actor::start and
1673
+ * set activity::moves_left to a value greater than 0.
1674
+ * Some require a more complex setup for this, which is why they're commented out for now.
1675
+ * To enable them, the activity would need to be paired with a setup method to be called
1676
+ * before activity::start_or_resume to spawn necessary terrain/items/vehicles/etc.
1677
+ * Activity actors that use ui functionality in their start methods cannot work at all,
1678
+ * only affects workout_activity_actor right now
1679
+ */
1680
+ static std::vector<player_activity> get_test_activities ( avatar &dummy, map &m )
1681
+ {
1682
+ tripoint p = dummy.pos ();
1683
+ tripoint north = p + tripoint_north;
1684
+ map_cursor c ( p );
1685
+ item_location loc;
1686
+ std::vector<item_location> locs;
1687
+ // this currently only works because the bookbinder is used in the first activity
1688
+ // after that it's removed from the map
1689
+ item &binderit = m.add_item ( dummy.pos (), item ( itype_book_binder ) );
1690
+ item_location bookbinder ( c, &binderit );
1691
+
1692
+ std::vector<player_activity> res{
1693
+ // player_activity( autodrive_activity_actor() ),
1694
+ // player_activity( bikerack_racking_activity_actor() ),
1695
+ // player_activity( boltcutting_activity_actor( north, item_location() ) ),
1696
+ player_activity ( bookbinder_copy_activity_actor ( bookbinder, recipe_water_clean ) ),
1697
+ player_activity ( consume_activity_actor ( item ( itype_water_clean ) ) ),
1698
+ // player_activity( craft_activity_actor() ),
1699
+ player_activity ( dig_activity_actor ( 1 , p, " " , north, 0 , " " ) ),
1700
+ player_activity ( dig_channel_activity_actor ( 1 , p, " " , north, 0 , " " ) ),
1701
+ // player_activity( disable_activity_actor() ),
1702
+ // player_activity( disassemble_activity_actor( 1 ) ),
1703
+ player_activity ( drop_activity_actor () ),
1704
+ // player_activity( ebooksave_activity_actor( loc, loc ) ),
1705
+ player_activity ( firstaid_activity_actor ( 1 , std::string () ) ),
1706
+ player_activity ( forage_activity_actor ( 1 ) ),
1707
+ player_activity ( gunmod_remove_activity_actor ( 1 , loc, 0 ) ),
1708
+ player_activity ( hacking_activity_actor () ),
1709
+ // player_activity( hacksaw_activity_actor( p, loc ) ),
1710
+ player_activity ( haircut_activity_actor () ),
1711
+ // player_activity( harvest_activity_actor( p ) ),
1712
+ player_activity ( hotwire_car_activity_actor ( 1 , p ) ),
1713
+ // player_activity( insert_item_activity_actor() ),
1714
+ player_activity ( lockpick_activity_actor::use_item ( 1 , loc, p ) ),
1715
+ // player_activity( longsalvage_activity_actor() ),
1716
+ player_activity ( meditate_activity_actor () ),
1717
+ player_activity ( migration_cancel_activity_actor () ),
1718
+ player_activity ( milk_activity_actor ( 1 , {p}, {std::string ()} ) ),
1719
+ player_activity ( mop_activity_actor ( 1 ) ),
1720
+ // player_activity( move_furniture_activity_actor( p, false ) ),
1721
+ player_activity ( move_items_activity_actor ( {}, {}, false , north ) ),
1722
+ player_activity ( open_gate_activity_actor ( 1 , p ) ),
1723
+ // player_activity( oxytorch_activity_actor( p, loc ) ),
1724
+ player_activity ( pickup_activity_actor ( {}, {}, cata::nullopt ) ),
1725
+ player_activity ( play_with_pet_activity_actor () ),
1726
+ // player_activity( prying_activity_actor( p, loc ) ),
1727
+ // player_activity( read_activity_actor() ),
1728
+ player_activity ( reload_activity_actor ( 1 , 0 , locs ) ),
1729
+ player_activity ( safecracking_activity_actor ( north ) ),
1730
+ player_activity ( shave_activity_actor () ),
1731
+ // player_activity( shearing_activity_actor( north ) ),
1732
+ player_activity ( stash_activity_actor () ),
1733
+ player_activity ( tent_deconstruct_activity_actor ( 1 , 1 , p, itype_tent_kit ) ),
1734
+ // player_activity( tent_placement_activity_actor() ),
1735
+ player_activity ( try_sleep_activity_actor ( time_duration::from_hours ( 1 ) ) ),
1736
+ player_activity ( unload_activity_actor ( 1 , loc ) ),
1737
+ player_activity ( wear_activity_actor ( {}, {} ) ),
1738
+ player_activity ( wield_activity_actor ( loc, 1 ) )
1739
+ // player_activity( workout_activity_actor( p ) )
1740
+ };
1741
+
1742
+ return res;
1743
+ }
1744
+
1745
+ static void cleanup ( avatar &dummy )
1746
+ {
1747
+ clear_map ();
1748
+
1749
+ REQUIRE ( dummy.activity .get_distractions ().empty () );
1750
+ REQUIRE ( !dummy.activity .is_distraction_ignored ( distraction_type::hostile_spotted_near ) );
1751
+ REQUIRE ( !dummy.activity .is_distraction_ignored ( distraction_type::dangerous_field ) );
1752
+ }
1753
+
1754
+ static void update_cache ( map &m )
1755
+ {
1756
+ // Why twice? See vision_test.cpp
1757
+ m.update_visibility_cache ( 0 );
1758
+ m.invalidate_map_cache ( 0 );
1759
+ m.build_map_cache ( 0 );
1760
+ m.update_visibility_cache ( 0 );
1761
+ m.invalidate_map_cache ( 0 );
1762
+ m.build_map_cache ( 0 );
1763
+ }
1764
+
1765
+ TEST_CASE ( " activity interruption by distractions" , " [activity][interruption]" )
1766
+ {
1767
+ avatar &dummy = get_avatar ();
1768
+ clear_avatar ();
1769
+ clear_map ();
1770
+ map &m = get_map ();
1771
+ calendar::turn = daylight_time ( calendar::turn ) + 2_hours;
1772
+
1773
+ for ( player_activity &activity : get_test_activities ( dummy, m ) ) {
1774
+ CAPTURE ( activity.id () );
1775
+ dummy.activity = activity;
1776
+ dummy.activity .start_or_resume ( dummy, false );
1777
+
1778
+ // this must be larger than 0 for interruption to happen
1779
+ REQUIRE ( dummy.activity .moves_left > 0 );
1780
+ // some activities are set to null during start if they don't get valid data
1781
+ REQUIRE ( dummy.activity .id () != ACT_NULL );
1782
+ // aiming is excluded from this kind of interruption
1783
+ REQUIRE ( dummy.activity .id () != ACT_AIM );
1784
+
1785
+ tripoint zombie_pos_near = dummy.pos () + tripoint ( 2 , 0 , 0 );
1786
+ tripoint zombie_pos_far = dummy.pos () + tripoint ( 10 , 0 , 0 );
1787
+
1788
+ // to make section names unique
1789
+ std::string act = activity.id ().str ();
1790
+
1791
+ SECTION ( act + " interruption by nearby enemy" ) {
1792
+ cleanup ( dummy );
1793
+
1794
+ spawn_test_monster ( mon_zombie.str (), zombie_pos_near );
1795
+ update_cache ( m );
1796
+
1797
+ std::map<distraction_type, std::string> dists = dummy.activity .get_distractions ();
1798
+
1799
+ CHECK ( dists.size () == 1 );
1800
+ CHECK ( dists.find ( distraction_type::hostile_spotted_near ) != dists.end () );
1801
+ }
1802
+
1803
+ SECTION ( act + " enemy too far away to interrupt" ) {
1804
+ cleanup ( dummy );
1805
+
1806
+ monster &zombie = spawn_test_monster ( mon_zombie.str (), zombie_pos_far );
1807
+ update_cache ( m );
1808
+
1809
+ REQUIRE ( dummy.sees ( zombie ) );
1810
+
1811
+ std::map<distraction_type, std::string> dists = dummy.activity .get_distractions ();
1812
+
1813
+ CHECK ( dists.empty () );
1814
+
1815
+ THEN ( " interruption by zombie moving towards dummy" ) {
1816
+ zombie.set_dest ( get_map ().getglobal ( dummy.pos () ) );
1817
+ int turns = 0 ;
1818
+ do {
1819
+ move_monster_turn ( zombie );
1820
+ dists = dummy.activity .get_distractions ();
1821
+ turns++;
1822
+ } while ( turns < 10 && dists.empty () );
1823
+
1824
+ CHECK ( dists.size () == 1 );
1825
+ CHECK ( dists.find ( distraction_type::hostile_spotted_near ) != dists.end () );
1826
+ }
1827
+ }
1828
+
1829
+ SECTION ( act + " enemy nearby, but no line of sight" ) {
1830
+ cleanup ( dummy );
1831
+
1832
+ m.ter_set ( dummy.pos () + tripoint_east, ter_t_wall );
1833
+ monster &zombie = spawn_test_monster ( mon_zombie.str (), zombie_pos_near );
1834
+ update_cache ( m );
1835
+
1836
+ REQUIRE ( !dummy.sees ( zombie ) );
1837
+
1838
+ std::map<distraction_type, std::string> dists = dummy.activity .get_distractions ();
1839
+
1840
+ CHECK ( dists.empty () );
1841
+
1842
+ THEN ( " interruption by zombie moving towards dummy" ) {
1843
+ zombie.set_dest ( get_map ().getglobal ( dummy.pos () ) );
1844
+ int turns = 0 ;
1845
+ do {
1846
+ move_monster_turn ( zombie );
1847
+ dists = dummy.activity .get_distractions ();
1848
+ turns++;
1849
+ } while ( turns < 5 && dists.empty () );
1850
+
1851
+ CHECK ( dists.size () == 1 );
1852
+ CHECK ( dists.find ( distraction_type::hostile_spotted_near ) != dists.end () );
1853
+ }
1854
+ }
1855
+
1856
+ SECTION ( act + " interruption by dangerous field" ) {
1857
+ cleanup ( dummy );
1858
+
1859
+ m.add_field ( dummy.pos (), field_fd_smoke );
1860
+
1861
+ std::map<distraction_type, std::string> dists = dummy.activity .get_distractions ();
1862
+
1863
+ CHECK ( dists.size () == 1 );
1864
+ CHECK ( dists.find ( distraction_type::dangerous_field ) != dists.end () );
1865
+ }
1866
+
1867
+ SECTION ( act + " interruption by multiple sources" ) {
1868
+ cleanup ( dummy );
1869
+
1870
+ spawn_test_monster ( mon_zombie.str (), zombie_pos_near );
1871
+ m.add_field ( dummy.pos (), field_fd_smoke );
1872
+ std::map<distraction_type, std::string> dists = dummy.activity .get_distractions ();
1873
+
1874
+ CHECK ( dists.size () == 2 );
1875
+ CHECK ( dists.find ( distraction_type::hostile_spotted_near ) != dists.end () );
1876
+ CHECK ( dists.find ( distraction_type::dangerous_field ) != dists.end () );
1877
+ }
1878
+ }
1879
+ }
0 commit comments