diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index 298a8177be462..5392cab0c32d1 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -1516,10 +1516,10 @@ Emitters randomly place [fields](#field-types) around their positions - every tu | Identifier | Description |--- |--- | `id` | Unique ID -| `field` | Field type emitted -| `intensity` | Initial intensity of the spawned fields (spawning multiple fields will still cause their intensity to increase). Default 1. -| `chance` | **Percent** chance of the emitter emitting, values above 100 will increase the quantity of fields placed via `roll_remainder` (ex: `chance: 150` will place one field 50% of the time and two fields the other 50% ). Failing the roll will disable the whole emission for the tick, not rolled for every `qty`! Default 100. -| `qty` | Number of fields placed. Fields are placed using the field propagation rules, allowing fields to spread. Default 1. +| `field` | Field type emitted. This can be a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info. +| `intensity` | Initial intensity of the spawned fields (spawning multiple fields will still cause their intensity to increase). Default 1. This can be a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info. +| `chance` | **Percent** chance of the emitter emitting, values above 100 will increase the quantity of fields placed via `roll_remainder` (ex: `chance: 150` will place one field 50% of the time and two fields the other 50% ). Failing the roll will disable the whole emission for the tick, not rolled for every `qty`! Default 100. This can be a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info. +| `qty` | Number of fields placed. Fields are placed using the field propagation rules, allowing fields to spread. Default 1. This can be a Variable Object, see the [doc](EFFECT_ON_CONDITION.md) for more info. ```JSON { diff --git a/src/emit.cpp b/src/emit.cpp index de611503beff6..3a3ad826183ea 100644 --- a/src/emit.cpp +++ b/src/emit.cpp @@ -5,33 +5,33 @@ #include #include "debug.h" + +#include "condition.h" #include "flexbuffer_json-inl.h" #include "flexbuffer_json.h" +#include "json.h" static std::map emits_all; /** @relates string_id */ template<> -bool string_id::is_valid() const +const emit &string_id::obj() const { const auto found = emits_all.find( *this ); if( found == emits_all.end() ) { - return false; + debugmsg( "Tried to get invalid emission data: %s", c_str() ); + static const emit null_emit{}; + return null_emit; } - return !found->second.field().id().is_null(); + return found->second; } /** @relates string_id */ template<> -const emit &string_id::obj() const +bool string_id::is_valid() const { const auto found = emits_all.find( *this ); - if( found == emits_all.end() ) { - debugmsg( "Tried to get invalid emission data: %s", c_str() ); - static const emit null_emit{}; - return null_emit; - } - return found->second; + return found != emits_all.end(); } emit::emit() : id_( emit_id::NULL_ID() ) {} @@ -46,11 +46,10 @@ void emit::load_emit( const JsonObject &jo ) emit et; et.id_ = emit_id( jo.get_string( "id" ) ); - et.field_name = jo.get_string( "field" ); - - jo.read( "intensity", et.intensity_ ); - jo.read( "qty", et.qty_ ); - jo.read( "chance", et.chance_ ); + et.field_ = get_str_or_var( jo.get_member( "field" ), "field" ); + et.intensity_ = get_dbl_or_var( jo, "intensity", false, 1.0 ); + et.qty_ = get_dbl_or_var( jo, "qty", false, 1.0 ); + et.chance_ = get_dbl_or_var( jo, "chance", false, 100.0 ); emits_all[ et.id_ ] = et; } @@ -62,24 +61,8 @@ const std::map &emit::all() void emit::finalize() { - for( auto &e : emits_all ) { - e.second.field_ = field_type_id( e.second.field_name ); - const int max_intensity = e.second.field_.obj().get_max_intensity(); - if( e.second.intensity_ > max_intensity || e.second.intensity_ < 1 ) { - debugmsg( "emission intensity of %s out of range (%d of max %d)", e.second.id_.c_str(), - e.second.intensity_, max_intensity ); - e.second.intensity_ = max_intensity; - } - if( e.second.qty_ <= 0 ) { - debugmsg( "emission qty of %s out of range", e.second.id_.c_str() ); - } - if( e.second.chance_ > 100 || e.second.chance_ <= 0 ) { - debugmsg( "emission chance of %s out of range (%d of min 1 max 100)", e.second.id_.c_str(), - e.second.chance_ ); - e.second.chance_ = std::max( std::min( e.second.chance_, 100 ), 1 ); - } - } } + void emit::check_consistency() { } diff --git a/src/emit.h b/src/emit.h index 2538ca39793b2..8d5510bca3222 100644 --- a/src/emit.h +++ b/src/emit.h @@ -7,6 +7,7 @@ #include "field_type.h" #include "type_id.h" +#include class JsonObject; @@ -26,23 +27,23 @@ class emit bool is_valid() const; /** Type of field to emit @see emit::is_valid */ - field_type_id field() const { - return field_; + field_type_id field( dialogue &d ) const { + return field_type_id( field_.evaluate( d ) ); } /** Intensity of output fields, range [1..maximum_intensity] */ - int intensity() const { - return intensity_; + int intensity( dialogue &d ) const { + return intensity_.evaluate( d ); } /** Units of field to generate per turn subject to @ref chance */ - int qty() const { - return qty_; + int qty( dialogue &d ) const { + return qty_.evaluate( d ); } /** Chance to emit each turn, range [1..100] */ - int chance() const { - return chance_; + int chance( dialogue &d ) const { + return chance_.evaluate( d ); } /** Load emission data from JSON definition */ @@ -62,13 +63,10 @@ class emit private: emit_id id_; - field_type_id field_ = fd_null.id_or( INVALID_FIELD_TYPE_ID ); - int intensity_ = 1; - int qty_ = 1; - int chance_ = 100; - - /** used during JSON loading only */ - std::string field_name; + str_or_var field_; + dbl_or_var intensity_; + dbl_or_var qty_; + dbl_or_var chance_; }; #endif // CATA_SRC_EMIT_H diff --git a/src/map_field.cpp b/src/map_field.cpp index 559cd97124436..fdce124401514 100644 --- a/src/map_field.cpp +++ b/src/map_field.cpp @@ -17,6 +17,7 @@ #include #include +#include "avatar.h" #include "bodypart.h" #include "calendar.h" #include "cata_utility.h" @@ -2103,10 +2104,11 @@ void map::emit_field( const tripoint &pos, const emit_id &src, float mul ) return; } - const float chance = src->chance() * mul; - if( src.is_valid() && x_in_y( chance, 100 ) ) { - const int qty = chance > 100.0f ? roll_remainder( src->qty() * chance / 100.0f ) : src->qty(); - propagate_field( pos, src->field(), qty, src->intensity() ); + dialogue d( get_talker_for( get_avatar() ), nullptr ); + const float chance = src->chance( d ) * mul; + if( x_in_y( chance, 100 ) ) { + const int qty = chance > 100.0f ? roll_remainder( src->qty( d ) * chance / 100.0f ) : src->qty( d ); + propagate_field( pos, src->field( d ), qty, src->intensity( d ) ); } }