diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 5cbac8af44dbe..81a10683c7e15 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -4508,6 +4508,7 @@ The contents of `use_action` fields can either be a string indicating a built-in "use_action": { "type": "transform", // The type of method, in this case one that transforms the item "target": "gasoline_lantern_on", // The item to transform to + "target_group": "twisted_geometry", // If used, target is a random item from itemgroup "variant_type": "condom_plain", // (optional) Defaults to ``. Specific variant type to set for the transformed item. Special string `` will pick a random variant from all available variants, based on the variant's defined weight "active": true, // Whether the item is active once transformed "ammo_scale": 0, // For use when an item automatically transforms into another when its ammo drops to 0, or to allow guns to transform with 0 ammo diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 8b8ff6beaf657..1f1571984e8a6 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -171,6 +171,11 @@ std::unique_ptr iuse_transform::clone() const void iuse_transform::load( const JsonObject &obj, const std::string & ) { obj.read( "target", target, true ); + obj.read( "target_group", target_group, true ); + + if( !target.is_empty() && !target_group.is_empty() ) { + obj.throw_error_at( "target_group", "Cannot use both target and target_group at once" ); + } obj.read( "msg", msg_transform ); obj.read( "variant_type", variant_type ); @@ -272,7 +277,8 @@ std::optional iuse_transform::use( Character *p, item &it, const tripoint & } } - if( it.count_by_charges() != target->count_by_charges() && it.count() > 1 ) { + if( target_group.is_empty() && it.count_by_charges() != target->count_by_charges() && + it.count() > 1 ) { item take_one = it.split( 1 ); do_transform( p, take_one, variant_type ); p->i_add_or_drop( take_one ); @@ -293,8 +299,12 @@ void iuse_transform::do_transform( Character *p, item &it, const std::string &va // defined here to allow making a new item assigned to the pointer item obj_it; if( container.is_empty() ) { - obj = &it.convert( target, p ); - obj->set_itype_variant( variant_type ); + if( !target_group.is_empty() ) { + obj = &it.convert( item_group::item_from( target_group ).typeId(), p ); + } else { + obj = &it.convert( target, p ); + obj->set_itype_variant( variant_type ); + } if( ammo_qty >= 0 || !random_ammo_qty.empty() ) { int qty; if( !random_ammo_qty.empty() ) { @@ -320,7 +330,9 @@ void iuse_transform::do_transform( Character *p, item &it, const std::string &va obj->set_itype_variant( variant_type ); int count = std::max( ammo_qty, 1 ); item cont; - if( target->count_by_charges() ) { + if( !target_group.is_empty() ) { + cont = item( item_group::item_from( target_group ).typeId(), calendar::turn ); + } else if( target->count_by_charges() ) { cont = item( target, calendar::turn, count ); count = 1; } else { @@ -423,7 +435,7 @@ std::string iuse_transform::get_name() const void iuse_transform::finalize( const itype_id & ) { - if( !item::type_is_defined( target ) ) { + if( !item::type_is_defined( target ) && target_group.is_empty() ) { debugmsg( "Invalid transform target: %s", target.c_str() ); } @@ -439,6 +451,11 @@ void iuse_transform::finalize( const itype_id & ) void iuse_transform::info( const item &it, std::vector &dump ) const { + + if( !target_group.is_empty() ) { + dump.emplace_back( "TOOL", _( "Can transform into one of several items" ) ); + return; + } int amount = std::max( ammo_qty, 1 ); item dummy( target, calendar::turn, target->count_by_charges() ? amount : 1 ); dummy.set_itype_variant( variant_type ); diff --git a/src/iuse_actor.h b/src/iuse_actor.h index c42b1ba9b33ce..b68b227a3beb0 100644 --- a/src/iuse_actor.h +++ b/src/iuse_actor.h @@ -53,6 +53,9 @@ class iuse_transform : public iuse_actor /** type of the resulting item */ itype_id target; + /** or one of items from itemgroup */ + item_group_id target_group; + /** if set transform item to container and place new item (of type @ref target) inside */ itype_id container;