diff --git a/src/item.cpp b/src/item.cpp index 968c7a38e8b03..9a850e0ca7783 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -4685,6 +4685,9 @@ units::length item::length() const if( made_of( LIQUID ) || is_soft() ) { return 0_mm; } + if( is_corpse() ) { + return units::default_length_from_volume( corpse->volume ); + } return type->longest_side; } diff --git a/src/item_factory.cpp b/src/item_factory.cpp index a84b7fc2cbc30..972ac81ac9823 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -450,7 +450,9 @@ void Item_factory::finalize_pre( itype &obj ) } if( obj.longest_side == -1_mm ) { - obj.longest_side = units::cube_to_volume( obj.volume ); + units::volume effective_volume = obj.count_by_charges() ? + ( obj.volume / obj.stack_size ) : obj.volume; + obj.longest_side = units::default_length_from_volume( effective_volume ); } } diff --git a/src/item_pocket.cpp b/src/item_pocket.cpp index 678cb584d71d0..001632c507946 100644 --- a/src/item_pocket.cpp +++ b/src/item_pocket.cpp @@ -53,7 +53,7 @@ void pocket_data::load( const JsonObject &jo ) mandatory( jo, was_loaded, "max_contains_volume", volume_capacity, volume_reader() ); mandatory( jo, was_loaded, "max_contains_weight", max_contains_weight, mass_reader() ); optional( jo, was_loaded, "max_item_length", max_item_length, - units::cube_to_volume( volume_capacity ) * M_SQRT2 ); + units::default_length_from_volume( volume_capacity ) * M_SQRT2 ); } optional( jo, was_loaded, "spoil_multiplier", spoil_multiplier, 1.0f ); optional( jo, was_loaded, "weight_multiplier", weight_multiplier, 1.0f ); diff --git a/src/units.h b/src/units.h index 5a105d8c28b14..6634348d224a9 100644 --- a/src/units.h +++ b/src/units.h @@ -540,7 +540,7 @@ inline constexpr value_type to_kilometer( const quantity -inline constexpr quantity cube_to_volume( +inline constexpr quantity default_length_from_volume( const quantity &v ) { return units::from_centimeter( diff --git a/tests/item_test.cpp b/tests/item_test.cpp index 3707b5fe01fd0..6eb133a788652 100644 --- a/tests/item_test.cpp +++ b/tests/item_test.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,9 @@ #include "catch/catch.hpp" #include "enums.h" #include "item.h" +#include "item_factory.h" #include "itype.h" +#include "monstergenerator.h" #include "ret_val.h" #include "units.h" #include "value_ptr.h" @@ -157,3 +160,46 @@ TEST_CASE( "stacking_over_time", "[item]" ) } } } + +static void assert_minimum_length_to_volume_ratio( const item &target ) +{ + if( target.type->get_id() == "null" ) { + return; + } + CAPTURE( target.type->get_id() ); + CAPTURE( target.volume() ); + CAPTURE( target.base_volume() ); + CAPTURE( target.type->volume ); + if( target.made_of( LIQUID ) || target.is_soft() ) { + CHECK( target.length() == 0_mm ); + return; + } + if( target.volume() == 0_ml ) { + CHECK( target.length() == -1_mm ); + return; + } + if( target.volume() == 1_ml ) { + CHECK( target.length() >= 0_mm ); + return; + } + // Minimum possible length is if the item is a sphere. + const float minimal_diameter = std::cbrt( ( 3.0 * units::to_milliliter( target.base_volume() ) ) / + ( 4.0 * M_PI ) ); + CHECK( units::to_millimeter( target.length() ) >= minimal_diameter * 10.0 ); +} + +TEST_CASE( "item length sanity check", "[item]" ) +{ + for( const itype *type : item_controller->all() ) { + const item sample( type, 0, item::solitary_tag {} ); + assert_minimum_length_to_volume_ratio( sample ); + } +} + +TEST_CASE( "corpse length sanity check", "[item]" ) +{ + for( const mtype &type : MonsterGenerator::generator().get_all_mtypes() ) { + const item sample = item::make_corpse( type.id ); + assert_minimum_length_to_volume_ratio( sample ); + } +}