diff --git a/doc/JSON/NPCs.md b/doc/JSON/NPCs.md
index 5811802202b42..5ff06401b5fde 100644
--- a/doc/JSON/NPCs.md
+++ b/doc/JSON/NPCs.md
@@ -1391,6 +1391,7 @@ _some functions support array arguments or kwargs, denoted with square brackets
| climate_control_str_chill() | ✅ | ❌ | u, n | return amount of chill climate control that character currently has (character feels better in cold places with it), in warmth points; default 0, affected by CLIMATE_CONTROL_HEAT enchantment.
Example:
`"condition": { "math": [ "n_climate_control_str_chill() < 0" ] }`|
| calories() | ✅ | ✅ | u, n | Return amount of calories character has. If used on item, return amount of calories this item gives when consumed (not affected by enchantments or mutations). Optional kwargs:
`format`: `s`/`v` - return the value in specific format. Can be `percent` (return percent to the healthy amount of calories, `100` being the target, bmi 25, or 110000 kcal) or `raw`. If now used, `raw` is used by default.
`dont_affect_weariness`: `true`/`false` (default false) When assigning value, whether the gained/spent calories should be tracked by weariness.
Example:
`"condition": { "math": [ "u_calories() < 0" ] }`
`"condition": { "math": [ "u_calories('format': 'percent') > 0" ] }`
`"condition": { "math": [ "u_calories() = 110000" ] }`|
| get_calories_daily() | ✅ | ❌ | g | Return amount of calories character consumed before, up to 30 days, in kcal. Calorie diary is something only character has, so it can't be used with NPCs. Optional kwargs:
`day`: `d/v` - picks the date the value would be pulled from, from 0 to 30. Default 0, meaning amount of calories you consumed today.
`type`: `s/v` - picks the data that would be pulled. Possible values are: `spent` - how much calories character spent in different activities throughout the day; `gained` - how much calories character ate that day; `ingested` - how much calories character processed that day; `total` - `gained` minus `spent`. Default is `total`;
Example:
`"condition": { "math": [ "get_calories_daily() > 1000" ] }`
`{ "math": [ "foo = get_calories_daily('type':'gained', 'day':'1')" ] }`|
+| quality( `s` / `v` ) | ✅ | ❌ | u, n | Return the level of a specified item tool quality. Only usable on item talkers.
Argument is the quality ID. Returns the lowest integer value if the item lacks the specified quality.
Optional kwargs:
`strict`: `true` / `false` (default false) When true the item must be empty to have the boiling quality.
Example
`"condition: { "math": [ " u_quality('HACK') > 0 " ] }`
`{ "math": [ "_cut_quality = u_quality('CUT') " ] }`
`condition: { "math": [ " u_quality('BOIL', 'strict': true ) > 0" ] }`
#### List of Character and item aspects
These can be read or written to with `val()`.
diff --git a/src/item_location.cpp b/src/item_location.cpp
index 09f2d209a550b..30de607475680 100644
--- a/src/item_location.cpp
+++ b/src/item_location.cpp
@@ -1182,3 +1182,10 @@ bool item_location::can_reload_with( const item_location &ammo, bool now ) const
}
return reloadable->can_reload_with( *ammo, now );
}
+
+int item_location::get_quality( const std::string &quality, bool strict ) const
+{
+ const item_location tool = *this;
+ quality_id qualityid( quality );
+ return tool->get_quality_nonrecursive( qualityid, strict );
+}
diff --git a/src/item_location.h b/src/item_location.h
index 3b443303bc4d2..61492ce3cd777 100644
--- a/src/item_location.h
+++ b/src/item_location.h
@@ -163,6 +163,13 @@ class item_location
*/
bool can_reload_with( const item_location &ammo, bool now ) const;
+ /**
+ * returns the item's level of the specified quality.
+ * @param quality the name of quality to check the level of
+ * @param boiling true if the item is required to be empty to have the boiling quality
+ */
+ int get_quality( const std::string &quality, bool strict ) const;
+
private:
class impl;
diff --git a/src/math_parser_diag.cpp b/src/math_parser_diag.cpp
index 0518fd05ecd65..2b155dd15e408 100644
--- a/src/math_parser_diag.cpp
+++ b/src/math_parser_diag.cpp
@@ -1689,6 +1689,20 @@ diag_eval_dbl_f weight_eval( char scope, std::vector const & /* para
};
}
+diag_eval_dbl_f quality_eval( char scope, std::vector const ¶ms /* params */,
+ diag_kwargs const &kwargs /* kwargs */ )
+{
+ diag_value strict_val = kwargs.kwarg_or( "strict" );
+
+ return[quality_param = params[0], strict_val,
+ beta = is_beta( scope )]( const_dialogue const & d ) {
+ std::string quality = quality_param.str( d );
+ bool strict = is_true( strict_val.dbl( d ) );
+
+ return d.const_actor( beta )->get_quality( quality, strict );
+ };
+}
+
diag_eval_dbl_f volume_eval( char scope, std::vector const & /* params */,
diag_kwargs const & /* kwargs */ )
{
@@ -1872,6 +1886,7 @@ std::map const dialogue_funcs{
{ "school_level_adjustment", { "un", 1, school_level_adjustment_eval, school_level_adjustment_ass } },
{ "spellcasting_adjustment", { "u", 1, nullptr, spellcasting_adjustment_ass } },
{ "get_calories_daily", { "g", 0, get_daily_calories } },
+ { "quality", { "un", 1, quality_eval } },
{ "skill", { "un", 1, skill_eval, skill_ass } },
{ "skill_exp", { "un", 1, skill_exp_eval, skill_exp_ass } },
{ "spell_count", { "un", 0, spell_count_eval}},
diff --git a/src/talker.h b/src/talker.h
index 23a8ef6db1152..293a3c1a309c2 100644
--- a/src/talker.h
+++ b/src/talker.h
@@ -646,6 +646,9 @@ class const_talker
virtual int climate_control_str_chill() const {
return 0;
}
+ virtual int get_quality( const std::string &, bool ) const {
+ return 0;
+ }
};
class talker: virtual public const_talker
diff --git a/src/talker_item.cpp b/src/talker_item.cpp
index 0044ec6277aa3..f71e7a5848473 100644
--- a/src/talker_item.cpp
+++ b/src/talker_item.cpp
@@ -126,6 +126,11 @@ int talker_item_const::get_weight() const
return units::to_milligram( me_it_const->get_item()->weight() );
}
+int talker_item_const::get_quality( const std::string &quality, bool strict ) const
+{
+ return me_it_const->get_quality( quality, strict );
+}
+
void talker_item::set_value( const std::string &var_name, const std::string &value )
{
me_it->get_item()->set_var( var_name, value );
diff --git a/src/talker_item.h b/src/talker_item.h
index 66ac3ae7929e8..edc04dc5201c8 100644
--- a/src/talker_item.h
+++ b/src/talker_item.h
@@ -59,6 +59,7 @@ class talker_item_const: public const_talker_cloner
int encumbrance_at( bodypart_id & ) const override;
int get_volume() const override;
int get_weight() const override;
+ int get_quality( const std::string &, bool strict ) const override;
private:
const item_location *me_it_const{};