Skip to content

Commit 538ff36

Browse files
authored
Merge pull request #54672 from mqrause/close_enemy_interruption
Fix activities not getting interrupted by dangerously close enemies
2 parents 27b26c2 + bf2de61 commit 538ff36

10 files changed

+304
-38
lines changed

src/activity_actor.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "avatar.h"
2222
#include "avatar_action.h"
2323
#include "bodypart.h"
24-
#include "calendar.h"
2524
#include "character.h"
2625
#include "coordinates.h"
2726
#include "contents_change_handler.h"
@@ -469,7 +468,7 @@ void aim_activity_actor::unload_RAS_weapon()
469468
}
470469
}
471470

472-
void autodrive_activity_actor::start( player_activity &act, Character &who )
471+
void autodrive_activity_actor::start( player_activity &, Character &who )
473472
{
474473
const bool in_vehicle = who.in_vehicle && who.controlling_vehicle;
475474
const optional_vpart_position vp = get_map().veh_at( who.pos() );
@@ -480,7 +479,6 @@ void autodrive_activity_actor::start( player_activity &act, Character &who )
480479

481480
player_vehicle = &vp->vehicle();
482481
player_vehicle->is_autodriving = true;
483-
act.moves_left = calendar::INDEFINITELY_LONG;
484482
}
485483

486484
void autodrive_activity_actor::do_turn( player_activity &act, Character &who )
@@ -2577,7 +2575,7 @@ std::unique_ptr<activity_actor> open_gate_activity_actor::deserialize( JsonValue
25772575

25782576
void consume_activity_actor::start( player_activity &act, Character &guy )
25792577
{
2580-
int moves;
2578+
int moves = 0;
25812579
Character &player_character = get_player_character();
25822580
if( consume_location ) {
25832581
ret_val<edible_rating> ret = ret_val<edible_rating>::make_success();
@@ -2592,9 +2590,9 @@ void consume_activity_actor::start( player_activity &act, Character &guy )
25922590
consume_menu_selections = std::vector<int>();
25932591
consume_menu_selected_items.clear();
25942592
consume_menu_filter.clear();
2595-
return;
2593+
} else {
2594+
moves = to_moves<int>( guy.get_consume_time( *consume_location ) );
25962595
}
2597-
moves = to_moves<int>( guy.get_consume_time( *consume_location ) );
25982596
} else if( !consume_item.is_null() ) {
25992597
ret_val<edible_rating> ret = ret_val<edible_rating>::make_success();
26002598
if( refuel ) {
@@ -2607,13 +2605,12 @@ void consume_activity_actor::start( player_activity &act, Character &guy )
26072605
consume_menu_selections = std::vector<int>();
26082606
consume_menu_selected_items.clear();
26092607
consume_menu_filter.clear();
2610-
return;
2608+
} else {
2609+
moves = to_moves<int>( guy.get_consume_time( consume_item ) );
26112610
}
2612-
moves = to_moves<int>( guy.get_consume_time( consume_item ) );
26132611
} else {
26142612
debugmsg( "Item/location to be consumed should not be null." );
26152613
canceled = true;
2616-
return;
26172614
}
26182615

26192616
act.moves_total = moves;
@@ -3043,7 +3040,6 @@ void craft_activity_actor::start( player_activity &act, Character &crafter )
30433040
if( !check_if_craft_okay( craft_item, crafter ) ) {
30443041
act.set_to_null();
30453042
}
3046-
act.moves_left = calendar::INDEFINITELY_LONG;
30473043
activity_override = craft_item.get_item()->get_making().exertion_level();
30483044
cached_crafting_speed = 0;
30493045
}
@@ -4443,7 +4439,6 @@ void disassemble_activity_actor::start( player_activity &act, Character &who )
44434439
// Mark the item, not available for other characters
44444440
target->set_var( "activity_var", who.name );
44454441

4446-
act.moves_left = calendar::INDEFINITELY_LONG;
44474442
activity_override = target->get_making().exertion_level();
44484443
}
44494444

