Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jsonify water boiling and other temperature effects on the item #78562

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions data/json/items/comestibles/drink.json
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,7 @@
"container": "bottle_plastic",
"sealed": false,
"delete": { "flags": [ "DECAYS_IN_AIR" ] },
"temperature_effects": [ { "temperature_above": "373 K", "transform": "water_clean", "remove_poison": true } ],
"contamination": [ { "disease": "highly_contaminated_food", "probability": 0.1 }, { "disease": "bad_food", "probability": 1 } ]
},
{
Expand All @@ -1508,6 +1509,7 @@
"copy-from": "water",
"name": { "str_sp": "murky water" },
"description": "Water, the stuff of life. This water looks like it has quite a bit of life in it in fact, and not the good kind. You should filter and sterilize it if you want to drink it.",
"temperature_effects": [ ],
"quench": 30,
"parasites": 5,
"contamination": [ { "disease": "highly_contaminated_food", "probability": 100 } ]
Expand Down
8 changes: 8 additions & 0 deletions doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3502,6 +3502,14 @@ Weakpoints only match if they share the same id, so it's important to define the
"recipe": "paste_nut_mill_10_1" // Reference to the recipe that performs the task. The syntax is <product name>_mill_<source amount>_<product amount>. The recipe is then defined as a normal recipe for the source with the product as its result and an id_suffix of "mill_X_Y".
// See data/json/recipes/food/milling.json for such recipes. Can also use "milling": { "into": "null", "recipe": "" } to override milling from a copied base item.
},
"temperature_effects": [{ // Optional. Specifies certain effects happening to the item when it reaches certain internal temperature thresholds.
// Holds an array of objects
"temperature_above": "373 K", // Temperature needs to be at least this high for the effect to happen.
"temperature_below": "0 K", // Temperature needs to be at least this low for the effect to happen.
// Exactly one of temperature_above and temperature_below must be set.
"transform": "water_clean", // The item id that we transform into upon reaching the temperature. Boiling water gives clean water, as an example.
"remove_poison": true // Whether we should remove poison from comestible item. Defaults to false.
}],
"explode_in_fire": true, // Should the item explode if set on fire
"nanofab_template_group": "nanofab_recipes", // This item is nanofabricator recipe, and point to itemgroup with items, that it could possibly contain; require nanofab_template_group
"template_requirements": "nanofabricator", // `requirement`, that needed to craft any of this templates; used as "one full requirememt per 250 ml of item's volume" - item with volume 750 ml would require three times of `requirement`, item of 2L - eight times of `requirement`
Expand Down
3 changes: 0 additions & 3 deletions src/game_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,6 @@ constexpr units::temperature freezer = units::from_celsius( -5 ); // -5 Celsius

// Temperature in which water freezes.
constexpr units::temperature freezing = units::from_celsius( 0 ); // 0 Celsius

// Temperature in which water boils.
constexpr units::temperature boiling = units::from_celsius( 100 ); // 100 Celsius
} // namespace temperatures

// Slowest speed at which a gun can be aimed.
Expand Down
21 changes: 16 additions & 5 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,6 @@ static const itype_id itype_rad_badge( "rad_badge" );
static const itype_id itype_rm13_armor( "rm13_armor" );
static const itype_id itype_stock_none( "stock_none" );
static const itype_id itype_tuned_mechanism( "tuned_mechanism" );
static const itype_id itype_water( "water" );
static const itype_id itype_water_clean( "water_clean" );
static const itype_id itype_waterproof_gunmod( "waterproof_gunmod" );

static const json_character_flag json_flag_CANNIBAL( "CANNIBAL" );
Expand Down Expand Up @@ -13222,9 +13220,22 @@ void item::set_temp_flags( units::temperature new_temperature, float freeze_perc
set_flag( flag_COLD );
}

// Convert water into clean water if it starts boiling
if( typeId() == itype_water && new_temperature > temperatures::boiling ) {
convert( itype_water_clean ).poison = 0;
// Execute temperature effects if a new threshold is reached.
// Water turning into clean water when boiling is a canonical example.
const islot_temperature_effects *te_data = type->temperature_effects_data.get();
if( te_data != nullptr ) {
for( const temperature_effect &eff : te_data->effects ) {
if( ( eff.temperature_above.has_value() && eff.temperature_above.value() <= new_temperature ) ||
( eff.temperature_below.has_value() && eff.temperature_below.value() >= new_temperature )
) {
if( eff.transform_into ) {
convert( eff.transform_into );
}
if( eff.remove_poison ) {
RenechCDDA marked this conversation as resolved.
Show resolved Hide resolved
poison = 0;
}
}
}
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,20 @@
}
}
}

// temperature_effects consistency
if( obj.temperature_effects_data ) {
for( const temperature_effect &eff : obj.temperature_effects_data->effects ) {
if( eff.temperature_above.has_value() == eff.temperature_below.has_value() ) {
debugmsg( "Exactly one of temperature_above and temperature_above must be set in %s temperature_effects",
obj.id.str() );
}
if( eff.transform_into.is_null() || !eff.transform_into.is_valid() ) {
debugmsg( "'%s' is not a valid item id (in %s temperature_effects)",
eff.transform_into.c_str(), obj.id.str() );
}
}
}
}

