diff --git a/data/json/monsters/fungus.json b/data/json/monsters/fungus.json index d398ac550bc0b..7159a2eb35361 100644 --- a/data/json/monsters/fungus.json +++ b/data/json/monsters/fungus.json @@ -363,7 +363,7 @@ "vision_day": 5, "vision_night": 5, "harvest": "exempt", - "emit_fields": [ "emit_fungal_leak" ], + "emit_fields": [ { "emit_id": "emit_fungal_leak", "delay": "1 s" } ], "special_attacks": [ [ "SUICIDE", 20 ], [ "scratch", 15 ] ], "death_drops": "default_zombie_items", "death_function": [ "FUNGALBURST" ], @@ -397,7 +397,7 @@ "vision_day": 5, "vision_night": 3, "harvest": "zombie", - "emit_fields": [ "emit_fungal_haze_plume" ], + "emit_fields": [ { "emit_id": "emit_fungal_haze_plume", "delay": "1 s" } ], "special_attacks": [ { "type": "bite", "cooldown": 5 }, [ "scratch", 15 ] ], "death_function": [ "FUNGUS" ], "flags": [ "SEES", "STUMBLES", "WARM", "BASHES", "GROUP_BASH", "POISON", "HARDTOSHOOT", "NO_BREATHE", "PUSH_MON", "FILTHY" ] diff --git a/data/json/monsters/nether.json b/data/json/monsters/nether.json index 0cfb6a8c256e2..66e84b39199c6 100644 --- a/data/json/monsters/nether.json +++ b/data/json/monsters/nether.json @@ -483,7 +483,7 @@ "vision_night": 50, "harvest": "exempt", "special_attacks": [ [ "TINDALOS_TELEPORT", 5 ] ], - "emit_fields": [ "emit_tindalos_gas_leak" ], + "emit_fields": [ { "emit_id": "emit_tindalos_gas_leak", "delay": "1 s" } ], "path_settings": { "max_dist": 10 }, "death_function": [ "MELT" ], "flags": [ @@ -526,7 +526,7 @@ "vision_night": 50, "harvest": "exempt", "special_attacks": [ [ "TINDALOS_TELEPORT", 5 ], [ "DISAPPEAR", 25 ] ], - "emit_fields": [ "emit_tindalos_gas_leak" ], + "emit_fields": [ { "emit_id": "emit_tindalos_gas_leak", "delay": "1 s" } ], "path_settings": { "max_dist": 10 }, "death_function": [ "MELT" ], "flags": [ diff --git a/data/json/monsters/zed_electric.json b/data/json/monsters/zed_electric.json index d18d60ce96ae8..55894aad0f20e 100644 --- a/data/json/monsters/zed_electric.json +++ b/data/json/monsters/zed_electric.json @@ -120,7 +120,7 @@ "vision_night": 3, "luminance": 16, "harvest": "CBM_SUBS", - "emit_fields": [ "emit_shock_cloud" ], + "emit_fields": [ { "emit_id": "emit_shock_cloud", "delay": "1 s" } ], "special_when_hit": [ "ZAPBACK", 75 ], "death_drops": "default_zombie_death_drops", "death_function": [ "NORMAL" ], diff --git a/data/json/monsters/zed_explosive.json b/data/json/monsters/zed_explosive.json index 11750b3a20aa4..f77a004ea5bd5 100644 --- a/data/json/monsters/zed_explosive.json +++ b/data/json/monsters/zed_explosive.json @@ -157,7 +157,7 @@ "melee_cut": 0, "vision_night": 3, "harvest": "exempt", - "emit_fields": [ "emit_toxic_leak" ], + "emit_fields": [ { "emit_id": "emit_toxic_leak", "delay": "1 s" } ], "special_attacks": [ [ "SUICIDE", 20 ], [ "scratch", 15 ] ], "death_drops": "default_zombie_items", "death_function": [ "GAS" ], diff --git a/data/json/monsters/zed_misc.json b/data/json/monsters/zed_misc.json index 67a8f5493cc88..25de114cd86bb 100644 --- a/data/json/monsters/zed_misc.json +++ b/data/json/monsters/zed_misc.json @@ -1017,7 +1017,7 @@ "vision_day": 50, "vision_night": 3, "harvest": "exempt", - "emit_fields": [ "emit_smoke_stream" ], + "emit_fields": [ { "emit_id": "emit_smoke_stream", "delay": "1 s" } ], "special_attacks": [ { "type": "bite", "cooldown": 5 }, [ "scratch", 15 ] ], "death_function": [ "SMOKEBURST" ], "flags": [ diff --git a/data/mods/CrazyCataclysm/crazy_monsters.json b/data/mods/CrazyCataclysm/crazy_monsters.json index f3d87a6d0a7d1..455fa6fd3647e 100644 --- a/data/mods/CrazyCataclysm/crazy_monsters.json +++ b/data/mods/CrazyCataclysm/crazy_monsters.json @@ -98,7 +98,7 @@ "armor_cut": 4, "vision_day": 30, "vision_night": 10, - "emit_fields": [ "emit_smoke_stream" ], + "emit_fields": [ { "emit_id": "emit_smoke_stream", "delay": "1 s" } ], "special_attacks": [ { "type": "bite", "cooldown": 5 } ], "anger_triggers": [ "HURT", "PLAYER_CLOSE" ], "placate_triggers": [ "MEAT" ], diff --git a/data/mods/Magiclysm/monsters/dragon.json b/data/mods/Magiclysm/monsters/dragon.json index 491d65f515bef..351bcde817762 100644 --- a/data/mods/Magiclysm/monsters/dragon.json +++ b/data/mods/Magiclysm/monsters/dragon.json @@ -155,7 +155,7 @@ "//": "Large means powerful, but it does not mean fast.", "speed": 100, "delete": { "flags": [ "PATH_AVOID_DANGER_2" ] }, - "emit_fields": [ "emit_dragon_adult_fright" ], + "emit_fields": [ { "emit_id": "emit_dragon_adult_fright", "delay": "1 s" } ], "special_attacks": [ { "type": "bite", "cooldown": 10 }, [ "scratch", 3 ], diff --git a/data/mods/Modular_Turrets/monster_override.json b/data/mods/Modular_Turrets/monster_override.json index 229fe875507a2..96658ff66b73a 100644 --- a/data/mods/Modular_Turrets/monster_override.json +++ b/data/mods/Modular_Turrets/monster_override.json @@ -170,7 +170,7 @@ "copy-from": "mon_defbot_base", "name": "riotcontrol robot", "description": "An automated defense robot still active due to its internal power source. This one is equipped with an electric prod, tear gas sprayer, and integrated 40mm beanbag launcher.", - "emit_fields": [ "emit_tear_gas_pulse" ], + "emit_fields": [ { "emit_id": "emit_tear_gas_pulse", "delay": "1 s" } ], "melee_damage": [ { "damage_type": "electric", "amount": 6 } ], "starting_ammo": { "40x46mm_m1006": 100 }, "special_attacks": [ diff --git a/data/mods/My_Sweet_Cataclysm/sweet_monsters.json b/data/mods/My_Sweet_Cataclysm/sweet_monsters.json index f4e0d87c30632..b1e66b30d73e8 100644 --- a/data/mods/My_Sweet_Cataclysm/sweet_monsters.json +++ b/data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -369,7 +369,7 @@ "vision_day": 5, "vision_night": 5, "harvest": "gum_spider", - "emit_fields": [ "emit_gum_web" ], + "emit_fields": [ { "emit_id": "emit_gum_web", "delay": "30 m" } ], "death_function": [ "NORMAL" ], "flags": [ "SEES", "SMELLS", "HEARS", "CLIMBS", "PATH_AVOID_FIRE", "PATH_AVOID_FALL" ], "reproduction": { "baby_egg": "gum", "baby_count": 10, "baby_timer": 5 } diff --git a/data/mods/Salvaged_Robots/monsters.json b/data/mods/Salvaged_Robots/monsters.json index 247708b5d115b..112510c8afc32 100644 --- a/data/mods/Salvaged_Robots/monsters.json +++ b/data/mods/Salvaged_Robots/monsters.json @@ -140,7 +140,7 @@ "morale": 10, "dodge": 8, "armor_cut": 4, - "emit_fields": [ "emit_sparks" ], + "emit_fields": [ { "emit_id": "emit_sparks", "delay": "1 s" } ], "revert_to_itype": "bot_distract_hack", "death_function": [ "MELT" ], "special_attacks": [ [ "PARROT", 0 ] ], @@ -160,7 +160,7 @@ "aggression": 10, "morale": 0, "dodge": 4, - "emit_fields": [ "emit_fire_plume" ], + "emit_fields": [ { "emit_id": "emit_fire_plume", "delay": "1 s" } ], "death_function": [ "MELT" ], "extend": { "flags": [ "STUMBLES", "HARDTOSHOOT", "PET_WONT_FOLLOW", "FIREY" ] } }, @@ -243,7 +243,7 @@ "description": "A salvaged eyebot repurposed into a floating space heater. It emits a constant jet of warm air to heat an enclosed space.", "revert_to_itype": "bot_eyebot_heater", "fear_triggers": [ "HURT" ], - "emit_fields": [ "emit_hot_air2_stream" ], + "emit_fields": [ { "emit_id": "emit_hot_air2_stream", "delay": "1 s" } ], "extend": { "flags": [ "PET_WONT_FOLLOW", "WARM" ] } }, { @@ -410,7 +410,7 @@ "morale": 10, "fear_triggers": [ "HURT" ], "revert_to_itype": "bot_utilibot_digester", - "emit_fields": [ "emit_acid_trail" ], + "emit_fields": [ { "emit_id": "emit_acid_trail", "delay": "1 s" } ], "extend": { "flags": [ "STUMBLES", "ABSORBS", "ACIDPROOF" ] } }, { @@ -533,7 +533,7 @@ "description": "A salvaged medibot stuffed with marijuana, covered in multicolored blinking lights, and programmed to dance. Why on Earth would you build this crazy thing?", "color": "yellow", "luminance": 100, - "emit_fields": [ "emit_weed_puff" ], + "emit_fields": [ { "emit_id": "emit_weed_puff", "delay": "1 s" } ], "melee_skill": 4, "melee_dice": 2, "melee_dice_sides": 4, @@ -1205,7 +1205,7 @@ "vision_day": 20, "revert_to_itype": "bot_defbot_samurai", "special_when_hit": [ "ZAPBACK", 5 ], - "emit_fields": [ "emit_electric_arcs" ], + "emit_fields": [ { "emit_id": "emit_electric_arcs", "delay": "1 s" } ], "extend": { "flags": [ "ELECTRIC" ] } }, { @@ -1229,7 +1229,7 @@ "dodge": 3, "vision_day": 50, "revert_to_itype": "bot_defbot_paladin", - "emit_fields": [ "emit_smoke_trail" ], + "emit_fields": [ { "emit_id": "emit_smoke_trail", "delay": "1 s" } ], "starting_ammo": { "gasoline": 1000 }, "special_attacks": [ [ "PARROT", 0 ], @@ -1368,7 +1368,7 @@ "luminance": 200, "armor_bash": 8, "revert_to_itype": "bot_advbot_glitter", - "emit_fields": [ "emit_dazzle_trail" ], + "emit_fields": [ { "emit_id": "emit_dazzle_trail", "delay": "1 s" } ], "special_attacks": [ { "type": "gun", @@ -1397,7 +1397,7 @@ "melee_damage": [ { "damage_type": "acid", "amount": 8 } ], "armor_bash": 8, "armor_cut": 8, - "emit_fields": [ "emit_acid_trail" ], + "emit_fields": [ { "emit_id": "emit_acid_trail", "delay": "1 s" } ], "special_when_hit": [ "ACIDSPLASH", 100 ], "special_attacks": [ [ "ACID_BARF", 10 ], @@ -1588,7 +1588,7 @@ "attack_effs": [ { "id": "downed", "chance": 20, "duration": 10 }, { "id": "irradiated", "chance": 50 } ], "vision_day": 20, "revert_to_itype": "bot_tankbot_sultan", - "emit_fields": [ "emit_nuclear_trail" ], + "emit_fields": [ { "emit_id": "emit_nuclear_trail", "delay": "1 s" } ], "special_attacks": [ [ "SMASH", 30 ], [ "GRAB", 20 ] ], "extend": { "flags": [ "STUMBLES", "GRABS" ] } } diff --git a/doc/MONSTERS.md b/doc/MONSTERS.md index a2798f3ad60b7..54c725f0ee0bd 100644 --- a/doc/MONSTERS.md +++ b/doc/MONSTERS.md @@ -234,6 +234,12 @@ An item group that is used to spawn items when the monster dies. This can be an How the monster behaves on death. See JSON_FLAGS.md for a list of possible functions. One can add or remove entries in mods via "add:death_function" and "remove:death_function". +## "emit_field" +(array of objects of emit_id and time_duration, optional) +"emit_fields": [ { "emit_id": "emit_gum_web", "delay": "30 m" } ], + +What field the monster emits and how often it does so. Time duration can use strings: "1 h", "60 m", "3600 s" etc... + ## "regenerates" (integer, optional) diff --git a/src/monster.cpp b/src/monster.cpp index 1a1594433b278..1cb0502b09473 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1941,8 +1941,12 @@ void monster::process_turn() { decrement_summon_timer(); if( !is_hallucination() ) { - for( const auto &e : type->emit_fields ) { - if( e == emit_id( "emit_shock_cloud" ) ) { + for( const std::pair &e : type->emit_fields ) { + if( !calendar::once_every( e.second ) ) { + continue; + } + const emit_id emid = e.first; + if( emid == emit_id( "emit_shock_cloud" ) ) { if( has_effect( effect_emp ) ) { continue; // don't emit electricity while EMPed } else if( has_effect( effect_supercharged ) ) { @@ -1950,7 +1954,7 @@ void monster::process_turn() continue; } } - g->m.emit_field( pos(), e ); + g->m.emit_field( pos(), emid ); } } diff --git a/src/monstergenerator.cpp b/src/monstergenerator.cpp index 7fc39dfbb71ab..6206c3e7e1aba 100644 --- a/src/monstergenerator.cpp +++ b/src/monstergenerator.cpp @@ -760,7 +760,20 @@ void mtype::load( const JsonObject &jo, const std::string &src ) dies.push_back( mdeath::normal ); } - assign( jo, "emit_fields", emit_fields ); + if( jo.has_array( "emit_fields" ) ) { + JsonArray jar = jo.get_array( "emit_fields" ); + if( jar.has_string( 0 ) ) { // TEMPORARY until 0.F + for( const std::string id : jar ) { + emit_fields.emplace( emit_id( id ), 1_seconds ); + } + } else { + while( jar.has_more() ) { + JsonObject obj = jar.next_object(); + emit_fields.emplace( emit_id( obj.get_string( "emit_id" ) ), + read_from_json_string( *obj.get_raw( "delay" ), time_duration::units ) ); + } + } + } if( jo.has_member( "special_when_hit" ) ) { JsonArray jsarr = jo.get_array( "special_when_hit" ); @@ -1149,9 +1162,10 @@ void MonsterGenerator::check_monster_definitions() const } } - for( const auto &e : mon.emit_fields ) { - if( !e.is_valid() ) { - debugmsg( "monster %s has invalid emit source %s", mon.id.c_str(), e.c_str() ); + for( const std::pair &e : mon.emit_fields ) { + const emit_id emid = e.first; + if( !emid.is_valid() ) { + debugmsg( "monster %s has invalid emit source %s", mon.id.c_str(), emid.c_str() ); } } diff --git a/src/mtype.h b/src/mtype.h index d28bc9f100be2..c3fd06ee887d2 100644 --- a/src/mtype.h +++ b/src/mtype.h @@ -353,7 +353,7 @@ struct mtype { int mech_str_bonus = 0; /** Emission sources that cycle each turn the monster remains alive */ - std::set emit_fields; + std::map emit_fields; pathfinding_settings path_settings;