diff --git a/data/json/npcs/common_chat/TALK_COMMON_ALLY.json b/data/json/npcs/common_chat/TALK_COMMON_ALLY.json index 4256814d68d9d..7a8a0e3fc5bf8 100644 --- a/data/json/npcs/common_chat/TALK_COMMON_ALLY.json +++ b/data/json/npcs/common_chat/TALK_COMMON_ALLY.json @@ -887,6 +887,12 @@ "condition": { "and": [ { "not": "npc_has_activity" }, { "not": { "npc_has_trait": "HALLUCINATION" } } ] }, "effect": "do_read" }, + { + "text": "Please study from an e-book.", + "topic": "TALK_DONE", + "condition": { "and": [ { "not": "npc_has_activity" }, { "not": { "npc_has_trait": "HALLUCINATION" } } ] }, + "effect": "do_eread" + }, { "text": "Please start deconstructing any vehicles in a deconstruction zone.", "topic": "TALK_DONE", diff --git a/src/game_inventory.cpp b/src/game_inventory.cpp index 421a2909b7cb3..5a1a723ed3615 100644 --- a/src/game_inventory.cpp +++ b/src/game_inventory.cpp @@ -1218,6 +1218,58 @@ item_location game_menus::inv::gun_to_modify( Character &you, const item &gunmod _( "You don't have any guns to modify." ) ); } +class ereader_inventory_preset : public pickup_inventory_preset +{ + public: + explicit ereader_inventory_preset( const Character &you ) : pickup_inventory_preset( you ), + you( you ) { + _collate_entries = true; + if( get_option( "INV_USE_ACTION_NAMES" ) ) { + append_cell( [ this ]( const item_location & loc ) { + return string_format( "%s", get_action_name( *loc ) ); + }, _( "ACTION" ) ); + } + } + + bool is_shown( const item_location &loc ) const override { + return loc->is_ebook_storage(); + } + + std::string get_denial( const item_location &loc ) const override { + const item &it = *loc; + + if( it.is_broken() ) { + return _( "E-reader is broken and won't turn on." ); + } + + if( !it.ammo_sufficient( &you, "EBOOKREAD" ) ) { + return string_format( + n_gettext( "Needs at least %d charge.", + "Needs at least %d charges.", loc->ammo_required() ), + loc->ammo_required() ); + } + + if( !it.has_flag( flag_ALLOWS_REMOTE_USE ) ) { + return pickup_inventory_preset::get_denial( loc ); + } + + return std::string(); + } + + protected: + std::string get_action_name( const item &it ) const { + return string_format( "Read on %s.", it.tname() ); + } + private: + const Character &you; +}; + +item_location game_menus::inv::ereader_to_use( Character &you ) +{ + const std::string msg = _( "You don't have any e-readers you can use." ); + return inv_internal( you, ereader_inventory_preset( you ), _( "Select e-reader." ), 1, msg ); +} + class read_inventory_preset: public pickup_inventory_preset { public: diff --git a/src/game_inventory.h b/src/game_inventory.h index 26791cad628ca..c3992431bd58c 100644 --- a/src/game_inventory.h +++ b/src/game_inventory.h @@ -116,6 +116,8 @@ item_location disassemble( Character &you ); item_location gun_to_modify( Character &you, const item &gunmod ); /** Book reading menu. */ item_location read( Character &you ); +/** E-Book reading menu. */ +item_location ereader_to_use( Character &you ); /** eBook reading menu. */ item_location ebookread( Character &you, item_location &ereader ); /** Menu for stealing stuff. */ diff --git a/src/npc.cpp b/src/npc.cpp index 28cc9df12a151..b209b15d269e9 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -1354,7 +1354,7 @@ time_duration npc::time_to_read( const item &book, const Character &reader ) con return retval; } -void npc::do_npc_read() +void npc::do_npc_read( bool ebook ) { // Can read items from inventory or within one tile (including in vehicles) Character *npc_player = as_character(); @@ -1362,7 +1362,20 @@ void npc::do_npc_read() return; } - item_location book = game_menus::inv::read( *npc_player ); + item_location book; + item_location ereader; + + if( !ebook ) { + book = game_menus::inv::read( *npc_player ); + } else { + ereader = game_menus::inv::ereader_to_use( *npc_player ); + if( !ereader ) { + add_msg( _( "Never mind." ) ); + return; + } + book = game_menus::inv::ebookread( *npc_player, ereader ); + } + if( !book ) { add_msg( _( "Never mind." ) ); return; @@ -1380,7 +1393,6 @@ void npc::do_npc_read() // NPCs can't read to other NPCs yet const time_duration time_taken = time_to_read( *book, *this ); - item_location ereader = {}; // NPCs read until they gain a level read_activity_actor actor( time_taken, book, ereader, true, getID().get_value() ); diff --git a/src/npc.h b/src/npc.h index f689da4cf91cf..c3f92b0d9c4a5 100644 --- a/src/npc.h +++ b/src/npc.h @@ -922,7 +922,7 @@ class npc : public Character bool wear_if_wanted( const item &it, std::string &reason ); bool can_read( const item &book, std::vector &fail_reasons ); time_duration time_to_read( const item &book, const Character &reader ) const; - void do_npc_read(); + void do_npc_read( bool ebook = false ); void stow_item( item &it ); bool wield( item &it ) override; void drop( const drop_locations &what, const tripoint &target, diff --git a/src/npctalk.cpp b/src/npctalk.cpp index c766f1349b503..cfa7575e39e02 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -5140,6 +5140,7 @@ void talk_effect_t::parse_string_effect( const std::string &effect_id, const Jso WRAP( do_mining ), WRAP( do_mopping ), WRAP( do_read ), + WRAP( do_eread ), WRAP( do_butcher ), WRAP( do_farming ), WRAP( assign_guard ), diff --git a/src/npctalk.h b/src/npctalk.h index 5477fc908658b..2f6b3e65c40c8 100644 --- a/src/npctalk.h +++ b/src/npctalk.h @@ -53,6 +53,7 @@ void do_construction( npc & ); void do_mining( npc & ); void do_mopping( npc & ); void do_read( npc & ); +void do_eread( npc & ); void do_chop_plank( npc & ); void do_vehicle_deconstruct( npc & ); void do_vehicle_repair( npc & ); diff --git a/src/npctalk_funcs.cpp b/src/npctalk_funcs.cpp index 577e2d4306f26..ad98114f3a24b 100644 --- a/src/npctalk_funcs.cpp +++ b/src/npctalk_funcs.cpp @@ -261,6 +261,11 @@ void talk_function::do_read( npc &p ) p.do_npc_read(); } +void talk_function::do_eread( npc &p ) +{ + p.do_npc_read( true ); +} + void talk_function::dismount( npc &p ) { p.npc_dismount();