void Item_factory::finalize_post_armor( itype &obj )
Expand Down Expand Up @@ -2667,6 +2681,29 @@
load( jo );
}

void temperature_effect::load( const JsonObject &jo )
{
optional( jo, was_loaded, "temperature_above", temperature_above );
optional( jo, was_loaded, "temperature_below", temperature_below );
optional( jo, was_loaded, "transform", transform_into );
optional( jo, was_loaded, "remove_poison", remove_poison );
}

static void load_temperature_effects(
const JsonObject &jo, const std::string_view member,
cata::value_ptr<islot_temperature_effects> &slotptr, const std::string &src )

Check failure on line 2694 in src/item_factory.cpp

View workflow job for this annotation

GitHub Actions / Basic Build and Test (Clang 10, Ubuntu, Curses)

unused parameter 'src' [-Werror,-Wunused-parameter]

Check failure on line 2694 in src/item_factory.cpp

View workflow job for this annotation

GitHub Actions / build (src)

Parameter 'src' of 'load_temperature_effects' can be std::string_view. [cata-use-string_view,-warnings-as-errors]

Check failure on line 2694 in src/item_factory.cpp

View workflow job for this annotation

GitHub Actions / build (src)

unused parameter 'src' [clang-diagnostic-unused-parameter,-warnings-as-errors]

Check failure on line 2694 in src/item_factory.cpp

View workflow job for this annotation

GitHub Actions / build (src)

parameter 'src' is unused [misc-unused-parameters,-warnings-as-errors]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clang error here. Looks like you pass along src but forgot to check if two definitions come from the same source?

{
if( !jo.has_member( member ) ) {
return;
}
slotptr = cata::make_value<islot_temperature_effects>();
for( const JsonObject &tejo : jo.get_array( member ) ) {

Check failure on line 2700 in src/item_factory.cpp

View workflow job for this annotation

GitHub Actions / build (src)

the type of the loop variable 'tejo' is different from the one returned by the iterator and generates an implicit conversion; you can either change the type to the matching one ('const JsonValue &' but 'const auto&' is always a valid option) or remove the reference to make it explicit that you are creating a new value [performance-implicit-conversion-in-loop,-warnings-as-errors]
temperature_effect eff;
eff.load( tejo );
slotptr->effects.push_back( eff );
}
}

static void load_memory_card_data( memory_card_info &mcd, const JsonObject &jo )
{
mcd.data_chance = jo.get_float( "data_chance", 1.0f );
Expand Down Expand Up @@ -4494,6 +4531,8 @@
assign( jo, "compostable", def.compostable, src == "dda" );
load_slot_optional( def.relic_data, jo, "relic_data", src );
assign( jo, "milling", def.milling_data, src == "dda" );
load_temperature_effects( jo, "temperature_effects", def.temperature_effects_data, src );


// optional gunmod slot may also specify mod data
if( jo.has_member( "gunmod_data" ) ) {
Expand Down
32 changes: 24 additions & 8 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -1204,6 +1204,21 @@ class islot_milling
void deserialize( const JsonObject &jo );
};

struct temperature_effect {
std::optional<units::temperature> temperature_above;
std::optional<units::temperature> temperature_below;

itype_id transform_into;
bool remove_poison = false;

bool was_loaded = false;
void load( const JsonObject &jo );
};

struct islot_temperature_effects {
std::vector<temperature_effect> effects;
};

struct memory_card_info {
float data_chance;
itype_id on_read_convert_to;
Expand All @@ -1228,6 +1243,14 @@ struct itype {

using FlagsSetType = std::set<flag_id>;

protected:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you made a comment for this (quoted below), could you expand on what you meant? I've never had any trouble debugging in VS regardless of where a member is placed inside a struct. Do you mean scrolling through the raw data shown when you hover a variable, while the program is breakpointed?

(P.s.: driveby change - i've moved itype::name field to be the first field in the struct to make debugging in VS less agonizing. No behavior change, no save compat issues or anything of that sort)

// private because it should only be accessed through itype::nname!
// nname() is used for display purposes
translation name = no_translation( "none" );

public:
translation description; // Flavor text

/**
* Slots for various item type properties. Each slot may contain a valid pointer or null, check
* this before using it.
Expand All @@ -1252,6 +1275,7 @@ struct itype {
cata::value_ptr<islot_seed> seed;
cata::value_ptr<relic> relic_data;
cata::value_ptr<islot_milling> milling_data;
cata::value_ptr<islot_temperature_effects> temperature_effects_data;
/*@}*/

/** Action to take BEFORE the item is placed on map. If it returns non-zero, item won't be placed. */
Expand Down Expand Up @@ -1390,14 +1414,6 @@ struct itype {
// How should the item explode
explosion_data explosion;

translation description; // Flavor text

protected:
// private because is should only be accessed through itype::nname!
// nname() is used for display purposes
translation name = no_translation( "none" );

public:
// Total of item's material portions (materials->second)
int mat_portion_total = 0;

Expand Down
Loading