diff --git a/doc/NPCs.md b/doc/NPCs.md index 35e8067397072..6f889c2f58fbe 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -852,8 +852,8 @@ Effect | Description `give_equipment` | Allows your character to select items from the NPC's inventory and transfer them to your inventory. `npc_gets_item` | Allows your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will not accept it if they do not have space or weight to carry it, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. `npc_gets_item_to_use` | Allow your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will attempt to wield it and will not accept it if it is too heavy or is an inferior weapon to what they are currently using, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. -`u_spawn_item: `string or [variable object](#variable-object), (*optional* `count: `int or [variable object](#variable-object)), (*optional* `container: `string or [variable object](#variable-object)), (*optional* `use_item_group: `bool), (*optional* `suppress_message: `bool) | Your character gains the item or `count` copies of the item, contained in container if specified. If used in an NPC conversation the items are said to be given by the NPC. If a variable item is passed for the name an item of the type contained in it will be used. If `use_item_group` is true (defaults to false) it will instead pull an item from the item group given. If `suppress_message` is true (defaults to false) no message will be shown. If `force_equip` is true (defaults to false) characters will equip the items if they can. -`u_buy_item: `string or [variable object](#variable-object), `cost: `int or [variable object](#variable-object), (*optional* `count: `int or [variable object](#variable-object)), (*optional* `container: `string or [variable object](#variable-object)), (*optional* `true_eocs: eocs_array`), (*optional* `false_eocs: eocs_array`), (*optional* `use_item_group: `bool), (*optional* `suppress_message: `bool) | The NPC will sell your character the item or `count` copies of the item, contained in `container`, and will subtract `cost` from `op_of_u.owed`. If the `op_o_u.owed` is less than `cost`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost` is satisfied. If `use_item_group` is true (defaults to false) it will instead pull an item from the item group given. If `suppress_message` is true (defaults to false) no message will be shown +`u_spawn_item: `string or [variable object](#variable-object), (*optional* `count: `int or [variable object](#variable-object)), (*optional* `container: `string or [variable object](#variable-object)), (*optional* `use_item_group: `bool), (*optional* `suppress_message: `bool), (*optional* `flags: `array of string or [variable object](#variable-object)) | Your character gains the item or `count` copies of the item, contained in container if specified. If used in an NPC conversation the items are said to be given by the NPC. If a variable item is passed for the name an item of the type contained in it will be used. If `use_item_group` is true (defaults to false) it will instead pull an item from the item group given. If `suppress_message` is true (defaults to false) no message will be shown. If `force_equip` is true (defaults to false) characters will equip the items if they can. The item will have all the flags from the array `flags`. +`u_buy_item: `string or [variable object](#variable-object), `cost: `int or [variable object](#variable-object), (*optional* `count: `int or [variable object](#variable-object)), (*optional* `container: `string or [variable object](#variable-object)), (*optional* `true_eocs: eocs_array`), (*optional* `false_eocs: eocs_array`), (*optional* `use_item_group: `bool), (*optional* `suppress_message: `bool), (*optional* `flags: `array of string or [variable object](#variable-object)) | The NPC will sell your character the item or `count` copies of the item, contained in `container`, and will subtract `cost` from `op_of_u.owed`. If the `op_o_u.owed` is less than `cost`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost` is satisfied. If `use_item_group` is true (defaults to false) it will instead pull an item from the item group given. If `suppress_message` is true (defaults to false) no message will be shown. The item will have all the flags from the array `flags`. `u_sell_item: `string or [variable object](#variable-object), (*optional* `cost: `int or [variable object](#variable-object)), (*optional* `count: `string or [variable object](#variable-object)), (*optional* `true_eocs: eocs_array`), (*optional* `false_eocs: eocs_array`) | Your character will give the NPC the item or `count` copies of the item, and will add `cost` to the NPC's `op_of_u.owed` if specified.
If cost isn't present, the your character gives the NPC the item at no charge.
This effect will fail if you do not have at least `count` copies of the item, so it should be checked with. If the item is sold, then all of the effect_on_conditions in `true_eocs` are run, otherwise all the effect_on_conditions in `false_eocs` are run. `u_bulk_trade_accept, npc_bulk_trade_accept, u_bulk_trade_accept, npc_bulk_trade_accept: `int or [variable object](#variable-object) | Only valid after a `repeat_response`. The player trades all instances of the item from the `repeat_response` with the NPC. For `u_bulk_trade_accept`, the player loses the items from their inventory and gains the same value of the NPC's faction currency; for `npc_bulk_trade_accept`, the player gains the items from the NPC's inventory and loses the same value of the NPC's faction currency. If there is remaining value, or the NPC doesn't have a faction currency, the remainder goes into the NPC's `op_of_u.owed`. If `quantity` is specified only that many items/charges will be moved. `u_bulk_donate, npc_bulk_donate` or `u_bulk_donate, npc_bulk_donate: `int or [variable object](#variable-object) | Only valid after a `repeat_response`. The player or NPC transfers all instances of the item from the `repeat_response`. For `u_bulk_donate`, the player loses the items from their inventory and the NPC gains them; for `npc_bulk_donate`, the player gains the items from the NPC's inventory and the NPC loses them. If a value is specified only that many items/charges will be moved. diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 4ebcb77085be5..18ccb930ab882 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -2956,7 +2956,9 @@ static void map_add_item( item &it, tripoint_abs_ms target_pos ) } static void receive_item( itype_id &item_name, int count, std::string_view container_name, - const dialogue &d, bool use_item_group, bool suppress_message, bool add_talker = true, + const dialogue &d, bool use_item_group, bool suppress_message, + const std::vector &flags, + bool add_talker = true, const tripoint_abs_ms &p = tripoint_abs_ms(), bool force_equip = false ) { item new_item; @@ -2965,6 +2967,10 @@ static void receive_item( itype_id &item_name, int count, std::string_view conta } else { new_item = item( item_name, calendar::turn ); } + for( const std::string &flag : flags ) { + new_item.set_flag( flag_id( flag ) ); + } + if( container_name.empty() ) { if( new_item.count_by_charges() ) { new_item.charges = count; @@ -3040,12 +3046,21 @@ void talk_effect_fun_t::set_spawn_item( const JsonObject &jo, std::string_view m loc_var = read_var_info( jo.get_object( "loc" ) ); } bool force_equip = jo.get_bool( "force_equip", false ); + + std::vector flags; + for( JsonValue jv : jo.get_array( "flags" ) ) { + flags.emplace_back( get_str_or_var( jv, "flags" ) ); + } function = [item_name, count, container_name, use_item_group, suppress_message, - add_talker, loc_var, force_equip]( dialogue & d ) { + add_talker, loc_var, force_equip, flags]( dialogue & d ) { itype_id iname = itype_id( item_name.evaluate( d ) ); const tripoint_abs_ms target_location = get_tripoint_from_var( loc_var, d ); + std::vector flags_str( flags.size() ); + for( const str_or_var &flat_sov : flags ) { + flags_str.emplace_back( flat_sov.evaluate( d ) ); + } receive_item( iname, count.evaluate( d ), container_name.evaluate( d ), d, use_item_group, - suppress_message, add_talker, target_location, force_equip ); + suppress_message, flags_str, add_talker, target_location, force_equip ); }; dialogue d( get_talker_for( get_avatar() ), nullptr, {} ); likely_rewards.emplace_back( static_cast( count.evaluate( d ) ), @@ -3072,17 +3087,25 @@ void talk_effect_fun_t::set_u_buy_item( const JsonObject &jo, std::string_view m container_name.str_val = ""; } + std::vector flags; + for( JsonValue jv : jo.get_array( "flags" ) ) { + flags.emplace_back( get_str_or_var( jv, "flags" ) ); + } str_or_var item_name = get_str_or_var( jo.get_member( member ), member, true ); function = [item_name, cost, count, container_name, true_eocs, false_eocs, - use_item_group, suppress_message]( dialogue & d ) { + use_item_group, suppress_message, flags]( dialogue & d ) { if( !d.actor( true )->buy_from( cost.evaluate( d ) ) ) { popup( _( "You can't afford it!" ) ); run_eoc_vector( false_eocs, d ); return; } itype_id iname = itype_id( item_name.evaluate( d ) ); + std::vector flags_str( flags.size() ); + for( const str_or_var &flat_sov : flags ) { + flags_str.emplace_back( flat_sov.evaluate( d ) ); + } receive_item( iname, count.evaluate( d ), - container_name.evaluate( d ), d, use_item_group, suppress_message ); + container_name.evaluate( d ), d, use_item_group, suppress_message, flags_str ); run_eoc_vector( true_eocs, d ); }; }