1 #include "npc.h"
2 
3 #include <algorithm>
4 #include <climits>
5 #include <cmath>
6 #include <cstdlib>
7 #include <functional>
8 #include <limits>
9 #include <memory>
10 #include <ostream>
11 
12 #include "activity_type.h"
13 #include "auto_pickup.h"
14 #include "basecamp.h"
15 #include "bodypart.h"
16 #include "catacharset.h"
17 #include "character.h"
18 #include "character_id.h"
19 #include "character_martial_arts.h"
20 #include "clzones.h"
21 #include "coordinate_conversions.h"
22 #include "cursesdef.h"
23 #include "damage.h"
24 #include "debug.h"
25 #include "dialogue.h"
26 #include "dialogue_chatbin.h"
27 #include "effect.h"
28 #include "enums.h"
29 #include "event.h"
30 #include "event_bus.h"
31 #include "faction.h"
32 #include "flag.h"
33 #include "game.h"
34 #include "game_constants.h"
35 #include "game_inventory.h"
36 #include "item.h"
37 #include "item_group.h"
38 #include "itype.h"
39 #include "iuse.h"
40 #include "iuse_actor.h"
41 #include "json.h"
42 #include "magic.h"
43 #include "make_static.h"
44 #include "map.h"
45 #include "map_iterator.h"
46 #include "mapdata.h"
47 #include "messages.h"
48 #include "mission.h"
49 #include "monster.h"
50 #include "morale_types.h"
51 #include "mtype.h"
52 #include "mutation.h"
53 #include "npc_class.h"
54 #include "npctalk.h"
55 #include "options.h"
56 #include "output.h"
57 #include "overmap.h"
58 #include "overmapbuffer.h"
59 #include "pathfinding.h"
60 #include "player_activity.h"
61 #include "ret_val.h"
62 #include "rng.h"
63 #include "skill.h"
64 #include "sounds.h"
65 #include "stomach.h"
66 #include "string_formatter.h"
67 #include "talker.h"
68 #include "talker_npc.h"
69 #include "text_snippets.h"
70 #include "tileray.h"
71 #include "trait_group.h"
72 #include "translations.h"
73 #include "units.h"
74 #include "value_ptr.h"
75 #include "veh_type.h"
76 #include "vehicle.h"
77 #include "viewer.h"
78 #include "visitable.h"
79 #include "vpart_position.h"
80 #include "vpart_range.h"
81 
82 static const activity_id ACT_READ( "ACT_READ" );
83 
84 static const efftype_id effect_bouldering( "bouldering" );
85 static const efftype_id effect_contacts( "contacts" );
86 static const efftype_id effect_controlled( "controlled" );
87 static const efftype_id effect_drunk( "drunk" );
88 static const efftype_id effect_high( "high" );
89 static const efftype_id effect_infection( "infection" );
90 static const efftype_id effect_mending( "mending" );
91 static const efftype_id effect_npc_flee_player( "npc_flee_player" );
92 static const efftype_id effect_npc_suspend( "npc_suspend" );
93 static const efftype_id effect_pkill_l( "pkill_l" );
94 static const efftype_id effect_pkill1( "pkill1" );
95 static const efftype_id effect_pkill2( "pkill2" );
96 static const efftype_id effect_pkill3( "pkill3" );
97 static const efftype_id effect_ridden( "ridden" );
98 static const efftype_id effect_riding( "riding" );
99 
100 static const itype_id itype_UPS_off( "UPS_off" );
101 
102 static const skill_id skill_archery( "archery" );
103 static const skill_id skill_bashing( "bashing" );
104 static const skill_id skill_cutting( "cutting" );
105 static const skill_id skill_pistol( "pistol" );
106 static const skill_id skill_rifle( "rifle" );
107 static const skill_id skill_shotgun( "shotgun" );
108 static const skill_id skill_smg( "smg" );
109 static const skill_id skill_speech( "speech" );
110 static const skill_id skill_stabbing( "stabbing" );
111 static const skill_id skill_throw( "throw" );
112 
113 static const bionic_id bio_memory( "bio_memory" );
114 
115 static const trait_id trait_BEE( "BEE" );
116 static const trait_id trait_CANNIBAL( "CANNIBAL" );
117 static const trait_id trait_DEBUG_MIND_CONTROL( "DEBUG_MIND_CONTROL" );
118 static const trait_id trait_HALLUCINATION( "HALLUCINATION" );
119 static const trait_id trait_HYPEROPIC( "HYPEROPIC" );
120 static const trait_id trait_ILLITERATE( "ILLITERATE" );
121 static const trait_id trait_MUTE( "MUTE" );
122 static const trait_id trait_PROF_DICEMASTER( "PROF_DICEMASTER" );
123 static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" );
124 static const trait_id trait_SAPIOVORE( "SAPIOVORE" );
125 static const trait_id trait_SCHIZOPHRENIC( "SCHIZOPHRENIC" );
126 static const trait_id trait_TERRIFYING( "TERRIFYING" );
127 
128 class monfaction;
129 
130 static void starting_clothes( npc &who, const npc_class_id &type, bool male );
131 static void starting_inv( npc &who, const npc_class_id &type );
132 
npc()133 npc::npc()
134     : restock( calendar::turn_zero )
135     , companion_mission_time( calendar::before_time_starts )
136     , companion_mission_time_ret( calendar::before_time_starts )
137 {
138     last_updated = calendar::turn;
139     submap_coords = point_zero;
140     position.x = -1;
141     position.y = -1;
142     position.z = 500;
143     last_player_seen_pos = cata::nullopt;
144     last_seen_player_turn = 999;
145     wanted_item_pos = tripoint_min;
146     guard_pos = tripoint_min;
147     goal = tripoint_abs_omt( tripoint_min );
148     fetching_item = false;
149     has_new_items = true;
150     worst_item_value = 0;
151     str_max = 0;
152     dex_max = 0;
153     int_max = 0;
154     per_max = 0;
155     marked_for_death = false;
156     death_drops = true;
157     dead = false;
158     hit_by_player = false;
159     hallucination = false;
160     moves = 100;
161     mission = NPC_MISSION_NULL;
162     myclass = npc_class_id::NULL_ID();
163     fac_id = faction_id::NULL_ID();
164     patience = 0;
165     attitude = NPCATT_NULL;
166 
167     *path_settings = pathfinding_settings( 0, 1000, 1000, 10, true, true, true, false, true );
168     for( direction threat_dir : npc_threat_dir ) {
169         ai_cache.threat_map[ threat_dir ] = 0.0f;
170     }
171 }
172 
standard_npc(const std::string & name,const tripoint & pos,const std::vector<std::string> & clothing,int sk_lvl,int s_str,int s_dex,int s_int,int s_per)173 standard_npc::standard_npc( const std::string &name, const tripoint &pos,
174                             const std::vector<std::string> &clothing,
175                             int sk_lvl, int s_str, int s_dex, int s_int, int s_per )
176 {
177     this->name = name;
178     position = pos;
179 
180     str_cur = std::max( s_str, 0 );
181     str_max = std::max( s_str, 0 );
182     dex_cur = std::max( s_dex, 0 );
183     dex_max = std::max( s_dex, 0 );
184     per_cur = std::max( s_per, 0 );
185     per_max = std::max( s_per, 0 );
186     int_cur = std::max( s_int, 0 );
187     int_max = std::max( s_int, 0 );
188 
189     set_body();
190     recalc_hp();
191 
192     for( const Skill &e : Skill::skills ) {
193         set_skill_level( e.ident(), std::max( sk_lvl, 0 ) );
194     }
195 
196     for( const std::string &e : clothing ) {
197         wear_item( item( e ), false );
198     }
199 
200     for( item &e : worn ) {
201         if( e.has_flag( flag_VARSIZE ) ) {
202             e.set_flag( flag_FIT );
203         }
204     }
205 }
206 
207 npc::npc( npc && ) = default;
208 npc &npc::operator=( npc && ) = default;
209 
210 static std::map<string_id<npc_template>, npc_template> npc_templates;
211 
load(const JsonObject & jsobj)212 void npc_template::load( const JsonObject &jsobj )
213 {
214     npc_template tem;
215     npc &guy = tem.guy;
216     guy.idz = jsobj.get_string( "id" );
217     guy.name.clear();
218     jsobj.read( "name_unique", tem.name_unique );
219     jsobj.read( "name_suffix", tem.name_suffix );
220     if( jsobj.has_string( "gender" ) ) {
221         if( jsobj.get_string( "gender" ) == "male" ) {
222             tem.gender_override = gender::male;
223         } else {
224             tem.gender_override = gender::female;
225         }
226     } else {
227         tem.gender_override = gender::random;
228     }
229     if( jsobj.has_string( "faction" ) ) {
230         guy.set_fac_id( jsobj.get_string( "faction" ) );
231     }
232 
233     if( jsobj.has_int( "class" ) ) {
234         guy.myclass = npc_class::from_legacy_int( jsobj.get_int( "class" ) );
235     } else if( jsobj.has_string( "class" ) ) {
236         guy.myclass = npc_class_id( jsobj.get_string( "class" ) );
237     }
238 
239     guy.set_attitude( static_cast<npc_attitude>( jsobj.get_int( "attitude" ) ) );
240     guy.mission = static_cast<npc_mission>( jsobj.get_int( "mission" ) );
241     guy.chatbin.first_topic = jsobj.get_string( "chat" );
242     if( jsobj.has_string( "mission_offered" ) ) {
243         guy.miss_ids.emplace_back( mission_type_id( jsobj.get_string( "mission_offered" ) ) );
244     } else if( jsobj.has_array( "mission_offered" ) ) {
245         for( const std::string line : jsobj.get_array( "mission_offered" ) ) {
246             guy.miss_ids.emplace_back( mission_type_id( line ) );
247         }
248     }
249     npc_templates.emplace( string_id<npc_template>( guy.idz ), std::move( tem ) );
250 }
251 
reset()252 void npc_template::reset()
253 {
254     npc_templates.clear();
255 }
256 
check_consistency()257 void npc_template::check_consistency()
258 {
259     for( const auto &e : npc_templates ) {
260         const auto &guy = e.second.guy;
261         if( !guy.myclass.is_valid() ) {
262             debugmsg( "Invalid NPC class %s", guy.myclass.c_str() );
263         }
264         std::string first_topic = guy.chatbin.first_topic;
265         if( const json_talk_topic *topic = get_talk_topic( first_topic ) ) {
266             cata::flat_set<std::string> reachable_topics =
267                 topic->get_directly_reachable_topics( true );
268             if( reachable_topics.count( "TALK_MISSION_OFFER" ) ) {
269                 debugmsg(
270                     "NPC template \"%s\" has dialogue \"%s\" which leads unconditionally to "
271                     "\"TALK_MISSION_OFFER\", which doesn't check for an available mission.  "
272                     "You should probably prefer \"TALK_MISSION_LIST\"",
273                     e.first.str(), first_topic );
274             }
275         }
276     }
277 }
278 
279 template<>
is_valid() const280 bool string_id<npc_template>::is_valid() const
281 {
282     return npc_templates.count( *this ) > 0;
283 }
284 
285 template<>
obj() const286 const npc_template &string_id<npc_template>::obj() const
287 {
288     const auto found = npc_templates.find( *this );
289     if( found == npc_templates.end() ) {
290         debugmsg( "Tried to get invalid npc: %s", c_str() );
291         static const npc_template dummy{};
292         return dummy;
293     }
294     return found->second;
295 }
296 
load_npc_template(const string_id<npc_template> & ident)297 void npc::load_npc_template( const string_id<npc_template> &ident )
298 {
299     auto found = npc_templates.find( ident );
300     if( found == npc_templates.end() ) {
301         debugmsg( "Tried to get invalid npc: %s", ident.c_str() );
302         return;
303     }
304     const npc_template &tem = found->second;
305     const npc &tguy = tem.guy;
306 
307     idz = tguy.idz;
308     myclass = npc_class_id( tguy.myclass );
309     randomize( myclass );
310     if( !tem.name_unique.empty() ) {
311         name = tem.name_unique.translated();
312     }
313     if( !tem.name_suffix.empty() ) {
314         //~ %1$s: npc name, %2$s: name suffix
315         name = string_format( pgettext( "npc name", "%1$s, %2$s" ), name, tem.name_suffix );
316     }
317     if( tem.gender_override != npc_template::gender::random ) {
318         male = tem.gender_override == npc_template::gender::male;
319     }
320     fac_id = tguy.fac_id;
321     set_fac( fac_id );
322     attitude = tguy.attitude;
323     mission = tguy.mission;
324     chatbin.first_topic = tguy.chatbin.first_topic;
325     for( const mission_type_id &miss_id : tguy.miss_ids ) {
326         add_new_mission( mission::reserve_new( miss_id, getID() ) );
327     }
328 }
329 
330 npc::~npc() = default;
331 
randomize(const npc_class_id & type)332 void npc::randomize( const npc_class_id &type )
333 {
334     if( !getID().is_valid() ) {
335         setID( g->assign_npc_id() );
336     }
337 
338     weapon   = item( "null", calendar::turn_zero );
339     inv->clear();
340     personality.aggression = rng( -10, 10 );
341     personality.bravery    = rng( -3, 10 );
342     personality.collector  = rng( -1, 10 );
343     personality.altruism   = rng( -10, 10 );
344     moves = 100;
345     mission = NPC_MISSION_NULL;
346     male = one_in( 2 );
347     pick_name();
348 
349     if( !type.is_valid() ) {
350         debugmsg( "Invalid NPC class %s", type.c_str() );
351         myclass = npc_class_id::NULL_ID();
352     } else if( type.is_null() ) {
353         myclass = npc_class::random_common();
354     } else {
355         myclass = type;
356     }
357 
358     const auto &the_class = myclass.obj();
359     str_max = the_class.roll_strength();
360     dex_max = the_class.roll_dexterity();
361     int_max = the_class.roll_intelligence();
362     per_max = the_class.roll_perception();
363 
364     for( auto &skill : Skill::skills ) {
365         int level = myclass->roll_skill( skill.ident() );
366 
367         set_skill_level( skill.ident(), level );
368     }
369 
370     if( type.is_null() ) { // Untyped; no particular specialization
371     } else if( type == NC_EVAC_SHOPKEEP ) {
372         personality.collector += rng( 1, 5 );
373 
374     } else if( type == NC_BARTENDER ) {
375         personality.collector += rng( 1, 5 );
376 
377     } else if( type == NC_JUNK_SHOPKEEP ) {
378         personality.collector += rng( 1, 5 );
379 
380     } else if( type == NC_ARSONIST ) {
381         personality.aggression += rng( 0, 1 );
382         personality.collector += rng( 0, 2 );
383 
384     } else if( type == NC_SOLDIER ) {
385         personality.aggression += rng( 1, 3 );
386         personality.bravery += rng( 0, 5 );
387 
388     } else if( type == NC_HACKER ) {
389         personality.bravery -= rng( 1, 3 );
390         personality.aggression -= rng( 0, 2 );
391 
392     } else if( type == NC_DOCTOR ) {
393         personality.aggression -= rng( 0, 4 );
394         cash += 10000 * rng( 0, 3 ) * rng( 0, 3 );
395 
396     } else if( type == NC_TRADER ) {
397         personality.collector += rng( 1, 5 );
398         cash += 25000 * rng( 1, 10 );
399 
400     } else if( type == NC_NINJA ) {
401         personality.bravery += rng( 0, 3 );
402         personality.collector -= rng( 1, 6 );
403         // TODO: give ninja his styles back
404 
405     } else if( type == NC_COWBOY ) {
406         personality.aggression += rng( 0, 2 );
407         personality.bravery += rng( 1, 5 );
408 
409     } else if( type == NC_SCIENTIST ) {
410         personality.aggression -= rng( 1, 5 );
411         personality.bravery -= rng( 2, 8 );
412         personality.collector += rng( 0, 2 );
413 
414     } else if( type == NC_BOUNTY_HUNTER ) {
415         personality.aggression += rng( 1, 6 );
416         personality.bravery += rng( 0, 5 );
417 
418     } else if( type == NC_THUG ) {
419         personality.aggression += rng( 1, 6 );
420         personality.bravery += rng( 0, 5 );
421 
422     } else if( type == NC_SCAVENGER ) {
423         personality.aggression += rng( 1, 3 );
424         personality.bravery += rng( 1, 4 );
425 
426     }
427     //A universal barter boost to keep NPCs competitive with players
428     //The int boost from trade wasn't active... now that it is, most
429     //players will vastly outclass npcs in trade without a little help.
430     mod_skill_level( skill_speech, rng( 2, 4 ) );
431 
432     set_body();
433     recalc_hp();
434 
435     starting_weapon( myclass );
436     starting_clothes( *this, myclass, male );
437     starting_inv( *this, myclass );
438     has_new_items = true;
439     clear_mutations();
440 
441     // Add fixed traits
442     for( const auto &tid : trait_group::traits_from( myclass->traits ) ) {
443         set_mutation( tid );
444     }
445 
446     // Run mutation rounds
447     for( const auto &mr : type->mutation_rounds ) {
448         int rounds = mr.second.roll();
449         for( int i = 0; i < rounds; ++i ) {
450             mutate_category( mr.first );
451         }
452     }
453     // Add bionics
454     for( const auto &bl : type->bionic_list ) {
455         int chance = bl.second;
456         if( rng( 0, 100 ) <= chance ) {
457             add_bionic( bl.first );
458         }
459     }
460     // Add proficiencies
461     for( const proficiency_id &prof : type->_starting_proficiencies ) {
462         add_proficiency( prof );
463     }
464     // Add spells for magiclysm mod
465     for( std::pair<spell_id, int> spell_pair : type->_starting_spells ) {
466         this->magic->learn_spell( spell_pair.first, *this, true );
467         spell &sp = this->magic->get_spell( spell_pair.first );
468         while( sp.get_level() < spell_pair.second && !sp.is_max_level() ) {
469             sp.gain_level();
470         }
471     }
472 }
473 
randomize_from_faction(faction * fac)474 void npc::randomize_from_faction( faction *fac )
475 {
476     // Personality = aggression, bravery, altruism, collector
477     set_fac( fac->id );
478     randomize( npc_class_id::NULL_ID() );
479 }
480 
set_fac(const faction_id & id)481 void npc::set_fac( const faction_id &id )
482 {
483     if( my_fac ) {
484         my_fac->remove_member( getID() );
485     }
486     my_fac = g->faction_manager_ptr->get( id );
487     if( my_fac ) {
488         if( !is_fake() && !is_hallucination() ) {
489             my_fac->add_to_membership( getID(), disp_name(), known_to_u );
490         }
491         fac_id = my_fac->id;
492     } else {
493         return;
494     }
495     apply_ownership_to_inv();
496 }
497 
apply_ownership_to_inv()498 void npc::apply_ownership_to_inv()
499 {
500     for( auto &e : inv_dump() ) {
501         e->set_owner( *this );
502     }
503 }
504 
get_fac_id() const505 faction_id npc::get_fac_id() const
506 {
507     return fac_id;
508 }
509 
get_faction() const510 faction *npc::get_faction() const
511 {
512     if( !my_fac ) {
513         return g->faction_manager_ptr->get( faction_id( "no_faction" ) );
514     }
515     return my_fac;
516 }
517 
518 // item id from group "<class-name>_<what>" or from fallback group
519 // may still be a null item!
random_item_from(const npc_class_id & type,const std::string & what,const item_group_id & fallback)520 static item random_item_from( const npc_class_id &type, const std::string &what,
521                               const item_group_id &fallback )
522 {
523     item result = item_group::item_from( item_group_id( type.str() + "_" + what ), calendar::turn );
524     if( result.is_null() ) {
525         result = item_group::item_from( fallback, calendar::turn );
526     }
527     return result;
528 }
529 
530 // item id from "<class-name>_<what>" or from "npc_<what>"
random_item_from(const npc_class_id & type,const std::string & what)531 static item random_item_from( const npc_class_id &type, const std::string &what )
532 {
533     return random_item_from( type, what, item_group_id( "npc_" + what ) );
534 }
535 
536 // item id from "<class-name>_<what>_<gender>" or from "npc_<what>_<gender>"
get_clothing_item(const npc_class_id & type,const std::string & what,bool male)537 static item get_clothing_item( const npc_class_id &type, const std::string &what, bool male )
538 {
539     item result;
540     //Check if class has gendered clothing
541     //Then check if it has an ungendered version
542     //Only if all that fails, grab from the default class.
543     if( male ) {
544         result = random_item_from( type, what + "_male", item_group_id::NULL_ID() );
545     } else {
546         result = random_item_from( type, what + "_female", item_group_id::NULL_ID() );
547     }
548     if( result.is_null() ) {
549         if( male ) {
550             result = random_item_from( type, what, item_group_id( "npc_" + what + "_male" ) );
551         } else {
552             result = random_item_from( type, what, item_group_id( "npc_" + what + "_female" ) );
553         }
554     }
555 
556     return result;
557 }
558 
starting_clothes(npc & who,const npc_class_id & type,bool male)559 void starting_clothes( npc &who, const npc_class_id &type, bool male )
560 {
561     std::vector<item> ret;
562     if( item_group::group_is_defined( type->worn_override ) ) {
563         ret = item_group::items_from( type->worn_override );
564     } else {
565         ret.push_back( get_clothing_item( type, "pants", male ) );
566         ret.push_back( get_clothing_item( type, "shirt", male ) );
567         ret.push_back( get_clothing_item( type, "underwear_top", male ) );
568         ret.push_back( get_clothing_item( type, "underwear_bottom", male ) );
569         ret.push_back( get_clothing_item( type, "underwear_feet", male ) );
570         ret.push_back( get_clothing_item( type, "shoes", male ) );
571         ret.push_back( random_item_from( type, "gloves" ) );
572         ret.push_back( random_item_from( type, "coat" ) );
573         ret.push_back( random_item_from( type, "vest" ) );
574         ret.push_back( random_item_from( type, "masks" ) );
575         // Why is the alternative group not named "npc_glasses" but "npc_eyes"?
576         ret.push_back( random_item_from( type, "glasses", item_group_id( "npc_eyes" ) ) );
577         ret.push_back( random_item_from( type, "hat" ) );
578         ret.push_back( random_item_from( type, "scarf" ) );
579         ret.push_back( random_item_from( type, "storage" ) );
580         ret.push_back( random_item_from( type, "holster" ) );
581         ret.push_back( random_item_from( type, "belt" ) );
582         ret.push_back( random_item_from( type, "wrist" ) );
583         ret.push_back( random_item_from( type, "extra" ) );
584     }
585 
586     for( item &it : who.worn ) {
587         it.on_takeoff( who );
588     }
589     who.worn.clear();
590     for( item &it : ret ) {
591         if( it.has_flag( flag_VARSIZE ) ) {
592             it.set_flag( flag_FIT );
593         }
594         if( who.can_wear( it ).success() ) {
595             it.on_wear( who );
596             who.worn.push_back( it );
597             it.set_owner( who );
598         }
599     }
600 }
601 
starting_inv(npc & who,const npc_class_id & type)602 void starting_inv( npc &who, const npc_class_id &type )
603 {
604     std::list<item> res;
605     who.inv->clear();
606     if( item_group::group_is_defined( type->carry_override ) ) {
607         *who.inv += item_group::items_from( type->carry_override );
608         return;
609     }
610 
611     item lighter( "lighter" );
612     // Set lighter ammo
613     if( !lighter.ammo_default().is_null() ) {
614         lighter.ammo_set( lighter.ammo_default(), rng( 10, 100 ) );
615     }
616     res.emplace_back( lighter );
617     // If wielding a gun, get some additional ammo for it
618     if( who.weapon.is_gun() ) {
619         item ammo;
620         if( !who.weapon.magazine_default().is_null() ) {
621             item mag( who.weapon.magazine_default() );
622             mag.ammo_set( mag.ammo_default() );
623             ammo = item( mag.ammo_default() );
624             res.push_back( mag );
625         } else if( !who.weapon.ammo_default().is_null() ) {
626             ammo = item( who.weapon.ammo_default() );
627             // TODO: Move to npc_class
628             // NC_COWBOY and NC_BOUNTY_HUNTER get 5-15 whilst all others get 3-6
629             int qty = 1 + ( type == NC_COWBOY ||
630                             type == NC_BOUNTY_HUNTER );
631             qty = rng( qty, qty * 2 );
632 
633             while( qty-- != 0 && who.can_stash( ammo ) ) {
634                 res.push_back( ammo );
635             }
636         }
637     }
638 
639     if( type == NC_ARSONIST ) {
640         res.emplace_back( "molotov" );
641     }
642 
643     int qty = ( type == NC_EVAC_SHOPKEEP ||
644                 type == NC_TRADER ) ? 5 : 2;
645     qty = rng( qty, qty * 3 );
646 
647     while( qty-- != 0 ) {
648         item tmp = random_item_from( type, "misc" ).in_its_container();
649         if( !tmp.is_null() ) {
650             if( !one_in( 3 ) && tmp.has_flag( flag_VARSIZE ) ) {
651                 tmp.set_flag( flag_FIT );
652             }
653             if( who.can_pickVolume( tmp ) ) {
654                 res.push_back( tmp );
655             }
656         }
657     }
658 
659     res.erase( std::remove_if( res.begin(), res.end(), [&]( const item & e ) {
660         return e.has_flag( flag_TRADER_AVOID );
661     } ), res.end() );
662     for( auto &it : res ) {
663         it.set_owner( who );
664     }
665     *who.inv += res;
666 }
667 
revert_after_activity()668 void npc::revert_after_activity()
669 {
670     mission = previous_mission;
671     attitude = previous_attitude;
672     activity = player_activity();
673     current_activity_id = activity_id::NULL_ID();
674     clear_destination();
675     backlog.clear();
676 }
677 
get_previous_mission()678 npc_mission npc::get_previous_mission()
679 {
680     return previous_mission;
681 }
682 
get_previous_attitude()683 npc_attitude npc::get_previous_attitude()
684 {
685     return previous_attitude;
686 }
687 
get_known_to_u()688 bool npc::get_known_to_u()
689 {
690     return known_to_u;
691 }
692 
set_known_to_u(bool known)693 void npc::set_known_to_u( bool known )
694 {
695     known_to_u = known;
696     if( my_fac ) {
697         my_fac->add_to_membership( getID(), disp_name(), known_to_u );
698     }
699 }
700 
setpos(const tripoint & pos)701 void npc::setpos( const tripoint &pos )
702 {
703     position = pos;
704     const point_abs_om pos_om_old( sm_to_om_copy( submap_coords ) );
705     submap_coords = get_map().get_abs_sub().xy() + point( pos.x / SEEX, pos.y / SEEY );
706     // TODO: fix point types
707     const point_abs_om pos_om_new( sm_to_om_copy( submap_coords ) );
708     if( !is_fake() && pos_om_old != pos_om_new ) {
709         overmap &om_old = overmap_buffer.get( pos_om_old );
710         overmap &om_new = overmap_buffer.get( pos_om_new );
711         if( const auto ptr = om_old.erase_npc( getID() ) ) {
712             om_new.insert_npc( ptr );
713         } else {
714             // Don't move the npc pointer around to avoid having two overmaps
715             // with the same npc pointer
716             debugmsg( "could not find npc %s on its old overmap", name );
717         }
718     }
719 }
720 
travel_overmap(const tripoint & pos)721 void npc::travel_overmap( const tripoint &pos )
722 {
723     // TODO: fix point types
724     const point_abs_om pos_om_old( sm_to_om_copy( submap_coords ) );
725     spawn_at_sm( pos );
726     const point_abs_om pos_om_new( sm_to_om_copy( submap_coords ) );
727     if( global_omt_location() == goal ) {
728         reach_omt_destination();
729     }
730     if( !is_fake() && pos_om_old != pos_om_new ) {
731         overmap &om_old = overmap_buffer.get( pos_om_old );
732         overmap &om_new = overmap_buffer.get( pos_om_new );
733         if( const auto ptr = om_old.erase_npc( getID() ) ) {
734             om_new.insert_npc( ptr );
735         } else {
736             // Don't move the npc pointer around to avoid having two overmaps
737             // with the same npc pointer
738             debugmsg( "could not find npc %s on its old overmap", name );
739         }
740     }
741 }
742 
spawn_at_sm(const tripoint & p)743 void npc::spawn_at_sm( const tripoint &p )
744 {
745     spawn_at_precise( p.xy(), tripoint( rng( 0, SEEX - 1 ), rng( 0, SEEY - 1 ), p.z ) );
746 }
747 
spawn_at_precise(const point & submap_offset,const tripoint & square)748 void npc::spawn_at_precise( const point &submap_offset, const tripoint &square )
749 {
750     submap_coords = submap_offset;
751     submap_coords.x += square.x / SEEX;
752     submap_coords.y += square.y / SEEY;
753     position.x = square.x % SEEX;
754     position.y = square.y % SEEY;
755     position.z = square.z;
756 }
757 
global_square_location() const758 tripoint npc::global_square_location() const
759 {
760     return sm_to_ms_copy( submap_coords ) + tripoint( posx() % SEEX, posy() % SEEY, position.z );
761 }
762 
place_on_map()763 void npc::place_on_map()
764 {
765     // The global absolute position (in map squares) of the npc is *always*
766     // "submap_coords.x * SEEX + posx() % SEEX" (analog for y).
767     // The main map assumes that pos is in its own (local to the main map)
768     // coordinate system. We have to change pos to match that assumption
769     const point dm( submap_coords - get_map().get_abs_sub().xy() );
770     const point offset( position.x % SEEX, position.y % SEEY );
771     // value of "submap_coords.x * SEEX + posx()" is unchanged
772     setpos( tripoint( offset.x + dm.x * SEEX, offset.y + dm.y * SEEY, posz() ) );
773 
774     if( g->is_empty( pos() ) || is_mounted() ) {
775         return;
776     }
777 
778     for( const tripoint &p : closest_points_first( pos(), SEEX + 1 ) ) {
779         if( g->is_empty( p ) ) {
780             setpos( p );
781             return;
782         }
783     }
784 
785     debugmsg( "Failed to place NPC in a valid location near (%d,%d,%d)", posx(), posy(), posz() );
786 }
787 
best_skill() const788 skill_id npc::best_skill() const
789 {
790     int highest_level = std::numeric_limits<int>::min();
791     skill_id highest_skill( skill_id::NULL_ID() );
792 
793     for( const auto &p : *_skills ) {
794         if( p.first.obj().is_combat_skill() ) {
795             const int level = p.second.level();
796             if( level > highest_level ) {
797                 highest_level = level;
798                 highest_skill = p.first;
799             }
800         }
801     }
802 
803     return highest_skill;
804 }
805 
best_skill_level() const806 int npc::best_skill_level() const
807 {
808     int highest_level = std::numeric_limits<int>::min();
809 
810     for( const auto &p : *_skills ) {
811         if( p.first.obj().is_combat_skill() ) {
812             const int level = p.second.level();
813             if( level > highest_level ) {
814                 highest_level = level;
815             }
816         }
817     }
818 
819     return highest_level;
820 }
821 
starting_weapon(const npc_class_id & type)822 void npc::starting_weapon( const npc_class_id &type )
823 {
824     if( item_group::group_is_defined( type->weapon_override ) ) {
825         weapon = item_group::item_from( type->weapon_override, calendar::turn );
826         return;
827     }
828 
829     const skill_id best = best_skill();
830 
831     // if NPC has no suitable skills default to stabbing weapon
832     if( !best || best == skill_stabbing ) {
833         weapon = random_item_from( type, "stabbing", item_group_id( "survivor_stabbing" ) );
834     } else if( best == skill_bashing ) {
835         weapon = random_item_from( type, "bashing", item_group_id( "survivor_bashing" ) );
836     } else if( best == skill_cutting ) {
837         weapon = random_item_from( type, "cutting", item_group_id( "survivor_cutting" ) );
838     } else if( best == skill_throw ) {
839         weapon = random_item_from( type, "throw" );
840     } else if( best == skill_archery ) {
841         weapon = random_item_from( type, "archery" );
842     } else if( best == skill_pistol ) {
843         weapon = random_item_from( type, "pistol", item_group_id( "guns_pistol_common" ) );
844     } else if( best == skill_shotgun ) {
845         weapon = random_item_from( type, "shotgun", item_group_id( "guns_shotgun_common" ) );
846     } else if( best == skill_smg ) {
847         weapon = random_item_from( type, "smg", item_group_id( "guns_smg_common" ) );
848     } else if( best == skill_rifle ) {
849         weapon = random_item_from( type, "rifle", item_group_id( "guns_rifle_common" ) );
850     }
851 
852     if( weapon.is_gun() ) {
853         if( !weapon.magazine_default().is_null() ) {
854             weapon.ammo_set( weapon.magazine_default()->magazine->default_ammo );
855         } else if( !weapon.ammo_default().is_null() ) {
856             weapon.ammo_set( weapon.ammo_default() );
857         } else {
858             debugmsg( "tried setting ammo for %s which has no magazine or ammo", weapon.typeId().c_str() );
859         }
860         //You should be able to wield your starting weapon
861         if( !meets_stat_requirements( weapon ) ) {
862             if( weapon.get_min_str() > get_str() ) {
863                 str_max = weapon.get_min_str();
864             }
865             if( weapon.type->min_dex > get_dex() ) {
866                 dex_max = weapon.type->min_dex;
867             }
868             if( weapon.type->min_int > get_int() ) {
869                 int_max = weapon.type->min_int;
870             }
871             if( weapon.type->min_per > get_per() ) {
872                 per_max = weapon.type->min_per;
873             }
874         }
875     }
876 
877     get_event_bus().send<event_type::character_wields_item>( getID(), weapon.typeId() );
878 
879     weapon.set_owner( get_faction()->id );
880 }
881 
can_read(const item & book,std::vector<std::string> & fail_reasons)882 bool npc::can_read( const item &book, std::vector<std::string> &fail_reasons )
883 {
884     if( !book.is_book() ) {
885         fail_reasons.push_back( string_format( _( "This %s is not good reading material." ),
886                                                book.tname() ) );
887         return false;
888     }
889     player *pl = dynamic_cast<player *>( this );
890     if( !pl ) {
891         return false;
892     }
893     const auto &type = book.type->book;
894     const skill_id &skill = type->skill;
895     const int skill_level = pl->get_skill_level( skill );
896     if( skill && skill_level < type->req ) {
897         fail_reasons.push_back( string_format( _( "I'm not smart enough to read this book." ) ) );
898         return false;
899     }
900     if( !skill || skill_level >= type->level ) {
901         fail_reasons.push_back( string_format( _( "I won't learn anything from this book." ) ) );
902         return false;
903     }
904 
905     // Check for conditions that disqualify us
906     if( type->intel > 0 && has_trait( trait_ILLITERATE ) ) {
907         fail_reasons.emplace_back( _( "I can't read!" ) );
908     } else if( has_trait( trait_HYPEROPIC ) && !worn_with_flag( flag_FIX_FARSIGHT ) &&
909                !has_effect( effect_contacts ) &&
910                !has_flag( STATIC( json_character_flag( "ENHANCED_VISION" ) ) ) ) {
911         fail_reasons.emplace_back( _( "I can't read without my glasses." ) );
912     } else if( fine_detail_vision_mod() > 4 ) {
913         // Too dark to read only applies if the player can read to himself
914         fail_reasons.emplace_back( _( "It's too dark to read!" ) );
915         return false;
916     }
917     return true;
918 }
919 
time_to_read(const item & book,const player & reader) const920 int npc::time_to_read( const item &book, const player &reader ) const
921 {
922     const auto &type = book.type->book;
923     const skill_id &skill = type->skill;
924     // The reader's reading speed has an effect only if they're trying to understand the book as they read it
925     // Reading speed is assumed to be how well you learn from books (as opposed to hands-on experience)
926     const bool try_understand = reader.fun_to_read( book ) ||
927                                 reader.get_skill_level( skill ) < type->level;
928     int reading_speed = try_understand ? std::max( reader.read_speed(), read_speed() ) : read_speed();
929 
930     int retval = type->time * reading_speed;
931     retval *= std::min( fine_detail_vision_mod(), reader.fine_detail_vision_mod() );
932 
933     if( type->intel > reader.get_int() && !reader.has_trait( trait_PROF_DICEMASTER ) ) {
934         retval += type->time * ( type->intel - reader.get_int() ) * 100;
935     }
936     return retval;
937 }
938 
finish_read(item & book)939 void npc::finish_read( item &book )
940 {
941     const auto &reading = book.type->book;
942     if( !reading ) {
943         revert_after_activity();
944         return;
945     }
946     const skill_id &skill = reading->skill;
947     // NPCs don't need to identify the book or learn recipes yet.
948     // NPCs don't read to other NPCs yet.
949     const bool display_messages = my_fac->id == faction_id( "your_followers" ) &&
950                                   get_player_view().sees( pos() );
951     bool continuous = false; //whether to continue reading or not
952 
953     if( book_fun_for( book, *this ) != 0 ) {
954         //Fun bonus is no longer calculated here.
955         add_morale( MORALE_BOOK, book_fun_for( book, *this ) * 5, book_fun_for( book,
956                     *this ) * 15, 1_hours, 30_minutes, true,
957                     book.type );
958     }
959 
960     book.mark_chapter_as_read( *this );
961 
962     if( skill && get_skill_level( skill ) < reading->level &&
963         get_skill_level_object( skill ).can_train() ) {
964         SkillLevel &skill_level = get_skill_level_object( skill );
965         const int originalSkillLevel = skill_level.level();
966 
967         // Calculate experience gained
968         /** @EFFECT_INT increases reading comprehension */
969         // Enhanced Memory Banks modestly boosts experience
970         int min_ex = std::max( 1, reading->time / 10 + get_int() / 4 );
971         int max_ex = reading->time / 5 + get_int() / 2 - originalSkillLevel;
972         if( has_active_bionic( bio_memory ) ) {
973             min_ex += 2;
974         }
975         if( max_ex < 2 ) {
976             max_ex = 2;
977         }
978         if( max_ex > 10 ) {
979             max_ex = 10;
980         }
981         if( max_ex < min_ex ) {
982             max_ex = min_ex;
983         }
984         const std::string &s = activity.get_str_value( 0, "1" );
985         double penalty = strtod( s.c_str(), nullptr );
986         min_ex *= ( originalSkillLevel + 1 ) * penalty;
987         min_ex = std::max( min_ex, 1 );
988         max_ex *= ( originalSkillLevel + 1 ) * penalty;
989         max_ex = std::max( min_ex, max_ex );
990 
991         skill_level.readBook( min_ex, max_ex, reading->level );
992         const std::string skill_name = skill.obj().name();
993         if( skill_level != originalSkillLevel ) {
994             get_event_bus().send<event_type::gains_skill_level>( getID(), skill, skill_level.level() );
995             if( display_messages ) {
996                 add_msg( m_good, _( "%s increases their %s level." ), disp_name(), skill_name );
997                 // NPC reads until they gain a level, then stop.
998                 revert_after_activity();
999                 return;
1000             }
1001         } else {
1002             continuous = true;
1003             if( display_messages ) {
1004                 add_msg( m_info, _( "%s learns a little about %s!" ), disp_name(), skill_name );
1005             }
1006         }
1007 
1008         if( ( skill_level == reading->level || !skill_level.can_train() ) ||
1009             ( has_trait( trait_SCHIZOPHRENIC ) && one_in( 25 ) ) ) {
1010             if( display_messages ) {
1011                 add_msg( m_info, _( "%s can no longer learn from %s." ), disp_name(), book.type_name() );
1012             }
1013         }
1014     } else if( skill ) {
1015         if( display_messages ) {
1016             add_msg( m_info, _( "%s can no longer learn from %s." ), disp_name(), book.type_name() );
1017         }
1018     }
1019 
1020     // NPCs can't learn martial arts from manuals (yet)
1021 
1022     if( continuous ) {
1023         activity.set_to_null();
1024         player *pl = dynamic_cast<player *>( this );
1025         if( pl ) {
1026             start_read( book, pl );
1027         }
1028         if( activity ) {
1029             return;
1030         }
1031     }
1032     activity.set_to_null();
1033     revert_after_activity();
1034 }
1035 
start_read(item & chosen,player * pl)1036 void npc::start_read( item &chosen, player *pl )
1037 {
1038     const int time_taken = time_to_read( chosen, *pl );
1039     const double penalty = static_cast<double>( time_taken ) / time_to_read( chosen, *pl );
1040     player_activity act( ACT_READ, time_taken, 0, pl->getID().get_value() );
1041     act.targets.emplace_back( item_location( *this, &chosen ) );
1042     act.str_values.push_back( std::to_string( penalty ) );
1043     // push an identifier of martial art book to the action handling
1044     if( chosen.type->use_methods.count( "MA_MANUAL" ) ) {
1045         act.str_values.clear();
1046         act.str_values.emplace_back( "martial_art" );
1047     }
1048     assign_activity( act );
1049 }
1050 
do_npc_read()1051 void npc::do_npc_read()
1052 {
1053     // Can read items from inventory or within one tile (including in vehicles)
1054     player *pl = dynamic_cast<player *>( this );
1055     if( !pl ) {
1056         return;
1057     }
1058     item_location loc = game_menus::inv::read( *pl );
1059 
1060     if( loc ) {
1061         std::vector<std::string> fail_reasons;
1062         Character *ch = dynamic_cast<Character *>( pl );
1063         if( !ch ) {
1064             return;
1065         }
1066         item &chosen = *loc.obtain( *ch );
1067         if( can_read( chosen, fail_reasons ) ) {
1068             if( get_player_view().sees( pos() ) ) {
1069                 add_msg( m_info, _( "%s starts reading." ), disp_name() );
1070             }
1071             start_read( chosen, pl );
1072         } else {
1073             for( const auto &elem : fail_reasons ) {
1074                 say( elem );
1075             }
1076         }
1077     } else {
1078         add_msg( _( "Never mind." ) );
1079     }
1080 }
1081 
wear_if_wanted(const item & it,std::string & reason)1082 bool npc::wear_if_wanted( const item &it, std::string &reason )
1083 {
1084     // Note: this function isn't good enough to use with NPC AI alone
1085     // Restrict it to player's orders for now
1086     if( !it.is_armor() ) {
1087         reason = _( "This can't be worn." );
1088         return false;
1089     }
1090 
1091     // Splints ignore limits, but only when being equipped on a broken part
1092     // TODO: Drop splints when healed
1093     if( it.has_flag( flag_SPLINT ) ) {
1094         for( const bodypart_id &bp : get_all_body_parts( get_body_part_flags::only_main ) ) {
1095             if( is_limb_broken( bp ) && !has_effect( effect_mending, bp.id() ) &&
1096                 it.covers( bp ) ) {
1097                 reason = _( "Thanks, I'll wear that now." );
1098                 return !!wear_item( it, false );
1099             }
1100         }
1101     }
1102 
1103     while( !worn.empty() ) {
1104         size_t size_before = worn.size();
1105         // Strip until we can put the new item on
1106         // This is one of the reasons this command is not used by the AI
1107         if( can_wear( it ).success() ) {
1108             // TODO: Hazmat/power armor makes this not work due to 1 boots/headgear limit
1109 
1110             if( !!wear_item( it, false ) ) {
1111                 reason = _( "Thanks, I'll wear that now." );
1112                 return true;
1113             } else {
1114                 reason = _( "I tried but couldn't wear it." );
1115                 return false;
1116             }
1117         }
1118         // Otherwise, maybe we should take off one or more items and replace them
1119         bool took_off = false;
1120         for( const bodypart_id &bp : get_all_body_parts() ) {
1121             if( !it.covers( bp ) ) {
1122                 continue;
1123             }
1124             // Find an item that covers the same body part as the new item
1125             auto iter = std::find_if( worn.begin(), worn.end(), [bp]( const item & armor ) {
1126                 return armor.covers( bp );
1127             } );
1128             if( iter != worn.end() && !( is_limb_broken( bp ) && iter->has_flag( flag_SPLINT ) ) ) {
1129                 took_off = takeoff( *iter );
1130                 break;
1131             }
1132         }
1133 
1134         if( !took_off || worn.size() >= size_before ) {
1135             // Shouldn't happen, but does
1136             reason = _( "I tried but couldn't wear it." );
1137             return false;
1138         }
1139     }
1140     reason = _( "Thanks, I'll wear that now." );
1141     return worn.empty() && wear_item( it, false );
1142 }
1143 
stow_item(item & it)1144 void npc::stow_item( item &it )
1145 {
1146     bool avatar_sees = get_player_view().sees( pos() );
1147     if( wear_item( it, false ) ) {
1148         // Wearing the item was successful, remove weapon and post message.
1149         if( avatar_sees ) {
1150             add_msg_if_npc( m_info, _( "<npcname> wears the %s." ), it.tname() );
1151         }
1152         remove_item( it );
1153         moves -= 15;
1154         // Weapon cannot be worn or wearing was not successful. Store it in inventory if possible,
1155         // otherwise drop it.
1156     } else if( can_stash( it ) ) {
1157         item &ret = i_add( remove_item( it ), true, nullptr, true, false );
1158         if( avatar_sees ) {
1159             add_msg_if_npc( m_info, _( "<npcname> puts away the %s." ), ret.tname() );
1160         }
1161         moves -= 15;
1162     } else { // No room for weapon, so we drop it
1163         if( avatar_sees ) {
1164             add_msg_if_npc( m_info, _( "<npcname> drops the %s." ), it.tname() );
1165         }
1166         get_map().add_item_or_charges( pos(), remove_item( it ) );
1167     }
1168 }
1169 
wield(item & it)1170 bool npc::wield( item &it )
1171 {
1172     // sanity check: exit early if we're trying to wield the current weapon
1173     // needed for ranged_balance_test
1174     if( is_wielding( it ) ) {
1175         return true;
1176     }
1177 
1178     item to_wield;
1179     if( has_item( it ) ) {
1180         to_wield = remove_item( it );
1181     } else {
1182         to_wield = it;
1183     }
1184 
1185     invalidate_inventory_validity_cache();
1186     cached_info.erase( "weapon_value" );
1187     if( has_wield_conflicts( to_wield ) ) {
1188         stow_item( weapon );
1189     }
1190 
1191     if( to_wield.is_null() ) {
1192         weapon = item();
1193         get_event_bus().send<event_type::character_wields_item>( getID(), weapon.typeId() );
1194         return true;
1195     }
1196 
1197     moves -= 15;
1198     if( to_wield.can_combine( weapon ) ) {
1199         weapon.combine( to_wield );
1200     } else {
1201         weapon = to_wield;
1202     }
1203 
1204     get_event_bus().send<event_type::character_wields_item>( getID(), weapon.typeId() );
1205 
1206     if( get_player_view().sees( pos() ) ) {
1207         add_msg_if_npc( m_info, _( "<npcname> wields a %s." ),  weapon.tname() );
1208     }
1209     invalidate_range_cache();
1210     return true;
1211 }
1212 
drop(const drop_locations & what,const tripoint & target,bool stash)1213 void npc::drop( const drop_locations &what, const tripoint &target,
1214                 bool stash )
1215 {
1216     Character::drop( what, target, stash );
1217     // TODO: Remove the hack. Its here because npcs didn't process activities, but they do now
1218     // so is this necessary?
1219     activity.do_turn( *this );
1220 }
1221 
invalidate_range_cache()1222 void npc::invalidate_range_cache()
1223 {
1224     if( weapon.is_gun() ) {
1225         confident_range_cache = confident_shoot_range( weapon, get_most_accurate_sight( weapon ) );
1226     } else {
1227         confident_range_cache = weapon.reach_range( *this );
1228     }
1229 }
1230 
form_opinion(const player & u)1231 void npc::form_opinion( const player &u )
1232 {
1233     // FEAR
1234     if( u.weapon.is_gun() ) {
1235         // TODO: Make bows not guns
1236         if( weapon.is_gun() ) {
1237             op_of_u.fear += 2;
1238         } else {
1239             op_of_u.fear += 6;
1240         }
1241     } else if( u.weapon_value( u.weapon ) > 20 ) {
1242         op_of_u.fear += 2;
1243     } else if( !u.is_armed() ) {
1244         // Unarmed, but actually unarmed ("unarmed weapons" are not unarmed)
1245         op_of_u.fear -= 3;
1246     }
1247 
1248     ///\EFFECT_STR increases NPC fear of the player
1249     if( u.str_max >= 16 ) {
1250         op_of_u.fear += 2;
1251     } else if( u.str_max >= 12 ) {
1252         op_of_u.fear += 1;
1253     } else if( u.str_max <= 3 ) {
1254         op_of_u.fear -= 3;
1255     } else if( u.str_max <= 5 ) {
1256         op_of_u.fear -= 1;
1257     }
1258 
1259     // is your health low
1260     for( const std::pair<const bodypart_str_id, bodypart> &elem : get_player_character().get_body() ) {
1261         const int hp_max = elem.second.get_hp_max();
1262         const int hp_cur = elem.second.get_hp_cur();
1263         if( hp_cur <= hp_max / 2 ) {
1264             op_of_u.fear--;
1265         }
1266     }
1267 
1268     // is my health low
1269     for( const std::pair<const bodypart_str_id, bodypart> &elem : get_body() ) {
1270         const int hp_max = elem.second.get_hp_max();
1271         const int hp_cur = elem.second.get_hp_cur();
1272         if( hp_cur <= hp_max / 2 ) {
1273             op_of_u.fear++;
1274         }
1275     }
1276 
1277     if( u.has_trait( trait_SAPIOVORE ) ) {
1278         op_of_u.fear += 10; // Sapiovores = Scary
1279     }
1280     if( u.has_trait( trait_TERRIFYING ) ) {
1281         op_of_u.fear += 6;
1282     }
1283 
1284     int u_ugly = 0;
1285     for( trait_id &mut : u.get_mutations() ) {
1286         u_ugly += mut.obj().ugliness;
1287     }
1288     op_of_u.fear += u_ugly / 2;
1289     op_of_u.trust -= u_ugly / 3;
1290 
1291     if( u.get_stim() > 20 ) {
1292         op_of_u.fear++;
1293     }
1294 
1295     if( u.has_effect( effect_drunk ) ) {
1296         op_of_u.fear -= 2;
1297     }
1298 
1299     // TRUST
1300     if( op_of_u.fear > 0 ) {
1301         op_of_u.trust -= 3;
1302     } else {
1303         op_of_u.trust += 1;
1304     }
1305 
1306     if( u.weapon.is_gun() ) {
1307         op_of_u.trust -= 2;
1308     } else if( !u.is_armed() ) {
1309         op_of_u.trust += 2;
1310     }
1311 
1312     // TODO: More effects
1313     if( u.has_effect( effect_high ) ) {
1314         op_of_u.trust -= 1;
1315     }
1316     if( u.has_effect( effect_drunk ) ) {
1317         op_of_u.trust -= 2;
1318     }
1319     if( u.get_stim() > 20 || u.get_stim() < -20 ) {
1320         op_of_u.trust -= 1;
1321     }
1322     if( u.get_painkiller() > 30 ) {
1323         op_of_u.trust -= 1;
1324     }
1325 
1326     if( op_of_u.trust > 0 ) {
1327         // Trust is worth a lot right now
1328         op_of_u.trust /= 2;
1329     }
1330 
1331     // VALUE
1332     op_of_u.value = 0;
1333     for( const std::pair<const bodypart_str_id, bodypart> &elem : get_body() ) {
1334         if( elem.second.get_hp_cur() < elem.second.get_hp_max() * 0.8f ) {
1335             op_of_u.value++;
1336         }
1337     }
1338     decide_needs();
1339     for( const npc_need &i : needs ) {
1340         if( i == need_food || i == need_drink ) {
1341             op_of_u.value += 2;
1342         }
1343     }
1344 
1345     if( op_of_u.fear < personality.bravery + 10 &&
1346         op_of_u.fear - personality.aggression > -10 && op_of_u.trust > -8 ) {
1347         set_attitude( NPCATT_TALK );
1348     } else if( op_of_u.fear - 2 * personality.aggression - personality.bravery < -30 ) {
1349         set_attitude( NPCATT_KILL );
1350     } else if( my_fac && my_fac->likes_u < -10 ) {
1351         if( is_player_ally() ) {
1352             mutiny();
1353         }
1354         set_attitude( NPCATT_KILL );
1355     } else {
1356         set_attitude( NPCATT_FLEE_TEMP );
1357     }
1358 
1359     add_msg_debug( "%s formed an opinion of u: %s", name, npc_attitude_id( attitude ) );
1360 }
1361 
mutiny()1362 void npc::mutiny()
1363 {
1364     if( !my_fac || !is_player_ally() ) {
1365         return;
1366     }
1367     const bool seen = get_player_view().sees( pos() );
1368     if( seen ) {
1369         add_msg( m_bad, _( "%s is tired of your incompetent leadership and abuse!" ), disp_name() );
1370     }
1371     // NPCs leaving your faction due to mistreatment further reduce their opinion of you
1372     if( my_fac->likes_u < -10 ) {
1373         op_of_u.trust += my_fac->respects_u / 10;
1374         op_of_u.anger += my_fac->likes_u / 10;
1375     }
1376     // NPCs leaving your faction for abuse reduce the hatred your (remaining) followers
1377     // feel for you, but also reduces their respect for you.
1378     my_fac->likes_u = std::max( 0, my_fac->likes_u / 2 + 10 );
1379     my_fac->respects_u -= 5;
1380     g->remove_npc_follower( getID() );
1381     set_fac( faction_id( "amf" ) );
1382     job.clear_all_priorities();
1383     if( assigned_camp ) {
1384         assigned_camp = cata::nullopt;
1385     }
1386     chatbin.first_topic = "TALK_STRANGER_NEUTRAL";
1387     set_attitude( NPCATT_NULL );
1388     say( _( "<follower_mutiny>  Adios, motherfucker!" ), sounds::sound_t::order );
1389     if( seen ) {
1390         my_fac->known_by_u = true;
1391     }
1392 }
1393 
vehicle_danger(int radius) const1394 float npc::vehicle_danger( int radius ) const
1395 {
1396     const tripoint from( posx() - radius, posy() - radius, posz() );
1397     const tripoint to( posx() + radius, posy() + radius, posz() );
1398     VehicleList vehicles = get_map().get_vehicles( from, to );
1399 
1400     int danger = 0;
1401 
1402     // TODO: check for most dangerous vehicle?
1403     for( size_t i = 0; i < vehicles.size(); ++i ) {
1404         const wrapped_vehicle &wrapped_veh = vehicles[i];
1405         if( wrapped_veh.v->is_moving() ) {
1406             // FIXME: this can't be the right way to do this
1407             units::angle facing = wrapped_veh.v->face.dir();
1408 
1409             point a( wrapped_veh.v->global_pos3().xy() );
1410             point b( static_cast<int>( a.x + units::cos( facing ) * radius ),
1411                      static_cast<int>( a.y + units::sin( facing ) * radius ) );
1412 
1413             // fake size
1414             /* This will almost certainly give the wrong size/location on customized
1415              * vehicles. This should just count frames instead. Or actually find the
1416              * size. */
1417             vehicle_part last_part;
1418             // vehicle_part_range is a forward only iterator, see comment in vpart_range.h
1419             for( const vpart_reference &vpr : wrapped_veh.v->get_all_parts() ) {
1420                 last_part = vpr.part();
1421             }
1422             int size = std::max( last_part.mount.x, last_part.mount.y );
1423 
1424             double normal = std::sqrt( static_cast<float>( ( b.x - a.x ) * ( b.x - a.x ) + ( b.y - a.y ) *
1425                                        ( b.y - a.y ) ) );
1426             int closest = static_cast<int>( std::abs( ( posx() - a.x ) * ( b.y - a.y ) - ( posy() - a.y ) *
1427                                             ( b.x - a.x ) ) / normal );
1428 
1429             if( size > closest ) {
1430                 danger = i;
1431             }
1432         }
1433     }
1434     return danger;
1435 }
1436 
turned_hostile() const1437 bool npc::turned_hostile() const
1438 {
1439     return ( op_of_u.anger >= hostile_anger_level() );
1440 }
1441 
hostile_anger_level() const1442 int npc::hostile_anger_level() const
1443 {
1444     return ( 20 + op_of_u.fear - personality.aggression );
1445 }
1446 
make_angry()1447 void npc::make_angry()
1448 {
1449     if( is_enemy() ) {
1450         return; // We're already angry!
1451     }
1452 
1453     // player allies that become angry should stop being player allies
1454     if( is_player_ally() ) {
1455         mutiny();
1456     }
1457 
1458     // Make associated faction, if any, angry at the player too.
1459     if( my_fac && my_fac->id != faction_id( "no_faction" ) && my_fac->id != faction_id( "amf" ) ) {
1460         my_fac->likes_u = std::min( -15, my_fac->likes_u - 5 );
1461         my_fac->respects_u = std::min( -15, my_fac->respects_u - 5 );
1462     }
1463     if( op_of_u.fear > 10 + personality.aggression + personality.bravery ) {
1464         set_attitude( NPCATT_FLEE_TEMP ); // We don't want to take u on!
1465     } else {
1466         set_attitude( NPCATT_KILL ); // Yeah, we think we could take you!
1467     }
1468 }
1469 
on_attacked(const Creature & attacker)1470 void npc::on_attacked( const Creature &attacker )
1471 {
1472     if( is_hallucination() ) {
1473         die( nullptr );
1474     }
1475     if( attacker.is_player() && !is_enemy() ) {
1476         make_angry();
1477         hit_by_player = true;
1478     }
1479 }
1480 
assigned_missions_value()1481 int npc::assigned_missions_value()
1482 {
1483     int ret = 0;
1484     for( auto &m : chatbin.missions_assigned ) {
1485         ret += m->get_value();
1486     }
1487     return ret;
1488 }
1489 
skills_offered_to(const player & p) const1490 std::vector<skill_id> npc::skills_offered_to( const player &p ) const
1491 {
1492     std::vector<skill_id> ret;
1493     for( const auto &pair : *_skills ) {
1494         const skill_id &id = pair.first;
1495         if( p.get_skill_level( id ) < pair.second.level() ) {
1496             ret.push_back( id );
1497         }
1498     }
1499     return ret;
1500 }
1501 
proficiencies_offered_to(const Character & guy) const1502 std::vector<proficiency_id> npc::proficiencies_offered_to( const Character &guy ) const
1503 {
1504     std::vector<proficiency_id> ret;
1505     for( const proficiency_id &known : known_proficiencies() ) {
1506         if( !guy.has_proficiency( known ) ) {
1507             ret.push_back( known );
1508         }
1509     }
1510     return ret;
1511 }
1512 
styles_offered_to(const player & p) const1513 std::vector<matype_id> npc::styles_offered_to( const player &p ) const
1514 {
1515     return p.martial_arts_data->get_unknown_styles( *martial_arts_data );
1516 }
1517 
spells_offered_to(player & p)1518 std::vector<spell_id> npc::spells_offered_to( player &p )
1519 {
1520     std::vector<spell_id> teachable;
1521     for( const spell_id &sp : magic->spells() ) {
1522         const spell &teacher_spell = magic->get_spell( sp );
1523         if( p.magic->can_learn_spell( p, sp ) ) {
1524             if( p.magic->knows_spell( sp ) ) {
1525                 const spell &student_spell = p.magic->get_spell( sp );
1526                 if( student_spell.is_max_level() ||
1527                     student_spell.get_level() >= teacher_spell.get_level() ) {
1528                     continue;
1529                 }
1530             }
1531             teachable.emplace_back( sp );
1532         }
1533     }
1534     return teachable;
1535 }
1536 
decide_needs()1537 void npc::decide_needs()
1538 {
1539     double needrank[num_needs];
1540     for( auto &elem : needrank ) {
1541         elem = 20;
1542     }
1543     if( weapon.is_gun() ) {
1544         int ups_drain = weapon.get_gun_ups_drain();
1545         if( ups_drain > 0 ) {
1546             int ups_charges = charges_of( itype_UPS_off, ups_drain ) +
1547                               charges_of( itype_UPS_off, ups_drain );
1548             needrank[need_ammo] = static_cast<double>( ups_charges ) / ups_drain;
1549         } else {
1550             const ammotype ammo_type = weapon.ammo_type();
1551             if( ammo_type != ammotype::NULL_ID() ) {
1552                 needrank[need_ammo] = get_ammo( ammo_type ).size();
1553             }
1554         }
1555         needrank[need_ammo] *= 5;
1556     }
1557     if( !base_location ) {
1558         needrank[need_safety] = 1;
1559     }
1560 
1561     needrank[need_weapon] = weapon_value( weapon );
1562     needrank[need_food] = 15 - get_hunger();
1563     needrank[need_drink] = 15 - get_thirst();
1564     const auto inv_food = items_with( []( const item & itm ) {
1565         return itm.is_food();
1566     } );
1567     for( const item *food : inv_food ) {
1568         needrank[ need_food ] += nutrition_for( *food ) / 4.0;
1569         needrank[ need_drink ] += food->get_comestible()->quench / 4.0;
1570     }
1571     needs.clear();
1572     size_t j;
1573     bool serious = false;
1574     for( int i = 1; i < num_needs; i++ ) {
1575         if( needrank[i] < 10 ) {
1576             serious = true;
1577         }
1578     }
1579     if( !serious ) {
1580         needs.push_back( need_none );
1581         needrank[0] = 10;
1582     }
1583     for( int i = 1; i < num_needs; i++ ) {
1584         if( needrank[i] < 20 ) {
1585             for( j = 0; j < needs.size(); j++ ) {
1586                 if( needrank[i] < needrank[needs[j]] ) {
1587                     needs.insert( needs.begin() + j, static_cast<npc_need>( i ) );
1588                     j = needs.size() + 1;
1589                 }
1590             }
1591             if( j == needs.size() ) {
1592                 needs.push_back( static_cast<npc_need>( i ) );
1593             }
1594         }
1595     }
1596 }
1597 
say(const std::string & line,const sounds::sound_t spriority) const1598 void npc::say( const std::string &line, const sounds::sound_t spriority ) const
1599 {
1600     std::string formatted_line = line;
1601     Character &player_character = get_player_character();
1602     parse_tags( formatted_line, player_character, *this );
1603     if( has_trait( trait_MUTE ) ) {
1604         return;
1605     }
1606 
1607     std::string sound = string_format( _( "%1$s saying \"%2$s\"" ), name, formatted_line );
1608     if( player_character.is_deaf() ) {
1609         add_msg_if_player_sees( *this, m_warning, _( "%1$s says something but you can't hear it!" ), name );
1610     }
1611     if( player_character.is_mute() ) {
1612         add_msg_if_player_sees( *this, m_warning, _( "%1$s says something but you can't reply to it!" ),
1613                                 name );
1614     }
1615     // Hallucinations don't make noise when they speak
1616     if( is_hallucination() ) {
1617         add_msg( _( "%1$s saying \"%2$s\"" ), name, formatted_line );
1618         return;
1619     }
1620     // Sound happens even if we can't hear it
1621     if( spriority == sounds::sound_t::order || spriority == sounds::sound_t::alert ) {
1622         sounds::sound( pos(), get_shout_volume(), spriority, sound, false, "speech",
1623                        male ? "NPC_m" : "NPC_f" );
1624     } else {
1625         sounds::sound( pos(), 16, sounds::sound_t::speech, sound, false, "speech",
1626                        male ? "NPC_m_loud" : "NPC_f_loud" );
1627     }
1628 }
1629 
wants_to_sell(const item & it) const1630 bool npc::wants_to_sell( const item &it ) const
1631 {
1632     if( !it.is_owned_by( *this ) ) {
1633         return false;
1634     }
1635     const int market_price = it.price( true );
1636     return wants_to_sell( it, value( it, market_price ), market_price );
1637 }
1638 
wants_to_sell(const item & it,int at_price,int) const1639 bool npc::wants_to_sell( const item &it, int at_price, int /*market_price*/ ) const
1640 {
1641     if( will_exchange_items_freely() ) {
1642         return true;
1643     }
1644 
1645     // Keep items that we never want to trade and the ones we don't want to trade while in use.
1646     if( it.has_flag( flag_TRADER_KEEP ) ||
1647         ( it.has_flag( flag_TRADER_KEEP_EQUIPPED ) && ( is_worn( it ) || is_wielding( it ) ) ) ) {
1648         return false;
1649     }
1650 
1651     // TODO: Base on inventory
1652     return at_price >= 0;
1653 }
1654 
wants_to_buy(const item & it) const1655 bool npc::wants_to_buy( const item &it ) const
1656 {
1657     const int market_price = it.price( true );
1658     return wants_to_buy( it, value( it, market_price ), market_price );
1659 }
1660 
wants_to_buy(const item & it,int at_price,int) const1661 bool npc::wants_to_buy( const item &it, int at_price, int /*market_price*/ ) const
1662 {
1663     if( will_exchange_items_freely() ) {
1664         return true;
1665     }
1666 
1667     if( it.has_flag( flag_TRADER_AVOID ) ) {
1668         return false;
1669     }
1670 
1671     // TODO: Base on inventory
1672     return at_price > 0;
1673 }
1674 
1675 // Will the NPC freely exchange items with the player?
will_exchange_items_freely() const1676 bool npc::will_exchange_items_freely() const
1677 {
1678     return is_player_ally();
1679 }
1680 
1681 // What's the maximum credit the NPC is willing to extend to the player?
1682 // This is currently very scrooge-like; NPCs are only likely to extend a few dollars
1683 // of credit at most.
max_credit_extended() const1684 int npc::max_credit_extended() const
1685 {
1686     if( is_player_ally() ) {
1687         return INT_MAX;
1688     }
1689 
1690     const int credit_trust    = 50;
1691     const int credit_value    = 50;
1692     const int credit_fear     = 50;
1693     const int credit_altruism = 100;
1694     const int credit_anger    = -200;
1695 
1696     return std::max( 0,
1697                      op_of_u.trust * credit_trust +
1698                      op_of_u.value * credit_value +
1699                      op_of_u.fear  * credit_fear  +
1700                      personality.altruism * credit_altruism +
1701                      op_of_u.anger * credit_anger
1702                    );
1703 }
1704 
1705 // How much is the NPC willing to owe the player?
1706 // This is much more generous, as it's the essentially the player holding the risk here.
max_willing_to_owe() const1707 int npc::max_willing_to_owe() const
1708 {
1709     if( is_player_ally() ) {
1710         return INT_MAX;
1711     }
1712 
1713     const int credit_trust    = 10000;
1714     const int credit_value    = 10000;
1715     const int credit_fear     = 10000;
1716     const int credit_altruism = 0;
1717     const int credit_anger    = -10000;
1718 
1719     return std::max( 0,
1720                      op_of_u.trust * credit_trust +
1721                      op_of_u.value * credit_value +
1722                      op_of_u.fear  * credit_fear  +
1723                      personality.altruism * credit_altruism +
1724                      op_of_u.anger * credit_anger
1725                    );
1726 
1727 }
1728 
shop_restock()1729 void npc::shop_restock()
1730 {
1731     if( ( restock != calendar::turn_zero ) && ( ( calendar::turn - restock ) < 3_days ) ) {
1732         return;
1733     }
1734 
1735     restock = calendar::turn + 3_days;
1736     if( is_player_ally() ) {
1737         return;
1738     }
1739     const item_group_id &from = myclass->get_shopkeeper_items();
1740     if( from == item_group_id( "EMPTY_GROUP" ) ) {
1741         return;
1742     }
1743 
1744     units::volume total_space = volume_capacity();
1745     if( mission == NPC_MISSION_SHOPKEEP ) {
1746         total_space = units::from_liter( 5000 );
1747     }
1748 
1749     std::list<item> ret;
1750     int shop_value = 75000;
1751     if( my_fac ) {
1752         shop_value = my_fac->wealth * 0.0075;
1753         if( mission == NPC_MISSION_SHOPKEEP && !my_fac->currency.is_empty() ) {
1754             item my_currency( my_fac->currency );
1755             if( !my_currency.is_null() ) {
1756                 my_currency.set_owner( *this );
1757                 int my_amount = rng( 5, 15 ) * shop_value / 100 / my_currency.price( true );
1758                 for( int lcv = 0; lcv < my_amount; lcv++ ) {
1759                     ret.push_back( my_currency );
1760                 }
1761             }
1762         }
1763     }
1764 
1765     int count = 0;
1766     bool last_item = false;
1767     while( shop_value > 0 && total_space > 0_ml && !last_item ) {
1768         item tmpit = item_group::item_from( from, calendar::turn );
1769         if( !tmpit.is_null() && total_space >= tmpit.volume() ) {
1770             tmpit.set_owner( *this );
1771             ret.push_back( tmpit );
1772             shop_value -= tmpit.price( true );
1773             total_space -= tmpit.volume();
1774             count += 1;
1775             last_item = count > 10 && one_in( 100 );
1776         }
1777     }
1778 
1779     // This removes some items according to item spawn scaling factor,
1780     const float spawn_rate = get_option<float>( "ITEM_SPAWNRATE" );
1781     if( spawn_rate < 1 ) {
1782         ret.remove_if( [spawn_rate]( auto & ) {
1783             return !( rng_float( 0, 1 ) < spawn_rate );
1784         } );
1785     }
1786 
1787     has_new_items = true;
1788     inv->clear();
1789     inv->push_back( ret );
1790 }
1791 
minimum_item_value() const1792 int npc::minimum_item_value() const
1793 {
1794     // TODO: Base on inventory
1795     int ret = 20;
1796     ret -= personality.collector;
1797     return ret;
1798 }
1799 
update_worst_item_value()1800 void npc::update_worst_item_value()
1801 {
1802     worst_item_value = 99999;
1803     // TODO: Cache this
1804     int inv_val = inv->worst_item_value( this );
1805     if( inv_val < worst_item_value ) {
1806         worst_item_value = inv_val;
1807     }
1808 }
1809 
value(const item & it) const1810 int npc::value( const item &it ) const
1811 {
1812     int market_price = it.price( true );
1813     return value( it, market_price );
1814 }
1815 
value(const item & it,int market_price) const1816 int npc::value( const item &it, int market_price ) const
1817 {
1818     if( it.is_dangerous() || ( it.has_flag( flag_BOMB ) && it.active ) ||
1819         it.made_of( phase_id::LIQUID ) ) {
1820         // NPCs won't be interested in buying active explosives or spilled liquids
1821         return -1000;
1822     }
1823 
1824     // faction currency trades at market price
1825     if( my_fac && my_fac->currency == it.typeId() ) {
1826         return market_price;
1827     }
1828 
1829     int ret = 0;
1830     // TODO: Cache own weapon value (it can be a bit expensive to compute 50 times/turn)
1831     double weapon_val = weapon_value( it ) - weapon_value( weapon );
1832     if( weapon_val > 0 ) {
1833         ret += weapon_val;
1834     }
1835 
1836     if( it.is_food() ) {
1837         int comestval = 0;
1838         if( nutrition_for( it ) > 0 || it.get_comestible()->quench > 0 ) {
1839             comestval++;
1840         }
1841         if( get_hunger() > 40 ) {
1842             comestval += ( nutrition_for( it ) + get_hunger() - 40 ) / 6;
1843         }
1844         if( get_thirst() > 40 ) {
1845             comestval += ( it.get_comestible()->quench + get_thirst() - 40 ) / 4;
1846         }
1847         if( comestval > 0 && will_eat( it ).success() ) {
1848             ret += comestval;
1849         }
1850     }
1851 
1852     if( it.is_ammo() ) {
1853         if( weapon.is_gun() && weapon.ammo_types().count( it.ammo_type() ) ) {
1854             // TODO: magazines - don't count ammo as usable if the weapon isn't.
1855             ret += 14;
1856         }
1857 
1858         if( has_gun_for_ammo( it.ammo_type() ) ) {
1859             // TODO: consider making this cumulative (once was)
1860             ret += 14;
1861         }
1862     }
1863 
1864     if( it.is_book() ) {
1865         auto &book = *it.type->book;
1866         ret += book.fun;
1867         if( book.skill && get_skill_level( book.skill ) < book.level &&
1868             get_skill_level( book.skill ) >= book.req ) {
1869             ret += book.level * 3;
1870         }
1871     }
1872 
1873     // Practical item value is more important than price
1874     ret *= 50;
1875 
1876     // TODO: Sometimes we want more than one tool?  Also we don't want EVERY tool.
1877     if( it.is_tool() && !has_amount( it.typeId(), 1 ) ) {
1878         ret += market_price * 0.2; // 20% premium for fresh tools
1879     }
1880     ret += market_price;
1881     return ret;
1882 }
1883 
clear_all()1884 void healing_options::clear_all()
1885 {
1886     bandage = false;
1887     disinfect = false;
1888     bleed = false;
1889     bite = false;
1890     infect = false;
1891 }
1892 
all_false()1893 bool healing_options::all_false()
1894 {
1895     return !any_true();
1896 }
1897 
any_true()1898 bool healing_options::any_true()
1899 {
1900     return bandage || bleed || bite || infect || disinfect;
1901 }
1902 
set_all()1903 void healing_options::set_all()
1904 {
1905     bandage = true;
1906     bleed = true;
1907     bite = true;
1908     infect = true;
1909     disinfect = true;
1910 }
1911 
has_healing_item(healing_options try_to_fix)1912 bool npc::has_healing_item( healing_options try_to_fix )
1913 {
1914     return !get_healing_item( try_to_fix, true ).is_null();
1915 }
1916 
has_healing_options()1917 healing_options npc::has_healing_options()
1918 {
1919     healing_options try_to_fix;
1920     try_to_fix.set_all();
1921     return has_healing_options( try_to_fix );
1922 }
1923 
has_healing_options(healing_options try_to_fix)1924 healing_options npc::has_healing_options( healing_options try_to_fix )
1925 {
1926     healing_options can_fix;
1927     can_fix.clear_all();
1928     healing_options *fix_p = &can_fix;
1929 
1930     visit_items( [&fix_p, try_to_fix]( item * node, item * ) {
1931         const use_function *use = node->type->get_use( "heal" );
1932         if( use == nullptr ) {
1933             return VisitResponse::NEXT;
1934         }
1935 
1936         const heal_actor &actor = dynamic_cast<const heal_actor &>( *( use->get_actor_ptr() ) );
1937         if( try_to_fix.bandage && !fix_p->bandage && actor.bandages_power > 0.0f ) {
1938             fix_p->bandage = true;
1939         }
1940         if( try_to_fix.disinfect && !fix_p->disinfect && actor.disinfectant_power > 0.0f ) {
1941             fix_p->disinfect = true;
1942         }
1943         if( try_to_fix.bleed && !fix_p->bleed && actor.bleed > 0 ) {
1944             fix_p->bleed = true;
1945         }
1946         if( try_to_fix.bite && !fix_p->bite && actor.bite > 0 ) {
1947             fix_p->bite = true;
1948         }
1949         if( try_to_fix.infect && !fix_p->infect && actor.infect > 0 ) {
1950             fix_p->infect = true;
1951         }
1952         // if we've found items for everything we're looking for, we're done
1953         if( ( !try_to_fix.bandage || fix_p->bandage ) &&
1954             ( !try_to_fix.disinfect || fix_p->disinfect ) &&
1955             ( !try_to_fix.bleed || fix_p->bleed ) &&
1956             ( !try_to_fix.bite || fix_p->bite ) &&
1957             ( !try_to_fix.infect || fix_p->infect ) ) {
1958             return VisitResponse::ABORT;
1959         }
1960 
1961         return VisitResponse::NEXT;
1962     } );
1963     return can_fix;
1964 }
1965 
get_healing_item(healing_options try_to_fix,bool first_best)1966 item &npc::get_healing_item( healing_options try_to_fix, bool first_best )
1967 {
1968     item *best = &null_item_reference();
1969     visit_items( [&best, try_to_fix, first_best]( item * node, item * ) {
1970         const use_function *use = node->type->get_use( "heal" );
1971         if( use == nullptr ) {
1972             return VisitResponse::NEXT;
1973         }
1974 
1975         const heal_actor &actor = dynamic_cast<const heal_actor &>( *( use->get_actor_ptr() ) );
1976         if( ( try_to_fix.bandage && actor.bandages_power > 0.0f ) ||
1977             ( try_to_fix.disinfect && actor.disinfectant_power > 0.0f ) ||
1978             ( try_to_fix.bleed && actor.bleed > 0 ) ||
1979             ( try_to_fix.bite && actor.bite > 0 ) ||
1980             ( try_to_fix.infect && actor.infect > 0 ) ) {
1981             best = node;
1982             if( first_best ) {
1983                 return VisitResponse::ABORT;
1984             }
1985         }
1986 
1987         return VisitResponse::NEXT;
1988     } );
1989 
1990     return *best;
1991 }
1992 
has_painkiller()1993 bool npc::has_painkiller()
1994 {
1995     return inv->has_enough_painkiller( get_pain() );
1996 }
1997 
took_painkiller() const1998 bool npc::took_painkiller() const
1999 {
2000     return ( has_effect( effect_pkill1 ) || has_effect( effect_pkill2 ) ||
2001              has_effect( effect_pkill3 ) || has_effect( effect_pkill_l ) );
2002 }
2003 
get_faction_ver() const2004 int npc::get_faction_ver() const
2005 {
2006     return faction_api_version;
2007 }
2008 
set_faction_ver(int new_version)2009 void npc::set_faction_ver( int new_version )
2010 {
2011     faction_api_version = new_version;
2012 }
2013 
has_faction_relationship(const player & p,const npc_factions::relationship flag) const2014 bool npc::has_faction_relationship( const player &p, const npc_factions::relationship flag ) const
2015 {
2016     faction *p_fac = p.get_faction();
2017     if( !my_fac || !p_fac ) {
2018         return false;
2019     }
2020 
2021     return my_fac->has_relationship( p_fac->id, flag );
2022 }
2023 
is_ally(const Character & p) const2024 bool npc::is_ally( const Character &p ) const
2025 {
2026     if( p.getID() == getID() ) {
2027         return true;
2028     }
2029     if( p.is_player() ) {
2030         if( my_fac && my_fac->id == faction_id( "your_followers" ) ) {
2031             return true;
2032         }
2033         if( faction_api_version < 2 ) {
2034             // legacy attitude support so let's be specific here
2035             if( attitude == NPCATT_FOLLOW || attitude == NPCATT_LEAD ||
2036                 attitude == NPCATT_WAIT || mission == NPC_MISSION_ACTIVITY ||
2037                 mission == NPC_MISSION_TRAVELLING || mission == NPC_MISSION_GUARD_ALLY ||
2038                 has_companion_mission() ) {
2039                 return true;
2040             }
2041         }
2042     } else {
2043         const npc &guy = dynamic_cast<const npc &>( p );
2044         if( my_fac && guy.get_faction() && my_fac->id == guy.get_faction()->id ) {
2045             return true;
2046         }
2047         if( faction_api_version < 2 ) {
2048             Character &player_character = get_player_character();
2049             if( is_ally( player_character ) && guy.is_ally( player_character ) ) {
2050                 return true;
2051             } else if( get_attitude_group( get_attitude() ) ==
2052                        guy.get_attitude_group( guy.get_attitude() ) ) {
2053                 return true;
2054             }
2055         }
2056     }
2057     return false;
2058 }
2059 
is_player_ally() const2060 bool npc::is_player_ally() const
2061 {
2062     return is_ally( get_player_character() );
2063 }
2064 
is_friendly(const Character & p) const2065 bool npc::is_friendly( const Character &p ) const
2066 {
2067     return is_ally( p ) || ( p.is_player() && ( is_walking_with() || is_player_ally() ) );
2068 }
2069 
is_minion() const2070 bool npc::is_minion() const
2071 {
2072     return is_player_ally() && op_of_u.trust >= 5;
2073 }
2074 
guaranteed_hostile() const2075 bool npc::guaranteed_hostile() const
2076 {
2077     return is_enemy() || ( my_fac && my_fac->likes_u < -10 );
2078 }
2079 
is_walking_with() const2080 bool npc::is_walking_with() const
2081 {
2082     return attitude == NPCATT_FOLLOW || attitude == NPCATT_LEAD || attitude == NPCATT_WAIT;
2083 }
2084 
is_obeying(const Character & p) const2085 bool npc::is_obeying( const Character &p ) const
2086 {
2087     return ( p.is_player() && is_walking_with() && is_player_ally() ) ||
2088            ( is_ally( p ) && is_stationary( true ) );
2089 }
2090 
is_following() const2091 bool npc::is_following() const
2092 {
2093     return attitude == NPCATT_FOLLOW || attitude == NPCATT_WAIT;
2094 }
2095 
is_leader() const2096 bool npc::is_leader() const
2097 {
2098     return attitude == NPCATT_LEAD;
2099 }
2100 
within_boundaries_of_camp() const2101 bool npc::within_boundaries_of_camp() const
2102 {
2103     const point_abs_omt p( global_omt_location().xy() );
2104     for( int x2 = -3; x2 < 3; x2++ ) {
2105         for( int y2 = -3; y2 < 3; y2++ ) {
2106             const point_abs_omt nearby = p + point( x2, y2 );
2107             cata::optional<basecamp *> bcp = overmap_buffer.find_camp( nearby );
2108             if( bcp ) {
2109                 return true;
2110             }
2111         }
2112     }
2113     return false;
2114 }
2115 
is_enemy() const2116 bool npc::is_enemy() const
2117 {
2118     return attitude == NPCATT_KILL || attitude == NPCATT_FLEE || attitude == NPCATT_FLEE_TEMP;
2119 }
2120 
is_stationary(bool include_guards) const2121 bool npc::is_stationary( bool include_guards ) const
2122 {
2123     if( include_guards && is_guarding() ) {
2124         return true;
2125     }
2126     return mission == NPC_MISSION_SHELTER || mission == NPC_MISSION_SHOPKEEP ||
2127            has_effect( effect_infection );
2128 }
2129 
is_guarding() const2130 bool npc::is_guarding( ) const
2131 {
2132     return mission == NPC_MISSION_GUARD || mission == NPC_MISSION_GUARD_ALLY || is_patrolling();
2133 }
2134 
is_patrolling() const2135 bool npc::is_patrolling() const
2136 {
2137     return mission == NPC_MISSION_GUARD_PATROL;
2138 }
2139 
has_player_activity() const2140 bool npc::has_player_activity() const
2141 {
2142     return activity && mission == NPC_MISSION_ACTIVITY && attitude == NPCATT_ACTIVITY;
2143 }
2144 
is_travelling() const2145 bool npc::is_travelling() const
2146 {
2147     return mission == NPC_MISSION_TRAVELLING;
2148 }
2149 
attitude_to(const Creature & other) const2150 Creature::Attitude npc::attitude_to( const Creature &other ) const
2151 {
2152     if( other.is_npc() || other.is_player() ) {
2153         const player &guy = dynamic_cast<const player &>( other );
2154         // check faction relationships first
2155         if( has_faction_relationship( guy, npc_factions::kill_on_sight ) ) {
2156             return Attitude::HOSTILE;
2157         } else if( has_faction_relationship( guy, npc_factions::watch_your_back ) ) {
2158             return Attitude::FRIENDLY;
2159         }
2160     }
2161 
2162     Character &player_character = get_player_character();
2163     if( is_player_ally() ) {
2164         // Friendly NPCs share player's alliances
2165         return player_character.attitude_to( other );
2166     }
2167 
2168     if( other.is_npc() ) {
2169         // Hostile NPCs are also hostile towards player's allies
2170         if( is_enemy() && other.attitude_to( player_character ) == Attitude::FRIENDLY ) {
2171             return Attitude::HOSTILE;
2172         }
2173 
2174         return Attitude::NEUTRAL;
2175     } else if( other.is_player() ) {
2176         // For now, make it symmetric.
2177         return other.attitude_to( *this );
2178     }
2179 
2180     // TODO: Get rid of the ugly cast without duplicating checks
2181     const monster &m = dynamic_cast<const monster &>( other );
2182     switch( m.attitude( this ) ) {
2183         case MATT_FOLLOW:
2184         case MATT_FPASSIVE:
2185         case MATT_IGNORE:
2186         case MATT_FLEE:
2187             return Attitude::NEUTRAL;
2188         case MATT_FRIEND:
2189             return Attitude::FRIENDLY;
2190         case MATT_ATTACK:
2191             return Attitude::HOSTILE;
2192         case MATT_NULL:
2193         case NUM_MONSTER_ATTITUDES:
2194             break;
2195     }
2196 
2197     return Attitude::NEUTRAL;
2198 }
2199 
npc_dismount()2200 void npc::npc_dismount()
2201 {
2202     if( !mounted_creature || !has_effect( effect_riding ) ) {
2203         add_msg_debug( "NPC %s tried to dismount, but they have no mount, or they are not riding",
2204                        disp_name() );
2205         return;
2206     }
2207     cata::optional<tripoint> pnt;
2208     for( const auto &elem : get_map().points_in_radius( pos(), 1 ) ) {
2209         if( g->is_empty( elem ) ) {
2210             pnt = elem;
2211             break;
2212         }
2213     }
2214     if( !pnt ) {
2215         add_msg_debug( "NPC %s could not find a place to dismount.", disp_name() );
2216         return;
2217     }
2218     remove_effect( effect_riding );
2219     if( mounted_creature->has_flag( MF_RIDEABLE_MECH ) &&
2220         !mounted_creature->type->mech_weapon.is_empty() ) {
2221         remove_item( weapon );
2222     }
2223     mounted_creature->remove_effect( effect_ridden );
2224     mounted_creature->add_effect( effect_controlled, 5_turns );
2225     mounted_creature = nullptr;
2226     setpos( *pnt );
2227     mod_moves( -100 );
2228 }
2229 
smash_ability() const2230 int npc::smash_ability() const
2231 {
2232     if( !is_hallucination() && ( !is_player_ally() || rules.has_flag( ally_rule::allow_bash ) ) ) {
2233         ///\EFFECT_STR_NPC increases smash ability
2234         return str_cur + weapon.damage_melee( damage_type::BASH );
2235     }
2236 
2237     // Not allowed to bash
2238     return 0;
2239 }
2240 
danger_assessment()2241 float npc::danger_assessment()
2242 {
2243     return ai_cache.danger_assessment;
2244 }
2245 
average_damage_dealt()2246 float npc::average_damage_dealt()
2247 {
2248     return static_cast<float>( melee_value( weapon ) );
2249 }
2250 
bravery_check(int diff)2251 bool npc::bravery_check( int diff )
2252 {
2253     return ( dice( 10 + personality.bravery, 6 ) >= dice( diff, 4 ) );
2254 }
2255 
emergency() const2256 bool npc::emergency() const
2257 {
2258     return emergency( ai_cache.danger_assessment );
2259 }
2260 
emergency(float danger) const2261 bool npc::emergency( float danger ) const
2262 {
2263     return ( danger > ( personality.bravery * 3 * hp_percentage() ) / 100.0 );
2264 }
2265 
2266 //Check if this npc is currently in the list of active npcs.
2267 //Active npcs are the npcs near the player that are actively simulated.
is_active() const2268 bool npc::is_active() const
2269 {
2270     return g->critter_at<npc>( pos() ) == this;
2271 }
2272 
follow_distance() const2273 int npc::follow_distance() const
2274 {
2275     Character &player_character = get_player_character();
2276     map &here = get_map();
2277     // HACK: If the player is standing on stairs, follow closely
2278     // This makes the stair hack less painful to use
2279     if( is_walking_with() &&
2280         ( here.has_flag( TFLAG_GOES_DOWN, player_character.pos() ) ||
2281           here.has_flag( TFLAG_GOES_UP, player_character.pos() ) ) ) {
2282         return 1;
2283     }
2284     // Uses ally_rule follow_distance_2 to determine if should follow by 2 or 4 tiles
2285     if( rules.has_flag( ally_rule::follow_distance_2 ) ) {
2286         return 2;
2287     }
2288     // If NPC doesn't see player, change follow distance to 2
2289     if( !sees( player_character ) ) {
2290         return 2;
2291     }
2292     return 4;
2293 }
2294 
basic_symbol_color() const2295 nc_color npc::basic_symbol_color() const
2296 {
2297     if( attitude == NPCATT_KILL ) {
2298         return c_red;
2299     } else if( attitude == NPCATT_FLEE || attitude == NPCATT_FLEE_TEMP ) {
2300         return c_light_red;
2301     } else if( is_player_ally() ) {
2302         return c_green;
2303     } else if( is_walking_with() ) {
2304         return c_light_green;
2305     } else if( guaranteed_hostile() ) {
2306         return c_red;
2307     }
2308     return c_pink;
2309 }
2310 
print_info(const catacurses::window & w,int line,int vLines,int column) const2311 int npc::print_info( const catacurses::window &w, int line, int vLines, int column ) const
2312 {
2313     const int last_line = line + vLines;
2314     const int iWidth = getmaxx( w ) - 1 - column;
2315     // First line of w is the border; the next 4 are terrain info, and after that
2316     // is a blank line. w is 13 characters tall, and we can't use the last one
2317     // because it's a border as well; so we have lines 6 through 11.
2318     // w is also 48 characters wide - 2 characters for border = 46 characters for us
2319 
2320     // Print health bar and NPC name on the first line.
2321     std::pair<std::string, nc_color> bar = get_hp_bar( hp_percentage(), 100 );
2322     mvwprintz( w, point( column, line ), bar.second, bar.first );
2323     const int bar_max_width = 5;
2324     const int bar_width = utf8_width( bar.first );
2325     for( int i = 0; i < bar_max_width - bar_width; ++i ) {
2326         mvwprintz( w, point( column + 4 - i, line ), c_white, "." );
2327     }
2328     line += fold_and_print( w, point( column + bar_max_width + 1, line ),
2329                             iWidth - bar_max_width - 1, basic_symbol_color(), name );
2330 
2331     Character &player_character = get_player_character();
2332     // Hostility indicator in the second line.
2333     Attitude att = attitude_to( player_character );
2334     const std::pair<translation, nc_color> res = Creature::get_attitude_ui_data( att );
2335     mvwprintz( w, point( column, line++ ), res.second, res.first.translated() );
2336 
2337     // Awareness indicator on the third line.
2338     std::string senses_str = sees( player_character ) ? _( "Aware of your presence" ) :
2339                              _( "Unaware of you" );
2340     line += fold_and_print( w, point( column, line ), iWidth,
2341                             sees( player_character ) ? c_yellow : c_green,
2342                             senses_str );
2343 
2344     // Print what item the NPC is holding if any on the fourth line.
2345     if( is_armed() ) {
2346         line += fold_and_print( w, point( column, line ), iWidth, c_red,
2347                                 std::string( "<color_light_gray>" ) + _( "Wielding: " ) + std::string( "</color>" ) +
2348                                 weapon.tname() );
2349     }
2350 
2351     // Worn gear list on following lines.
2352     const std::string worn_str = enumerate_as_string( worn.begin(), worn.end(), []( const item & it ) {
2353         return it.tname();
2354     } );
2355     if( !worn_str.empty() ) {
2356         std::vector<std::string> worn_lines = foldstring( _( "Wearing: " ) + worn_str, iWidth );
2357         int worn_numlines = worn_lines.size();
2358         for( int i = 0; i < worn_numlines && line < last_line; i++ ) {
2359             if( line + 1 == last_line ) {
2360                 worn_lines[i].append( "…" );
2361             }
2362             trim_and_print( w, point( column, line++ ), iWidth, c_light_gray, worn_lines[i] );
2363         }
2364     }
2365 
2366     if( line == last_line ) {
2367         return line;
2368     }
2369 
2370     // as of now, visibility of mutations is between 0 and 10
2371     // 10 perception and 10 distance would see all mutations - cap 0
2372     // 10 perception and 30 distance - cap 5, some mutations visible
2373     // 3 perception and 3 distance would see all mutations - cap 0
2374     // 3 perception and 15 distance - cap 5, some mutations visible
2375     // 3 perception and 20 distance would be barely able to discern huge antlers on a person - cap 10
2376     const int per = player_character.get_per();
2377     const int dist = rl_dist( player_character.pos(), pos() );
2378     int visibility_cap;
2379     if( per <= 1 ) {
2380         visibility_cap = INT_MAX;
2381     } else {
2382         visibility_cap = std::round( dist * dist / 20.0 / ( per - 1 ) );
2383     }
2384 
2385     const std::string trait_str = visible_mutations( visibility_cap );
2386     if( !trait_str.empty() ) {
2387         std::vector<std::string> trait_lines = foldstring( _( "Traits: " ) + trait_str, iWidth );
2388         int trait_numlines = trait_lines.size();
2389         for( int i = 0; i < trait_numlines && line < last_line; i++ ) {
2390             if( line + 1 == last_line ) {
2391                 trait_lines[i].append( "…" );
2392             }
2393             trim_and_print( w, point( column, line++ ), iWidth, c_light_gray, trait_lines[i] );
2394         }
2395     }
2396 
2397     return line;
2398 }
2399 
opinion_text() const2400 std::string npc::opinion_text() const
2401 {
2402     std::string ret;
2403     std::string desc;
2404 
2405     if( op_of_u.trust <= -10 ) {
2406         desc = _( "Completely untrusting" );
2407     } else if( op_of_u.trust <= -6 ) {
2408         desc = _( "Very untrusting" );
2409     } else if( op_of_u.trust <= -3 ) {
2410         desc = _( "Untrusting" );
2411     } else if( op_of_u.trust <= 2 ) {
2412         desc = _( "Uneasy" );
2413     } else if( op_of_u.trust <= 4 ) {
2414         desc = _( "Trusting" );
2415     } else if( op_of_u.trust < 10 ) {
2416         desc = _( "Very trusting" );
2417     } else {
2418         desc = _( "Completely trusting" );
2419     }
2420 
2421     ret += string_format( _( "Trust: %d (%s);\n" ), op_of_u.trust, desc );
2422 
2423     if( op_of_u.fear <= -10 ) {
2424         desc = _( "Thinks you're laughably harmless" );
2425     } else if( op_of_u.fear <= -6 ) {
2426         desc = _( "Thinks you're harmless" );
2427     } else if( op_of_u.fear <= -3 ) {
2428         desc = _( "Unafraid" );
2429     } else if( op_of_u.fear <= 2 ) {
2430         desc = _( "Wary" );
2431     } else if( op_of_u.fear <= 5 ) {
2432         desc = _( "Afraid" );
2433     } else if( op_of_u.fear < 10 ) {
2434         desc = _( "Very afraid" );
2435     } else {
2436         desc = _( "Terrified" );
2437     }
2438 
2439     ret += string_format( _( "Fear: %d (%s);\n" ), op_of_u.fear, desc );
2440 
2441     if( op_of_u.value <= -10 ) {
2442         desc = _( "Considers you a major liability" );
2443     } else if( op_of_u.value <= -6 ) {
2444         desc = _( "Considers you a burden" );
2445     } else if( op_of_u.value <= -3 ) {
2446         desc = _( "Considers you an annoyance" );
2447     } else if( op_of_u.value <= 2 ) {
2448         desc = _( "Doesn't care about you" );
2449     } else if( op_of_u.value <= 5 ) {
2450         desc = _( "Values your presence" );
2451     } else if( op_of_u.value < 10 ) {
2452         desc = _( "Treasures you" );
2453     } else {
2454         desc = _( "Best Friends Forever!" );
2455     }
2456 
2457     ret += string_format( _( "Value: %d (%s);\n" ), op_of_u.value, desc );
2458 
2459     if( op_of_u.anger <= -10 ) {
2460         desc = _( "You can do no wrong!" );
2461     } else if( op_of_u.anger <= -6 ) {
2462         desc = _( "You're good people" );
2463     } else if( op_of_u.anger <= -3 ) {
2464         desc = _( "Thinks well of you" );
2465     } else if( op_of_u.anger <= 2 ) {
2466         desc = _( "Ambivalent" );
2467     } else if( op_of_u.anger <= 5 ) {
2468         desc = _( "Pissed off" );
2469     } else if( op_of_u.anger < 10 ) {
2470         desc = _( "Angry" );
2471     } else {
2472         desc = _( "About to kill you" );
2473     }
2474 
2475     ret += string_format( _( "Anger: %d (%s)." ), op_of_u.anger, desc );
2476 
2477     return ret;
2478 }
2479 
maybe_shift(cata::optional<tripoint> & pos,const point & d)2480 static void maybe_shift( cata::optional<tripoint> &pos, const point &d )
2481 {
2482     if( pos ) {
2483         *pos += d;
2484     }
2485 }
2486 
maybe_shift(tripoint & pos,const point & d)2487 static void maybe_shift( tripoint &pos, const point &d )
2488 {
2489     if( pos != tripoint_min ) {
2490         pos += d;
2491     }
2492 }
2493 
shift(const point & s)2494 void npc::shift( const point &s )
2495 {
2496     const point shift = sm_to_ms_copy( s );
2497 
2498     setpos( pos() - shift );
2499 
2500     maybe_shift( wanted_item_pos, point( -shift.x, -shift.y ) );
2501     maybe_shift( last_player_seen_pos, point( -shift.x, -shift.y ) );
2502     maybe_shift( pulp_location, point( -shift.x, -shift.y ) );
2503     path.clear();
2504 }
2505 
is_dead() const2506 bool npc::is_dead() const
2507 {
2508     return dead || is_dead_state();
2509 }
2510 
reboot()2511 void npc::reboot()
2512 {
2513     //The NPC got into an infinite loop, in game.cpp  -monmove() - a debugmsg just popped up
2514     // informing player of this.
2515     // put them to sleep and reboot their brain.
2516     // they can be woken up by the player, and if their brain is fixed, great,
2517     // if not, they will faint again, and the NPC can be kept asleep until the bug is fixed.
2518     cancel_activity();
2519     path.clear();
2520     last_player_seen_pos = cata::nullopt;
2521     last_seen_player_turn = 999;
2522     wanted_item_pos = tripoint_min;
2523     guard_pos = tripoint_min;
2524     goal = no_goal_point;
2525     fetching_item = false;
2526     has_new_items = true;
2527     worst_item_value = 0;
2528     mission = NPC_MISSION_NULL;
2529     patience = 0;
2530     ai_cache.danger = 0;
2531     ai_cache.total_danger = 0;
2532     ai_cache.danger_assessment = 0;
2533     ai_cache.target.reset();
2534     ai_cache.ally.reset();
2535     ai_cache.can_heal.clear_all();
2536     ai_cache.sound_alerts.clear();
2537     ai_cache.s_abs_pos = tripoint_zero;
2538     ai_cache.stuck = 0;
2539     ai_cache.guard_pos = cata::nullopt;
2540     ai_cache.my_weapon_value = 0;
2541     ai_cache.friends.clear();
2542     ai_cache.dangerous_explosives.clear();
2543     ai_cache.threat_map.clear();
2544     ai_cache.searched_tiles.clear();
2545     activity = player_activity();
2546     clear_destination();
2547     add_effect( effect_npc_suspend, 24_hours, true, 1 );
2548 }
2549 
die(Creature * nkiller)2550 void npc::die( Creature *nkiller )
2551 {
2552     if( dead ) {
2553         // We are already dead, don't die again, note that npc::dead is
2554         // *only* set to true in this function!
2555         return;
2556     }
2557     if( assigned_camp ) {
2558         cata::optional<basecamp *> bcp = overmap_buffer.find_camp( ( *assigned_camp ).xy() );
2559         if( bcp ) {
2560             ( *bcp )->remove_assignee( getID() );
2561         }
2562     }
2563     assigned_camp = cata::nullopt;
2564     // Need to unboard from vehicle before dying, otherwise
2565     // the vehicle code cannot find us
2566     if( in_vehicle ) {
2567         get_map().unboard_vehicle( pos(), true );
2568     }
2569     if( is_mounted() ) {
2570         monster *critter = mounted_creature.get();
2571         critter->remove_effect( effect_ridden );
2572         critter->mounted_player = nullptr;
2573         critter->mounted_player_id = character_id();
2574     }
2575     // if this NPC was the only member of a micro-faction, clean it up.
2576     if( my_fac ) {
2577         if( !is_fake() && !is_hallucination() ) {
2578             if( my_fac->members.size() == 1 ) {
2579                 for( const item *elem : inv_dump() ) {
2580                     elem->remove_owner();
2581                     elem->remove_old_owner();
2582                 }
2583             }
2584             my_fac->remove_member( getID() );
2585         }
2586     }
2587     dead = true;
2588     Character::die( nkiller );
2589 
2590     if( is_hallucination() ) {
2591         add_msg_if_player_sees( *this, _( "%s disappears." ), name.c_str() );
2592         return;
2593     }
2594 
2595     add_msg_if_player_sees( *this, _( "%s dies!" ), name );
2596 
2597     if( Character *ch = dynamic_cast<Character *>( killer ) ) {
2598         get_event_bus().send<event_type::character_kills_character>( ch->getID(), getID(), get_name() );
2599     }
2600 
2601     Character &player_character = get_player_character();
2602     if( killer == &player_character && ( !guaranteed_hostile() || hit_by_player ) ) {
2603         bool cannibal = player_character.has_trait( trait_CANNIBAL );
2604         bool psycho = player_character.has_trait( trait_PSYCHOPATH );
2605         if( player_character.has_trait( trait_SAPIOVORE ) || psycho ) {
2606             // No morale effect
2607         } else if( cannibal ) {
2608             player_character.add_morale( MORALE_KILLED_INNOCENT, -5, 0, 2_days, 3_hours );
2609         } else {
2610             player_character.add_morale( MORALE_KILLED_INNOCENT, -100, 0, 2_days, 3_hours );
2611         }
2612     }
2613 
2614     place_corpse();
2615 }
2616 
npc_attitude_id(npc_attitude att)2617 std::string npc_attitude_id( npc_attitude att )
2618 {
2619     static const std::map<npc_attitude, std::string> npc_attitude_ids = {
2620         { NPCATT_NULL, "NPCATT_NULL" },
2621         { NPCATT_TALK, "NPCATT_TALK" },
2622         { NPCATT_FOLLOW, "NPCATT_FOLLOW" },
2623         { NPCATT_LEAD, "NPCATT_LEAD" },
2624         { NPCATT_WAIT, "NPCATT_WAIT" },
2625         { NPCATT_MUG, "NPCATT_MUG" },
2626         { NPCATT_WAIT_FOR_LEAVE, "NPCATT_WAIT_FOR_LEAVE" },
2627         { NPCATT_KILL, "NPCATT_KILL" },
2628         { NPCATT_FLEE, "NPCATT_FLEE" },
2629         { NPCATT_FLEE_TEMP, "NPCATT_FLEE_TEMP" },
2630         { NPCATT_HEAL, "NPCATT_HEAL" },
2631         { NPCATT_ACTIVITY, "NPCATT_ACTIVITY" },
2632         { NPCATT_RECOVER_GOODS, "NPCATT_RECOVER_GOODS" },
2633         { NPCATT_LEGACY_1, "NPCATT_LEGACY_1" },
2634         { NPCATT_LEGACY_2, "NPCATT_LEGACY_2" },
2635         { NPCATT_LEGACY_3, "NPCATT_LEGACY_3" },
2636         { NPCATT_LEGACY_4, "NPCATT_LEGACY_4" },
2637         { NPCATT_LEGACY_5, "NPCATT_LEGACY_5" },
2638         { NPCATT_LEGACY_6, "NPCATT_LEGACY_6" },
2639     };
2640     const auto &iter = npc_attitude_ids.find( att );
2641     if( iter == npc_attitude_ids.end() ) {
2642         debugmsg( "Invalid attitude: %d", att );
2643         return "NPCATT_INVALID";
2644     }
2645 
2646     return iter->second;
2647 }
2648 
npc_attitude_name(npc_attitude att)2649 std::string npc_attitude_name( npc_attitude att )
2650 {
2651     switch( att ) {
2652         // Don't care/ignoring player
2653         case NPCATT_NULL:
2654             return _( "Ignoring" );
2655         // Move to and talk to player
2656         case NPCATT_TALK:
2657             return _( "Wants to talk" );
2658         // Follow the player
2659         case NPCATT_FOLLOW:
2660             return _( "Following" );
2661         // Lead the player, wait for them if they're behind
2662         case NPCATT_LEAD:
2663             return _( "Leading" );
2664         // Waiting for the player
2665         case NPCATT_WAIT:
2666             return _( "Waiting for you" );
2667         // Mug the player
2668         case NPCATT_MUG:
2669             return _( "Mugging you" );
2670         // Attack the player if our patience runs out
2671         case NPCATT_WAIT_FOR_LEAVE:
2672             return _( "Waiting for you to leave" );
2673         // Kill the player
2674         case NPCATT_KILL:
2675             return _( "Attacking to kill" );
2676         // Get away from the player
2677         case NPCATT_FLEE:
2678         case NPCATT_FLEE_TEMP:
2679             return _( "Fleeing" );
2680         // Get to the player and heal them
2681         case NPCATT_HEAL:
2682             return _( "Healing you" );
2683         case NPCATT_ACTIVITY:
2684             return _( "Performing a task" );
2685         case NPCATT_RECOVER_GOODS:
2686             return _( "Trying to recover stolen goods" );
2687         case NPCATT_LEGACY_1:
2688         case NPCATT_LEGACY_2:
2689         case NPCATT_LEGACY_3:
2690         case NPCATT_LEGACY_4:
2691         case NPCATT_LEGACY_5:
2692         case NPCATT_LEGACY_6:
2693             return _( "NPC Legacy Attitude" );
2694         default:
2695             break;
2696     }
2697 
2698     debugmsg( "Invalid attitude: %d", att );
2699     return _( "Unknown attitude" );
2700 }
2701 
2702 //message related stuff
2703 
2704 //message related stuff
add_msg_if_npc(const std::string & msg) const2705 void npc::add_msg_if_npc( const std::string &msg ) const
2706 {
2707     add_msg( replace_with_npc_name( msg ) );
2708 }
2709 
add_msg_player_or_npc(const std::string &,const std::string & npc_msg) const2710 void npc::add_msg_player_or_npc( const std::string &/*player_msg*/,
2711                                  const std::string &npc_msg ) const
2712 {
2713     add_msg_if_player_sees( *this, replace_with_npc_name( npc_msg ) );
2714 }
2715 
add_msg_if_npc(const game_message_params & params,const std::string & msg) const2716 void npc::add_msg_if_npc( const game_message_params &params, const std::string &msg ) const
2717 {
2718     add_msg( params, replace_with_npc_name( msg ) );
2719 }
2720 
add_msg_player_or_npc(const game_message_params & params,const std::string &,const std::string & npc_msg) const2721 void npc::add_msg_player_or_npc( const game_message_params &params,
2722                                  const std::string &/*player_msg*/,
2723                                  const std::string &npc_msg ) const
2724 {
2725     if( get_player_view().sees( *this ) ) {
2726         add_msg( params, replace_with_npc_name( npc_msg ) );
2727     }
2728 }
2729 
add_msg_player_or_say(const std::string &,const std::string & npc_speech) const2730 void npc::add_msg_player_or_say( const std::string &/*player_msg*/,
2731                                  const std::string &npc_speech ) const
2732 {
2733     say( npc_speech );
2734 }
2735 
add_msg_player_or_say(const game_message_params &,const std::string &,const std::string & npc_speech) const2736 void npc::add_msg_player_or_say( const game_message_params &/*params*/,
2737                                  const std::string &/*player_msg*/, const std::string &npc_speech ) const
2738 {
2739     say( npc_speech );
2740 }
2741 
add_new_mission(class mission * miss)2742 void npc::add_new_mission( class mission *miss )
2743 {
2744     chatbin.add_new_mission( miss );
2745 }
2746 
on_unload()2747 void npc::on_unload()
2748 {
2749 }
2750 
2751 // A throtled version of player::update_body since npc's don't need to-the-turn updates.
npc_update_body()2752 void npc::npc_update_body()
2753 {
2754     if( calendar::once_every( 10_seconds ) ) {
2755         update_body( last_updated, calendar::turn );
2756         last_updated = calendar::turn;
2757     }
2758 }
2759 
on_load()2760 void npc::on_load()
2761 {
2762     const auto advance_effects = [&]( const time_duration & elapsed_dur ) {
2763         for( auto &elem : *effects ) {
2764             for( auto &_effect_it : elem.second ) {
2765                 effect &e = _effect_it.second;
2766                 const time_duration &time_left = e.get_duration();
2767                 if( time_left > 1_turns ) {
2768                     if( time_left < elapsed_dur ) {
2769                         e.set_duration( 1_turns );
2770                     } else {
2771                         e.set_duration( time_left - elapsed_dur );
2772                     }
2773                 }
2774             }
2775         }
2776     };
2777     // Cap at some reasonable number, say 2 days
2778     const time_duration dt = std::min( calendar::turn - last_updated, 2_days );
2779     // TODO: Sleeping, healing etc.
2780     last_updated = calendar::turn;
2781     time_point cur = calendar::turn - dt;
2782     add_msg_debug( "on_load() by %s, %d turns", name, to_turns<int>( dt ) );
2783     // First update with 30 minute granularity, then 5 minutes, then turns
2784     for( ; cur < calendar::turn - 30_minutes; cur += 30_minutes + 1_turns ) {
2785         update_body( cur, cur + 30_minutes );
2786         advance_effects( 30_minutes );
2787     }
2788     for( ; cur < calendar::turn - 5_minutes; cur += 5_minutes + 1_turns ) {
2789         update_body( cur, cur + 5_minutes );
2790         advance_effects( 5_minutes );
2791     }
2792     for( ; cur < calendar::turn; cur += 1_turns ) {
2793         update_body( cur, cur + 1_turns );
2794         process_effects();
2795     }
2796 
2797     if( dt > 0_turns ) {
2798         // This ensures food is properly rotten at load
2799         // Otherwise NPCs try to eat rotten food and fail
2800         process_items();
2801         // give NPCs that are doing activities a pile of moves
2802         if( has_destination() || activity ) {
2803             mod_moves( to_moves<int>( dt ) );
2804         }
2805     }
2806 
2807     // Not necessarily true, but it's not a bad idea to set this
2808     has_new_items = true;
2809 
2810     map &here = get_map();
2811     // for spawned npcs
2812     if( here.has_flag( "UNSTABLE", pos() ) ) {
2813         add_effect( effect_bouldering, 1_turns,  true );
2814     } else if( has_effect( effect_bouldering ) ) {
2815         remove_effect( effect_bouldering );
2816     }
2817     if( here.veh_at( pos() ).part_with_feature( VPFLAG_BOARDABLE, true ) && !in_vehicle ) {
2818         here.board_vehicle( pos(), this );
2819     }
2820     if( has_effect( effect_riding ) && !mounted_creature ) {
2821         if( const monster *const mon = g->critter_at<monster>( pos() ) ) {
2822             mounted_creature = g->shared_from( *mon );
2823         } else {
2824             add_msg_debug( "NPC is meant to be riding, though the mount is not found when %s is loaded",
2825                            disp_name() );
2826         }
2827     }
2828     if( has_trait( trait_HALLUCINATION ) ) {
2829         hallucination = true;
2830     }
2831 }
2832 
2833 constexpr tripoint_abs_omt npc::no_goal_point;
2834 
query_yn(const std::string &) const2835 bool npc::query_yn( const std::string &/*msg*/ ) const
2836 {
2837     // NPCs don't like queries - most of them are in the form of "Do you want to get hurt?".
2838     return false;
2839 }
2840 
speed_rating() const2841 float npc::speed_rating() const
2842 {
2843     float ret = get_speed() / 100.0f;
2844     ret *= 100.0f / run_cost( 100, false );
2845 
2846     return ret;
2847 }
2848 
dispose_item(item_location && obj,const std::string &)2849 bool npc::dispose_item( item_location &&obj, const std::string & )
2850 {
2851     stow_item( *obj.get_item() );
2852     return true;
2853 }
2854 
process_turn()2855 void npc::process_turn()
2856 {
2857     player::process_turn();
2858 
2859     // NPCs shouldn't be using stamina, but if they have, set it back to max
2860     // If the stamina is higher than the max (Languorous), set it back to max
2861     if( calendar::once_every( 1_minutes ) && get_stamina() != get_stamina_max() ) {
2862         set_stamina( get_stamina_max() );
2863     }
2864 
2865     if( is_player_ally() && calendar::once_every( 1_hours ) &&
2866         get_hunger() < 200 && get_thirst() < 100 && op_of_u.trust < 5 ) {
2867         // Friends who are well fed will like you more
2868         // 24 checks per day, best case chance at trust 0 is 1 in 48 for +1 trust per 2 days
2869         float trust_chance = 5 - op_of_u.trust;
2870         // Penalize for bad impression
2871         // TODO: Penalize for traits and actions (especially murder, unless NPC is psycho)
2872         int op_penalty = std::max( 0, op_of_u.anger ) +
2873                          std::max( 0, -op_of_u.value ) +
2874                          std::max( 0, op_of_u.fear );
2875         // Being barely hungry and thirsty, not in pain and not wounded means good care
2876         int state_penalty = get_hunger() + get_thirst() + ( 100 - hp_percentage() ) + get_pain();
2877         if( x_in_y( trust_chance, 240 + 10 * op_penalty + state_penalty ) ) {
2878             op_of_u.trust++;
2879         }
2880 
2881         // TODO: Similar checks for fear and anger
2882     }
2883 
2884     // TODO: Add decreasing trust/value/etc. here when player doesn't provide food
2885     // TODO: Make NPCs leave the player if there's a path out of map and player is sleeping/unseen/etc.
2886 }
2887 
invoke_item(item * used,const tripoint & pt,int)2888 bool npc::invoke_item( item *used, const tripoint &pt, int )
2889 {
2890     const auto &use_methods = used->type->use_methods;
2891 
2892     if( use_methods.empty() ) {
2893         return false;
2894     } else if( use_methods.size() == 1 ) {
2895         return Character::invoke_item( used, use_methods.begin()->first, pt );
2896     }
2897     return false;
2898 }
2899 
invoke_item(item * used,const std::string & method)2900 bool npc::invoke_item( item *used, const std::string &method )
2901 {
2902     return Character::invoke_item( used, method );
2903 }
2904 
invoke_item(item * used)2905 bool npc::invoke_item( item *used )
2906 {
2907     return Character::invoke_item( used );
2908 }
2909 
2910 std::array<std::pair<std::string, overmap_location_str_id>, npc_need::num_needs> npc::need_data = {
2911     {
2912         { "need_none", overmap_location_str_id( "source_of_anything" ) },
2913         { "need_ammo", overmap_location_str_id( "source_of_ammo" ) },
2914         { "need_weapon", overmap_location_str_id( "source_of_weapons" )},
2915         { "need_gun", overmap_location_str_id( "source_of_guns" ) },
2916         { "need_food", overmap_location_str_id( "source_of_food" )},
2917         { "need_drink", overmap_location_str_id( "source_of_drink" ) },
2918         { "need_safety", overmap_location_str_id( "source_of_safety" ) }
2919     }
2920 };
2921 
get_need_str_id(const npc_need & need)2922 std::string npc::get_need_str_id( const npc_need &need )
2923 {
2924     return need_data[static_cast<size_t>( need )].first;
2925 }
2926 
get_location_for(const npc_need & need)2927 overmap_location_str_id npc::get_location_for( const npc_need &need )
2928 {
2929     return need_data[static_cast<size_t>( need )].second;
2930 }
2931 
operator <<(std::ostream & os,const npc_need & need)2932 std::ostream &operator<< ( std::ostream &os, const npc_need &need )
2933 {
2934     return os << npc::get_need_str_id( need );
2935 }
2936 
will_accept_from_player(const item & it) const2937 bool npc::will_accept_from_player( const item &it ) const
2938 {
2939     if( is_hallucination() ) {
2940         return false;
2941     }
2942 
2943     if( is_minion() || get_player_character().has_trait( trait_DEBUG_MIND_CONTROL ) ||
2944         it.has_flag( flag_NPC_SAFE ) ) {
2945         return true;
2946     }
2947 
2948     if( !it.type->use_methods.empty() ) {
2949         return false;
2950     }
2951 
2952     if( it.is_comestible() ) {
2953         if( it.get_comestible_fun() < 0 || it.poison > 0 ) {
2954             return false;
2955         }
2956     }
2957 
2958     return true;
2959 }
2960 
get_pathfinding_settings() const2961 const pathfinding_settings &npc::get_pathfinding_settings() const
2962 {
2963     return get_pathfinding_settings( false );
2964 }
2965 
get_pathfinding_settings(bool no_bashing) const2966 const pathfinding_settings &npc::get_pathfinding_settings( bool no_bashing ) const
2967 {
2968     path_settings->bash_strength = no_bashing ? 0 : smash_ability();
2969     // TODO: Extract climb skill
2970     const int climb = std::min( 20, get_dex() );
2971     if( climb > 1 ) {
2972         // Success is !one_in(dex), so 0%, 50%, 66%, 75%...
2973         // Penalty for failure chance is 1/success = 1/(1-failure) = 1/(1-(1/dex)) = dex/(dex-1)
2974         path_settings->climb_cost = ( 10 - climb / 5 ) * climb / ( climb - 1 );
2975     } else {
2976         // Climbing at this dexterity will always fail
2977         path_settings->climb_cost = 0;
2978     }
2979 
2980     return *path_settings;
2981 }
2982 
get_path_avoid() const2983 std::set<tripoint> npc::get_path_avoid() const
2984 {
2985     std::set<tripoint> ret;
2986     for( Creature &critter : g->all_creatures() ) {
2987         // TODO: Cache this somewhere
2988         ret.insert( critter.pos() );
2989     }
2990     map &here = get_map();
2991     if( rules.has_flag( ally_rule::avoid_doors ) ) {
2992         for( const tripoint &p : here.points_in_radius( pos(), 30 ) ) {
2993             if( here.open_door( p, true, true ) ) {
2994                 ret.insert( p );
2995             }
2996         }
2997     }
2998     if( rules.has_flag( ally_rule::hold_the_line ) ) {
2999         for( const tripoint &p : here.points_in_radius( get_player_character().pos(), 1 ) ) {
3000             if( here.close_door( p, true, true ) || here.move_cost( p ) > 2 ) {
3001                 ret.insert( p );
3002             }
3003         }
3004     }
3005     return ret;
3006 }
3007 
get_monster_faction() const3008 mfaction_id npc::get_monster_faction() const
3009 {
3010     if( my_fac ) {
3011         if( my_fac->mon_faction.is_valid() ) {
3012             return my_fac->mon_faction;
3013         }
3014     }
3015 
3016     // legacy checks
3017     // Those can't be static int_ids, because mods add factions
3018     static const string_id<monfaction> human_fac( "human" );
3019     static const string_id<monfaction> player_fac( "player" );
3020     static const string_id<monfaction> bee_fac( "bee" );
3021 
3022     if( is_player_ally() ) {
3023         return player_fac.id();
3024     }
3025 
3026     if( has_trait( trait_BEE ) ) {
3027         return bee_fac.id();
3028     }
3029 
3030     return human_fac.id();
3031 }
3032 
extended_description() const3033 std::string npc::extended_description() const
3034 {
3035     std::string ss;
3036     // For some reason setting it using str or constructor doesn't work
3037     ss += Character::extended_description();
3038 
3039     ss += "\n--\n";
3040     if( attitude == NPCATT_KILL ) {
3041         ss += _( "Is trying to kill you." );
3042     } else if( attitude == NPCATT_FLEE || attitude == NPCATT_FLEE_TEMP ) {
3043         ss += _( "Is trying to flee from you." );
3044     } else if( is_player_ally() ) {
3045         ss += _( "Is your friend." );
3046     } else if( is_following() ) {
3047         ss += _( "Is following you." );
3048     } else if( is_leader() ) {
3049         ss += _( "Is guiding you." );
3050     } else if( guaranteed_hostile() ) {
3051         ss += _( "Will try to kill you or flee from you if you reveal yourself." );
3052     } else {
3053         ss += _( "Is neutral." );
3054     }
3055 
3056     if( hit_by_player ) {
3057         ss += "--\n";
3058         ss += _( "Is still innocent and killing them will be considered murder." );
3059         // TODO: "But you don't care because you're an edgy psycho"
3060     }
3061 
3062     return replace_colors( ss );
3063 }
3064 
get_epilogue() const3065 std::string npc::get_epilogue() const
3066 {
3067     return SNIPPET.random_from_category(
3068                male ? "epilogue_npc_male" : "epilogue_npc_female"
3069            ).value_or( translation() ).translated();
3070 }
3071 
set_companion_mission(npc & p,const std::string & mission_id)3072 void npc::set_companion_mission( npc &p, const std::string &mission_id )
3073 {
3074     const tripoint_abs_omt omt_pos = p.global_omt_location();
3075     set_companion_mission( omt_pos, p.companion_mission_role_id, mission_id );
3076 }
3077 
hp_description() const3078 std::pair<std::string, nc_color> npc::hp_description() const
3079 {
3080     int cur_hp = hp_percentage();
3081     std::string damage_info;
3082     std::string pronoun;
3083     if( male ) {
3084         pronoun = _( "He " );
3085     } else {
3086         pronoun = _( "She " );
3087     }
3088     nc_color col;
3089     if( cur_hp == 100 ) {
3090         damage_info = pronoun + _( "is uninjured." );
3091         col = c_green;
3092     } else if( cur_hp >= 80 ) {
3093         damage_info = pronoun + _( "is lightly injured." );
3094         col = c_light_green;
3095     } else if( cur_hp >= 60 ) {
3096         damage_info = pronoun + _( "is moderately injured." );
3097         col = c_yellow;
3098     } else if( cur_hp >= 30 ) {
3099         damage_info = pronoun + _( "is heavily injured." );
3100         col = c_yellow;
3101     } else if( cur_hp >= 10 ) {
3102         damage_info = pronoun + _( "is severely injured." );
3103         col = c_light_red;
3104     } else {
3105         damage_info = pronoun + _( "is nearly dead!" );
3106         col = c_red;
3107     }
3108     return std::make_pair( damage_info, col );
3109 }
set_companion_mission(const tripoint_abs_omt & omt_pos,const std::string & role_id,const std::string & mission_id)3110 void npc::set_companion_mission( const tripoint_abs_omt &omt_pos, const std::string &role_id,
3111                                  const std::string &mission_id )
3112 {
3113     comp_mission.position = omt_pos;
3114     comp_mission.mission_id = mission_id;
3115     comp_mission.role_id = role_id;
3116 }
3117 
set_companion_mission(const tripoint_abs_omt & omt_pos,const std::string & role_id,const std::string & mission_id,const tripoint_abs_omt & destination)3118 void npc::set_companion_mission( const tripoint_abs_omt &omt_pos, const std::string &role_id,
3119                                  const std::string &mission_id, const tripoint_abs_omt &destination )
3120 {
3121     comp_mission.position = omt_pos;
3122     comp_mission.mission_id = mission_id;
3123     comp_mission.role_id = role_id;
3124     comp_mission.destination = destination;
3125 }
3126 
reset_companion_mission()3127 void npc::reset_companion_mission()
3128 {
3129     comp_mission.position = tripoint_abs_omt( -999, -999, -999 );
3130     comp_mission.mission_id.clear();
3131     comp_mission.role_id.clear();
3132     if( comp_mission.destination ) {
3133         comp_mission.destination = cata::nullopt;
3134     }
3135 }
3136 
get_mission_destination() const3137 cata::optional<tripoint_abs_omt> npc::get_mission_destination() const
3138 {
3139     if( comp_mission.destination ) {
3140         return comp_mission.destination;
3141     } else {
3142         return cata::nullopt;
3143     }
3144 }
3145 
has_companion_mission() const3146 bool npc::has_companion_mission() const
3147 {
3148     return !comp_mission.mission_id.empty();
3149 }
3150 
get_companion_mission() const3151 npc_companion_mission npc::get_companion_mission() const
3152 {
3153     return comp_mission;
3154 }
3155 
get_attitude_group(npc_attitude att) const3156 attitude_group npc::get_attitude_group( npc_attitude att ) const
3157 {
3158     switch( att ) {
3159         case NPCATT_MUG:
3160         case NPCATT_WAIT_FOR_LEAVE:
3161         case NPCATT_KILL:
3162             return attitude_group::hostile;
3163         case NPCATT_FLEE:
3164         case NPCATT_FLEE_TEMP:
3165             return attitude_group::fearful;
3166         case NPCATT_FOLLOW:
3167         case NPCATT_ACTIVITY:
3168         case NPCATT_LEAD:
3169             return attitude_group::friendly;
3170         default:
3171             break;
3172     }
3173     return attitude_group::neutral;
3174 }
3175 
set_mission(npc_mission new_mission)3176 void npc::set_mission( npc_mission new_mission )
3177 {
3178     if( new_mission != mission ) {
3179         previous_mission = mission;
3180         mission = new_mission;
3181     }
3182     if( mission == NPC_MISSION_ACTIVITY ) {
3183         current_activity_id = activity.id();
3184     }
3185 }
3186 
has_activity() const3187 bool npc::has_activity() const
3188 {
3189     return mission == NPC_MISSION_ACTIVITY && attitude == NPCATT_ACTIVITY;
3190 }
3191 
get_attitude() const3192 npc_attitude npc::get_attitude() const
3193 {
3194     return attitude;
3195 }
3196 
set_attitude(npc_attitude new_attitude)3197 void npc::set_attitude( npc_attitude new_attitude )
3198 {
3199     if( new_attitude == attitude ) {
3200         return;
3201     }
3202     previous_attitude = attitude;
3203     if( new_attitude == NPCATT_FLEE ) {
3204         new_attitude = NPCATT_FLEE_TEMP;
3205     }
3206     if( new_attitude == NPCATT_FLEE_TEMP && !has_effect( effect_npc_flee_player ) ) {
3207         add_effect( effect_npc_flee_player, 24_hours );
3208     }
3209 
3210     add_msg_debug( "%s changes attitude from %s to %s",
3211                    name, npc_attitude_id( attitude ), npc_attitude_id( new_attitude ) );
3212     attitude_group new_group = get_attitude_group( new_attitude );
3213     attitude_group old_group = get_attitude_group( attitude );
3214     if( new_group != old_group && !is_fake() && get_player_view().sees( *this ) ) {
3215         switch( new_group ) {
3216             case attitude_group::hostile:
3217                 add_msg_if_npc( m_bad, _( "<npcname> gets angry!" ) );
3218                 break;
3219             case attitude_group::fearful:
3220                 add_msg_if_npc( m_warning, _( "<npcname> gets scared!" ) );
3221                 break;
3222             default:
3223                 if( old_group == attitude_group::hostile ) {
3224                     add_msg_if_npc( m_good, _( "<npcname> calms down." ) );
3225                 } else if( old_group == attitude_group::fearful ) {
3226                     add_msg_if_npc( _( "<npcname> is no longer afraid." ) );
3227                 }
3228                 break;
3229         }
3230     }
3231     attitude = new_attitude;
3232 }
3233 
npc_follower_rules()3234 npc_follower_rules::npc_follower_rules()
3235 {
3236     engagement = combat_engagement::CLOSE;
3237     aim = aim_rule::WHEN_CONVENIENT;
3238     overrides = ally_rule::DEFAULT;
3239     override_enable = ally_rule::DEFAULT;
3240 
3241     set_flag( ally_rule::use_guns );
3242     set_flag( ally_rule::use_grenades );
3243     clear_flag( ally_rule::use_silent );
3244     set_flag( ally_rule::avoid_friendly_fire );
3245 
3246     clear_flag( ally_rule::allow_pick_up );
3247     clear_flag( ally_rule::allow_bash );
3248     clear_flag( ally_rule::allow_sleep );
3249     set_flag( ally_rule::allow_complain );
3250     set_flag( ally_rule::allow_pulp );
3251     clear_flag( ally_rule::close_doors );
3252     clear_flag( ally_rule::follow_close );
3253     clear_flag( ally_rule::avoid_doors );
3254     clear_flag( ally_rule::hold_the_line );
3255     clear_flag( ally_rule::ignore_noise );
3256     clear_flag( ally_rule::forbid_engage );
3257     set_flag( ally_rule::follow_distance_2 );
3258 }
3259 
has_flag(ally_rule test,bool check_override) const3260 bool npc_follower_rules::has_flag( ally_rule test, bool check_override ) const
3261 {
3262     if( check_override && ( static_cast<int>( test ) & static_cast<int>( override_enable ) ) ) {
3263         // if the override is set and false, return false
3264         if( static_cast<int>( test ) & ~static_cast<int>( overrides ) ) {
3265             return false;
3266             // if the override is set and true, return true
3267         } else if( static_cast<int>( test ) & static_cast<int>( overrides ) ) {
3268             return true;
3269         }
3270     }
3271     return static_cast<int>( test ) & static_cast<int>( flags );
3272 }
3273 
set_flag(ally_rule setit)3274 void npc_follower_rules::set_flag( ally_rule setit )
3275 {
3276     flags = static_cast<ally_rule>( static_cast<int>( flags ) | static_cast<int>( setit ) );
3277 }
3278 
clear_flag(ally_rule clearit)3279 void npc_follower_rules::clear_flag( ally_rule clearit )
3280 {
3281     flags = static_cast<ally_rule>( static_cast<int>( flags ) & ~static_cast<int>( clearit ) );
3282 }
3283 
toggle_flag(ally_rule toggle)3284 void npc_follower_rules::toggle_flag( ally_rule toggle )
3285 {
3286     if( has_flag( toggle ) ) {
3287         clear_flag( toggle );
3288     } else {
3289         set_flag( toggle );
3290     }
3291 }
3292 
set_specific_override_state(ally_rule rule,bool state)3293 void npc_follower_rules::set_specific_override_state( ally_rule rule, bool state )
3294 {
3295     if( state ) {
3296         set_override( rule );
3297     } else {
3298         clear_override( rule );
3299     }
3300     enable_override( rule );
3301 }
3302 
toggle_specific_override_state(ally_rule rule,bool state)3303 void npc_follower_rules::toggle_specific_override_state( ally_rule rule, bool state )
3304 {
3305     if( has_override_enable( rule ) && has_override( rule ) == state ) {
3306         clear_override( rule );
3307         disable_override( rule );
3308     } else {
3309         set_specific_override_state( rule, state );
3310     }
3311 }
3312 
has_override_enable(ally_rule test) const3313 bool npc_follower_rules::has_override_enable( ally_rule test ) const
3314 {
3315     return static_cast<int>( test ) & static_cast<int>( override_enable );
3316 }
3317 
enable_override(ally_rule setit)3318 void npc_follower_rules::enable_override( ally_rule setit )
3319 {
3320     override_enable = static_cast<ally_rule>( static_cast<int>( override_enable ) |
3321                       static_cast<int>( setit ) );
3322 }
3323 
disable_override(ally_rule clearit)3324 void npc_follower_rules::disable_override( ally_rule clearit )
3325 {
3326     override_enable = static_cast<ally_rule>( static_cast<int>( override_enable ) &
3327                       ~static_cast<int>( clearit ) );
3328 }
3329 
has_override(ally_rule test) const3330 bool npc_follower_rules::has_override( ally_rule test ) const
3331 {
3332     return static_cast<int>( test ) & static_cast<int>( overrides );
3333 }
3334 
set_override(ally_rule setit)3335 void npc_follower_rules::set_override( ally_rule setit )
3336 {
3337     overrides = static_cast<ally_rule>( static_cast<int>( overrides ) | static_cast<int>( setit ) );
3338 }
3339 
clear_override(ally_rule clearit)3340 void npc_follower_rules::clear_override( ally_rule clearit )
3341 {
3342     overrides = static_cast<ally_rule>( static_cast<int>( overrides ) &
3343                                         ~static_cast<int>( clearit ) );
3344 }
3345 
set_danger_overrides()3346 void npc_follower_rules::set_danger_overrides()
3347 {
3348     overrides = ally_rule::DEFAULT;
3349     override_enable = ally_rule::DEFAULT;
3350     set_override( ally_rule::follow_close );
3351     set_override( ally_rule::avoid_doors );
3352     set_override( ally_rule::hold_the_line );
3353     enable_override( ally_rule::follow_close );
3354     enable_override( ally_rule::allow_sleep );
3355     enable_override( ally_rule::close_doors );
3356     enable_override( ally_rule::avoid_doors );
3357     enable_override( ally_rule::hold_the_line );
3358 }
3359 
clear_overrides()3360 void npc_follower_rules::clear_overrides()
3361 {
3362     overrides = ally_rule::DEFAULT;
3363     override_enable = ally_rule::DEFAULT;
3364 }
3365 
get_thirst() const3366 int npc::get_thirst() const
3367 {
3368     return Character::get_thirst() - units::to_milliliter<int>( stomach.get_water() ) / 5;
3369 }
3370 
describe_mission() const3371 std::string npc::describe_mission() const
3372 {
3373     switch( mission ) {
3374         case NPC_MISSION_SHELTER:
3375             return string_format( _( "I'm holing up here for safety.  Long term, %s" ),
3376                                   myclass.obj().get_job_description() );
3377         case NPC_MISSION_SHOPKEEP:
3378             return _( "I run the shop here." );
3379         case NPC_MISSION_GUARD:
3380         case NPC_MISSION_GUARD_ALLY:
3381         case NPC_MISSION_GUARD_PATROL:
3382             return string_format( _( "Currently, I'm guarding this location.  Overall, %s" ),
3383                                   myclass.obj().get_job_description() );
3384         case NPC_MISSION_ACTIVITY:
3385             return string_format( _( "Right now, I'm <current_activity>.  In general, %s" ),
3386                                   myclass.obj().get_job_description() );
3387         case NPC_MISSION_TRAVELLING:
3388         case NPC_MISSION_NULL:
3389             return myclass.obj().get_job_description();
3390         default:
3391             return string_format( "ERROR: Someone forgot to code an npc_mission text for "
3392                                   "mission: %d.", static_cast<int>( mission ) );
3393     } // switch (mission)
3394 }
3395 
name_and_activity() const3396 std::string npc::name_and_activity() const
3397 {
3398     if( current_activity_id ) {
3399         const std::string activity_name = current_activity_id.obj().verb().translated();
3400         //~ %1$s - npc name, %2$s - npc current activity name.
3401         return string_format( _( "%1$s (%2$s)" ), name, activity_name );
3402     } else {
3403         return name;
3404     }
3405 }
3406 
get_talker_for(npc & guy)3407 std::unique_ptr<talker> get_talker_for( npc &guy )
3408 {
3409     return std::make_unique<talker_npc>( &guy );
3410 }
get_talker_for(npc * guy)3411 std::unique_ptr<talker> get_talker_for( npc *guy )
3412 {
3413     return std::make_unique<talker_npc>( guy );
3414 }
3415