@@ -5804,6 +5799,10 @@ std::unique_ptr<activity_actor> forage_activity_actor::deserialize( JsonValue &j
58045799
void longsalvage_activity_actor::start( player_activity &act, Character & )
58055800
{
58065801
act.index = index;
5802+
5803+
//todo: refactor the actor to process items in ::do_turn, then remove setting the moves to 0
5804+
//this currently still can't get interrupted before you get attacked
5805+
act.moves_left = 0;
58075806
}
58085807

58095808
void longsalvage_activity_actor::finish( player_activity &act, Character &who )

src/activity_actor_definitions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class autodrive_activity_actor : public activity_actor
117117
return activity_id( "ACT_AUTODRIVE" );
118118
}
119119

120-
void start( player_activity &act, Character & ) override;
120+
void start( player_activity &, Character & ) override;
121121
void do_turn( player_activity &, Character & ) override;
122122
void canceled( player_activity &, Character & ) override;
123123
void finish( player_activity &act, Character & ) override;

src/do_turn.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "creature_tracker.h"
99
#include "event_bus.h"
1010
#include "explosion.h"
11-
#include "field.h"
1211
#include "game.h"
1312
#include "gamemode.h"
1413
#include "help.h"
@@ -35,7 +34,6 @@
3534
#include "wcwidth.h"
3635
#include "worldfactory.h"
3736

38-
static const activity_id ACT_AIM( "ACT_AIM" );
3937
static const activity_id ACT_AUTODRIVE( "ACT_AUTODRIVE" );
4038
static const activity_id ACT_OPERATION( "ACT_OPERATION" );
4139

@@ -729,32 +727,13 @@ bool do_turn()
729727
// If player is performing a task, a monster is dangerously close,
730728
// and monster can reach to the player or it has some sort of a ranged attack,
731729
// warn them regardless of previous safemode warnings
732-
if( u.activity && !u.has_activity( ACT_AIM ) &&
733-
u.activity.moves_left > 0 &&
734-
!u.activity.is_distraction_ignored( distraction_type::hostile_spotted_near ) ) {
735-
Creature *hostile_critter = g->is_hostile_very_close( true );
736-
737-
if( hostile_critter != nullptr ) {
738-
g->cancel_activity_or_ignore_query( distraction_type::hostile_spotted_near,
739-
string_format( _( "The %s is dangerously close!" ),
740-
hostile_critter->get_name() ) );
741-
}
742-
}
743-
744-
if( u.activity && !u.has_activity( ACT_AIM ) && u.activity.moves_left > 0 &&
745-
!u.activity.is_distraction_ignored( distraction_type::dangerous_field ) ) {
746-
for( const std::pair<const field_type_id, field_entry> &field : m.field_at( u.pos() ) ) {
747-
if( u.is_dangerous_field( field.second ) ) {
748-
if( g->cancel_activity_or_ignore_query( distraction_type::dangerous_field,
749-
string_format( _( "You stand in %s!" ),
750-
field.second.name() ) ) ||
751-
u.activity.is_distraction_ignored( distraction_type::dangerous_field ) ) {
752-
break;
753-
}
730+
if( u.activity ) {
731+
for( std::pair<const distraction_type, std::string> &dist : u.activity.get_distractions() ) {
732+
if( g->cancel_activity_or_ignore_query( dist.first, dist.second ) ) {
733+
break;
754734
}
755735
}
756736
}
757-
758737
}
759738
}
760739

src/game.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,6 +3855,18 @@ Creature *game::is_hostile_within( int distance, bool dangerous )
38553855
return nullptr;
38563856
}
38573857

