1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
#include "activity_actor_definitions.h"
#include "avatar.h"
#include "calendar.h"
#include "cata_catch.h"
#include "itype.h"
#include "npc.h"
#include "type_id.h"
#include "map.h"
#include "map_helpers.h"
#include "player_helpers.h"
#include "activity_scheduling_helper.h"
static const activity_id ACT_FIRSTAID( "ACT_FIRSTAID" );
static const efftype_id effect_bandaged( "bandaged" );
static const itype_id itype_bandages( "bandages" );
static const skill_id skill_firstaid( "firstaid" );
static void process_activity_interrupt( Character &guy, const int interrupt_time )
{
do {
guy.moves += guy.get_speed();
while( guy.moves > 0 && guy.has_activity( ACT_FIRSTAID ) ) {
guy.activity.do_turn( guy );
if( guy.activity.moves_total - guy.activity.moves_left >= interrupt_time ) {
// Assume the player confirms the option to cancel the activity when getting interrupted,
// as in Character::react_to_felt_pain()
guy.cancel_activity();
}
}
} while( guy.has_activity( ACT_FIRSTAID ) );
}
static bool bandages_filter( const item &it )
{
return ( it.typeId() == itype_bandages );
}
TEST_CASE( "avatar_does_healing", "[activity][firstaid][avatar]" )
{
avatar &dummy = get_avatar();
clear_avatar();
clear_map();
const bodypart_id right_arm( "arm_r" );
npc &dunsel = spawn_npc( point_east, "test_talker" );
set_time( calendar::turn_zero + 12_hours );
dunsel.pos() = dummy.pos() + point_east;
dummy.set_skill_level( skill_firstaid, 10 );
int moves = 500;
item_location bandages = dummy.i_add( item( itype_bandages ) );
int start_bandage_count = dummy.items_with( bandages_filter ).size();
REQUIRE( dummy.has_item( *bandages ) );
GIVEN( "avatar has a damaged right arm" ) {
dummy.apply_damage( nullptr, right_arm, 20 );
WHEN( "avatar bandages self" ) {
dummy.assign_activity( firstaid_activity_actor( moves, bandages->tname(), dummy.getID() ) );
dummy.activity.targets.emplace_back( bandages );
dummy.activity.str_values.emplace_back( right_arm.id().c_str() );
process_activity( dummy );
THEN( "Check that bandage was consumed and arm is bandaged" ) {
CHECK( start_bandage_count - dummy.items_with( bandages_filter ).size() == 1 );
CHECK( dummy.has_effect( effect_bandaged, right_arm ) );
}
}
}
GIVEN( "avatar has a damaged right arm" ) {
dummy.apply_damage( nullptr, right_arm, 20 );
WHEN( "avatar bandages self and is interrupted before finishing" ) {
dummy.assign_activity( firstaid_activity_actor( moves, bandages->tname(), dummy.getID() ) );
dummy.activity.targets.emplace_back( bandages );
dummy.activity.str_values.emplace_back( right_arm.id().c_str() );
process_activity_interrupt( dummy, moves / 2 );
THEN( "Check that bandage was not consumed and arm is not bandaged" ) {
CHECK( start_bandage_count - dummy.items_with( bandages_filter ).size() == 0 );
CHECK( !dummy.has_effect( effect_bandaged, right_arm ) );
}
}
}
GIVEN( "npc has a damaged right arm" ) {
dunsel.apply_damage( nullptr, right_arm, 20 );
WHEN( "avatar bandages npc" ) {
dummy.assign_activity( firstaid_activity_actor( moves, bandages->tname(), dunsel.getID() ) );
dummy.activity.targets.emplace_back( bandages );
dummy.activity.str_values.emplace_back( right_arm.id().c_str() );
process_activity( dummy );
THEN( "Check that bandage was consumed and npc's arm is bandaged" ) {
CHECK( start_bandage_count - dummy.items_with( bandages_filter ).size() == 1 );
CHECK( dunsel.has_effect( effect_bandaged, right_arm ) );
}
}
}
}
TEST_CASE( "npc_does_healing", "[activity][firstaid][npc]" )
{
avatar &dummy = get_avatar();
clear_avatar();
clear_map();
const bodypart_id right_arm( "arm_r" );
npc &dunsel = spawn_npc( point_east, "test_talker" );
set_time( calendar::turn_zero + 12_hours );
dunsel.pos() = dummy.pos() + point_east;
dunsel.set_skill_level( skill_firstaid, 10 );
int moves = 500;
item_location bandages = dunsel.i_add( item( itype_bandages ) );
int start_bandage_count = dunsel.items_with( bandages_filter ).size();
REQUIRE( dunsel.has_item( *bandages ) );
GIVEN( "npc has a damaged right arm" ) {
dunsel.apply_damage( nullptr, right_arm, 20 );
WHEN( "npc bandages self" ) {
// See npc::heal_self()
bandages->type->invoke( &dunsel, *bandages, dunsel.pos(), "heal" );
process_activity( dunsel );
THEN( "Check that bandage was consumed and arm is bandaged" ) {
CHECK( start_bandage_count - dunsel.items_with( bandages_filter ).size() == 1 );
CHECK( dunsel.has_effect( effect_bandaged, right_arm ) );
}
}
}
GIVEN( "npc has a damaged right arm" ) {
dunsel.apply_damage( nullptr, right_arm, 20 );
WHEN( "npc bandages self and is interrupted before finishing" ) {
// See npc::heal_self()
bandages->type->invoke( &dunsel, *bandages, dunsel.pos(), "heal" );
process_activity_interrupt( dunsel, moves / 2 );
THEN( "Check that bandage was not consumed and arm is not bandaged" ) {
CHECK( start_bandage_count - dunsel.items_with( bandages_filter ).size() == 0 );
CHECK( !dunsel.has_effect( effect_bandaged, right_arm ) );
}
}
}
GIVEN( "avatar has a damaged right arm" ) {
dummy.apply_damage( nullptr, right_arm, 20 );
WHEN( "npc bandages avatar" ) {
// See npc::heal_player
bandages->type->invoke( &dunsel, *bandages, dummy.pos(), "heal" );
process_activity( dunsel );
THEN( "Check that bandage was consumed and avatar's arm is bandaged" ) {
CHECK( start_bandage_count - dunsel.items_with( bandages_filter ).size() == 1 );
CHECK( dummy.has_effect( effect_bandaged, right_arm ) );
}
}
}
}
|