3858+
field_entry *game::is_in_dangerous_field()
3859+
{
3860+
map &here = get_map();
3861+
for( std::pair<const field_type_id, field_entry> &field : here.field_at( u.pos() ) ) {
3862+
if( u.is_dangerous_field( field.second ) ) {
3863+
return &field.second;
3864+
}
3865+
}
3866+
3867+
return nullptr;
3868+
}
3869+
38583870
std::unordered_set<tripoint> game::get_fishable_locations( int distance, const tripoint &fish_pos )
38593871
{
38603872
// We're going to get the contiguous fishable terrain starting at

src/game.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ class game
559559
character_id assign_npc_id();
560560
Creature *is_hostile_nearby();
561561
Creature *is_hostile_very_close( bool dangerous = false );
562+
field_entry *is_in_dangerous_field();
562563
// Handles shifting coordinates transparently when moving between submaps.
563564
// Helper to make calling with a player pointer less verbose.
564565
point update_map( Character &p, bool z_level_changed = false );

src/player_activity.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "calendar.h"
1111
#include "character.h"
1212
#include "construction.h"
13+
#include "field.h"
14+
#include "game.h"
1315
#include "item.h"
1416
#include "itype.h"
1517
#include "map.h"
@@ -464,3 +466,28 @@ void player_activity::inherit_distractions( const player_activity &other )
464466
ignore_distraction( type );
465467
}
466468
}
469+
470+
471+
std::map<distraction_type, std::string> player_activity::get_distractions()
472+
{
473+
std::map < distraction_type, std::string > res;
474+
if( id() != ACT_AIM && moves_left > 0 ) {
475+
if( !is_distraction_ignored( distraction_type::hostile_spotted_near ) ) {
476+
Creature *hostile_critter = g->is_hostile_very_close( true );
477+
if( hostile_critter != nullptr ) {
478+
res.emplace( distraction_type::hostile_spotted_near,
479+
string_format( _( "The %s is dangerously close!" ),
480+
g->is_hostile_very_close( true )->get_name() ) );
481+
}
482+
}
483+
if( !is_distraction_ignored( distraction_type::dangerous_field ) ) {
484+
field_entry *field = g->is_in_dangerous_field();
485+
if( field != nullptr ) {
486+
res.emplace( distraction_type::dangerous_field, string_format( _( "You stand in %s!" ),
487+
g->is_in_dangerous_field()->name() ) );
488+
}
489+
}
490+
}
491+
492+
return res;
493+
}

src/player_activity.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <vector>
1212

1313
#include "activity_actor.h"
14+
#include "calendar.h"
1415
#include "clone_ptr.h"
1516
#include "compatibility.h"
1617
#include "enums.h"
@@ -41,7 +42,7 @@ class player_activity
4142
/** Total number of moves required to complete the activity */
4243
int moves_total = 0;
4344
/** The number of moves remaining in this activity before it is complete. */
44-
int moves_left = 0;
45+
int moves_left = calendar::INDEFINITELY_LONG;
4546
/** Controls whether this activity can be cancelled at all */
4647
bool interruptable = true;
4748
/** Controls whether this activity can be cancelled with 'pause' action */
@@ -177,6 +178,8 @@ class player_activity
177178
bool do_drop_invalid_inventory() const {
178179
return !actor || actor->do_drop_invalid_inventory();
179180
}
181+
182+
std::map<distraction_type, std::string> get_distractions();
180183
};
181184

182185
#endif // CATA_SRC_PLAYER_ACTIVITY_H

tests/monster_helpers.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include "monster_helpers.h"
2+
3+
#include "item.h"
4+
#include "monster.h"
5+
6+
void move_monster_turn( monster &mon )
7+
{
8+
const int moves = mon.get_speed();
9+
mon.mod_moves( moves );
10+
while( mon.get_moves() > 0 ) {
11+
mon.move();
12+
}
13+
}

tests/monster_helpers.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
#ifndef CATA_TESTS_MONSTER_HELPERS_H
3+
#define CATA_TESTS_MONSTER_HELPERS_H
4+
5+
class monster;
6+
7+
void move_monster_turn( monster &mon );
8+
9+
#endif // CATA_TESTS_MONSTER_HELPERS_H

0 commit comments

Comments
 (0)