From 7df31a3263792e27e5bdde232cfb017c66a6cc1e Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:21 +0000 Subject: [PATCH 1/8] EoCs and dialogue track src EoCs need to have a src value defined so that they can overwrite eachoter. When loaded inline, sometimes this is not the case. Rip and tear dialogue stuff to ensure that EoCs can track their src. --- .../portal_storm_effect_on_condition.json | 2 +- data/json/npcs/missiondef.json | 4 +- .../mods/Aftershock/effects_on_condition.json | 5 - src/dialogue.h | 24 +- src/effect_on_condition.cpp | 8 +- src/mission.h | 3 +- src/mission_util.cpp | 5 +- src/missiondef.cpp | 2 +- src/npc.cpp | 4 +- src/npc.h | 2 +- src/npctalk.cpp | 456 ++++++++++-------- src/text_snippets.cpp | 2 +- 12 files changed, 285 insertions(+), 232 deletions(-) diff --git a/data/json/effects_on_condition/nether_eocs/portal_storm_effect_on_condition.json b/data/json/effects_on_condition/nether_eocs/portal_storm_effect_on_condition.json index d28c093da671d..8ce678af9100c 100644 --- a/data/json/effects_on_condition/nether_eocs/portal_storm_effect_on_condition.json +++ b/data/json/effects_on_condition/nether_eocs/portal_storm_effect_on_condition.json @@ -1120,7 +1120,7 @@ "case": 7, "effect": { "run_eocs": [ - { "id": "EOC_PORTAL_DUNGEON_REWARD_ITEM" }, + "EOC_PORTAL_DUNGEON_REWARD_ITEM", { "id": "EOC_PORTAL_DEPENDENT_DUNGEON_FINAL", "condition": { "u_has_trait": "PORTAL_DEPENDENT" }, diff --git a/data/json/npcs/missiondef.json b/data/json/npcs/missiondef.json index fc67b967c3a57..036f95196f9b7 100644 --- a/data/json/npcs/missiondef.json +++ b/data/json/npcs/missiondef.json @@ -330,9 +330,7 @@ "end": { "effect": [ "stop_following", - { - "weighted_list_eocs": [ [ { "id": "get_katana" }, 5 ], [ { "id": "get_deagle_44" }, 10 ], [ { "id": "get_m4_carbine" }, 6 ] ] - } + { "weighted_list_eocs": [ [ "get_katana", 5 ], [ "get_deagle_44", 10 ], [ "get_m4_carbine", 6 ] ] } ] }, "origins": [ "ORIGIN_SECONDARY" ], diff --git a/data/mods/Aftershock/effects_on_condition.json b/data/mods/Aftershock/effects_on_condition.json index 640d9e8e6a526..de47e81cd3595 100644 --- a/data/mods/Aftershock/effects_on_condition.json +++ b/data/mods/Aftershock/effects_on_condition.json @@ -71,11 +71,6 @@ { "u_teleport": { "global_val": "new_map" }, "force": true } ] }, - { - "type": "effect_on_condition", - "id": "EOC_AFS_ESCAPE_POD_CARGO_TP", - "effect": [ { "u_teleport": { "global_val": "new_map" }, "force": true } ] - }, { "type": "effect_on_condition", "id": "EOC_CRASHING_SHIP_SETUP", diff --git a/src/dialogue.h b/src/dialogue.h index 8b815a7bb30ec..fb1d3f7e8c3ee 100644 --- a/src/dialogue.h +++ b/src/dialogue.h @@ -129,12 +129,14 @@ struct talk_effect_t { void set_effect_consequence( const talk_effect_fun_t &fun, dialogue_consequence con ); void set_effect_consequence( const std::function &ptr, dialogue_consequence con ); - void load_effect( const JsonObject &jo, const std::string &member_name ); - void parse_sub_effect( const JsonObject &jo ); - void parse_string_effect( const std::string &effect_id, const JsonObject &jo ); + void load_effect( const JsonObject &jo, const std::string &member_name, + std::string_view src ); + void parse_sub_effect( const JsonObject &jo, std::string_view src ); + void parse_string_effect( const std::string &effect_id, const JsonObject &jo, + std::string_view src ); talk_effect_t() = default; - explicit talk_effect_t( const JsonObject &, const std::string & ); + explicit talk_effect_t( const JsonObject &, const std::string &, std::string_view src ); /** * Functions that are called when the response is chosen. @@ -178,7 +180,7 @@ struct talk_response { std::set get_consequences( dialogue &d ) const; talk_response(); - explicit talk_response( const JsonObject & ); + explicit talk_response( const JsonObject &, std::string_view ); }; struct dialogue { @@ -368,12 +370,12 @@ class json_talk_response // the topic to move to on failure std::string failure_topic; - void load_condition( const JsonObject &jo ); + void load_condition( const JsonObject &jo, std::string_view src ); bool test_condition( dialogue &d ) const; public: json_talk_response() = default; - explicit json_talk_response( const JsonObject &jo ); + explicit json_talk_response( const JsonObject &jo, std::string_view src ); const talk_response &get_actual_response() const; bool has_condition() const { @@ -394,7 +396,7 @@ class json_talk_repeat_response { public: json_talk_repeat_response() = default; - explicit json_talk_repeat_response( const JsonObject &jo ); + explicit json_talk_repeat_response( const JsonObject &jo, std::string_view src ); bool is_npc = false; bool include_containers = false; std::vector for_item; @@ -408,7 +410,7 @@ class json_dynamic_line_effect std::function condition; talk_effect_t effect; public: - json_dynamic_line_effect( const JsonObject &jo, const std::string &id ); + json_dynamic_line_effect( const JsonObject &jo, const std::string &id, std::string_view src ); bool test_condition( dialogue &d ) const; void apply( dialogue &d ) const; }; @@ -433,7 +435,7 @@ class json_talk_topic * It will override dynamic_line and replace_built_in_responses if those entries * exist in the input, otherwise they will not be changed at all. */ - void load( const JsonObject &jo ); + void load( const JsonObject &jo, std::string_view src ); std::string get_dynamic_line( dialogue &d ) const; std::vector get_speaker_effects() const; @@ -452,6 +454,6 @@ class json_talk_topic }; void unload_talk_topics(); -void load_talk_topic( const JsonObject &jo ); +void load_talk_topic( const JsonObject &jo, std::string_view src ); #endif // CATA_SRC_DIALOGUE_H diff --git a/src/effect_on_condition.cpp b/src/effect_on_condition.cpp index 276caba9baac0..268ea51f73551 100644 --- a/src/effect_on_condition.cpp +++ b/src/effect_on_condition.cpp @@ -75,7 +75,7 @@ void effect_on_conditions::check_consistency() { } -void effect_on_condition::load( const JsonObject &jo, const std::string_view ) +void effect_on_condition::load( const JsonObject &jo, const std::string_view src ) { mandatory( jo, was_loaded, "id", id ); optional( jo, was_loaded, "eoc_type", type, eoc_type::NUM_EOC_TYPES ); @@ -98,10 +98,10 @@ void effect_on_condition::load( const JsonObject &jo, const std::string_view ) read_condition( jo, "condition", condition, false ); has_condition = true; } - true_effect.load_effect( jo, "effect" ); + true_effect.load_effect( jo, "effect", std::string( src ) ); if( jo.has_member( "false_effect" ) ) { - false_effect.load_effect( jo, "false_effect" ); + false_effect.load_effect( jo, "false_effect", std::string( src ) ); has_false_effect = true; } @@ -117,7 +117,7 @@ void effect_on_condition::load( const JsonObject &jo, const std::string_view ) } effect_on_condition_id effect_on_conditions::load_inline_eoc( const JsonValue &jv, - std::string_view src ) + const std::string_view src ) { if( jv.test_string() ) { return effect_on_condition_id( jv.get_string() ); diff --git a/src/mission.h b/src/mission.h index 5e7c3a2623f5f..6ad01ef886796 100644 --- a/src/mission.h +++ b/src/mission.h @@ -260,7 +260,8 @@ struct mission_type { static void finalize(); static void check_consistency(); - bool parse_funcs( const JsonObject &jo, std::function &phase_func ); + bool parse_funcs( const JsonObject &jo, std::string_view src, + std::function &phase_func ); void load( const JsonObject &jo, const std::string &src ); /** diff --git a/src/mission_util.cpp b/src/mission_util.cpp index b5cc7d0b4c5e2..d50189f7199a0 100644 --- a/src/mission_util.cpp +++ b/src/mission_util.cpp @@ -526,7 +526,8 @@ bool mission_util::load_funcs( const JsonObject &jo, return true; } -bool mission_type::parse_funcs( const JsonObject &jo, std::function &phase_func ) +bool mission_type::parse_funcs( const JsonObject &jo, const std::string_view src, + std::function &phase_func ) { std::vector> funcs; if( !mission_util::load_funcs( jo, funcs ) ) { @@ -537,7 +538,7 @@ bool mission_type::parse_funcs( const JsonObject &jo, std::functionfind_npc( miss->get_npc_id() ); ::dialogue d( get_talker_for( get_avatar() ), diff --git a/src/missiondef.cpp b/src/missiondef.cpp index a942ec3e6851c..c7f2b1ff96e88 100644 --- a/src/missiondef.cpp +++ b/src/missiondef.cpp @@ -365,7 +365,7 @@ void mission_type::load( const JsonObject &jo, const std::string &src ) assign_function( jo, phase, phase_func, mission_function_map ); } else if( jo.has_member( phase ) ) { JsonObject j_start = jo.get_object( phase ); - if( !parse_funcs( j_start, phase_func ) ) { + if( !parse_funcs( j_start, src, phase_func ) ) { deferred.emplace_back( jo, src ); jo.allow_omitted_members(); j_start.allow_omitted_members(); diff --git a/src/npc.cpp b/src/npc.cpp index 79fddacf97d07..dee63fcc56c64 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -296,7 +296,7 @@ npc &npc::operator=( npc && ) noexcept( list_is_noexcept ) = default; static std::map, npc_template> npc_templates; -void npc_template::load( const JsonObject &jsobj ) +void npc_template::load( const JsonObject &jsobj, const std::string_view src ) { npc_template tem; npc &guy = tem.guy; @@ -450,7 +450,7 @@ void npc_template::load( const JsonObject &jsobj ) tem.personality->altruism = personality.get_int( "altruism" ); } for( JsonValue jv : jsobj.get_array( "death_eocs" ) ) { - guy.death_eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + guy.death_eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, src ) ); } npc_templates.emplace( guy.idz, std::move( tem ) ); diff --git a/src/npc.h b/src/npc.h index c087293756f31..61e9206412771 100644 --- a/src/npc.h +++ b/src/npc.h @@ -1513,7 +1513,7 @@ class npc_template std::optional per; std::optional personality; - static void load( const JsonObject &jsobj ); + static void load( const JsonObject &jsobj, std::string_view src ); static void reset(); static void check_consistency(); }; diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 1dea0eac3d7b2..95de6f3e67983 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -127,29 +127,33 @@ using item_menu = std::function; using item_menu_mul = std::function; struct sub_effect_parser { - using f_t = talk_effect_fun_t::func( * )( const JsonObject &, std::string_view ); - using f_t_beta = talk_effect_fun_t::func( * )( const JsonObject &, std::string_view, bool ); - using f_t_effect = talk_effect_fun_t ( * )( const JsonObject &, std::string_view ); - using f_t_beta_effect = talk_effect_fun_t ( * )( const JsonObject &, std::string_view, bool ); + using f_t = talk_effect_fun_t::func( * )( const JsonObject &, std::string_view, + const std::string_view src ); + using f_t_beta = talk_effect_fun_t::func( * )( const JsonObject &, std::string_view, + const std::string_view src, bool ); + using f_t_effect = talk_effect_fun_t ( * )( const JsonObject &, std::string_view, + const std::string_view src ); + using f_t_beta_effect = talk_effect_fun_t ( * )( const JsonObject &, std::string_view, + const std::string_view src, bool ); sub_effect_parser( std::string_view key_alpha_, jarg arg_, f_t f_ ) : key_alpha( key_alpha_ ), arg( arg_ ) { - f = [f_]( const JsonObject & jo, std::string_view key, bool ) { - return talk_effect_fun_t( f_( jo, key ) ); + f = [f_]( const JsonObject & jo, std::string_view key, const std::string_view src, bool ) { + return talk_effect_fun_t( f_( jo, key, src ) ); }; } sub_effect_parser( std::string_view key_alpha_, std::string_view key_beta_, jarg arg_, f_t_beta f_ ) : key_alpha( key_alpha_ ), key_beta( key_beta_ ), arg( arg_ ) { - f = [f_]( const JsonObject & jo, std::string_view key, bool beta ) { - return talk_effect_fun_t( f_( jo, key, beta ) ); + f = [f_]( const JsonObject & jo, std::string_view key, const std::string_view src, bool beta ) { + return talk_effect_fun_t( f_( jo, key, src, beta ) ); }; has_beta = true; } sub_effect_parser( std::string_view key_alpha_, jarg arg_, f_t_effect f_ ) : key_alpha( key_alpha_ ), arg( arg_ ) { - f = [f_]( const JsonObject & jo, std::string_view key, bool ) { - return f_( jo, key ); + f = [f_]( const JsonObject & jo, std::string_view key, const std::string_view src, bool ) { + return f_( jo, key, src ); }; } @@ -168,7 +172,8 @@ struct sub_effect_parser { std::string_view key_alpha; std::string_view key_beta; jarg arg; - std::function f; + std::function + f; }; struct item_search_data { @@ -269,15 +274,15 @@ static void run_eoc_vector( const std::vector &eocs, con } static std::vector load_eoc_vector( const JsonObject &jo, - const std::string_view member ) + const std::string_view member, const std::string_view src ) { std::vector eocs; if( jo.has_array( member ) ) { for( JsonValue jv : jo.get_array( member ) ) { - eocs.push_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + eocs.push_back( effect_on_conditions::load_inline_eoc( jv, src ) ); } } else if( jo.has_member( member ) ) { - eocs.push_back( effect_on_conditions::load_inline_eoc( jo.get_member( member ), "" ) ); + eocs.push_back( effect_on_conditions::load_inline_eoc( jo.get_member( member ), src ) ); } return eocs; } @@ -288,10 +293,10 @@ struct eoc_entry { }; static std::vector load_eoc_vector_id_and_var( - const JsonObject &jo, const std::string_view member ) + const JsonObject &jo, const std::string_view member, const std::string_view src ) { std::vector eocs_entries; - auto process_jv = [member, &eocs_entries]( const JsonValue & jv ) { + auto process_jv = [member, &eocs_entries, &src]( const JsonValue & jv ) { eoc_entry entry; if( jv.test_object() ) { JsonObject jo = jv.get_object(); @@ -301,7 +306,7 @@ load_eoc_vector_id_and_var( } } if( !entry.var ) { - entry.id = effect_on_conditions::load_inline_eoc( jv, "" ); + entry.id = effect_on_conditions::load_inline_eoc( jv, src ); } eocs_entries.push_back( entry ); }; @@ -2747,10 +2752,10 @@ talk_trial::talk_trial( const JsonObject &jo ) } } -static talk_topic load_inline_topic( const JsonObject &jo ) +static talk_topic load_inline_topic( const JsonObject &jo, const std::string_view src ) { const std::string id = jo.get_string( "id" ); - json_talk_topics[id].load( jo ); + json_talk_topics[id].load( jo, src ); return talk_topic( id ); } @@ -2897,7 +2902,8 @@ namespace talk_effect_fun { namespace { -talk_effect_fun_t::func f_companion_mission( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_companion_mission( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var id = get_str_or_var( jo.get_member( member ), member, true ); return [id]( dialogue const & d ) { @@ -2907,7 +2913,7 @@ talk_effect_fun_t::func f_companion_mission( const JsonObject &jo, std::string_v } talk_effect_fun_t::func f_add_effect( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_effect = get_str_or_var( jo.get_member( member ), member, true ); bool permanent = false; @@ -2945,7 +2951,7 @@ talk_effect_fun_t::func f_add_effect( const JsonObject &jo, std::string_view mem } talk_effect_fun_t::func f_remove_effect( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var old_effect = get_str_or_var( jo.get_member( member ), member, true ); @@ -2962,7 +2968,7 @@ talk_effect_fun_t::func f_remove_effect( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_add_trait( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_trait = get_str_or_var( jo.get_member( member ), member, true ); str_or_var new_variant; @@ -2982,7 +2988,7 @@ talk_effect_fun_t::func f_add_trait( const JsonObject &jo, std::string_view memb } talk_effect_fun_t::func f_activate_trait( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_trait = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, new_trait]( dialogue const & d ) { @@ -2991,7 +2997,7 @@ talk_effect_fun_t::func f_activate_trait( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_deactivate_trait( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_trait = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, new_trait]( dialogue const & d ) { @@ -3000,7 +3006,7 @@ talk_effect_fun_t::func f_deactivate_trait( const JsonObject &jo, std::string_vi } talk_effect_fun_t::func f_remove_trait( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var old_trait = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, old_trait]( dialogue const & d ) { @@ -3009,7 +3015,7 @@ talk_effect_fun_t::func f_remove_trait( const JsonObject &jo, std::string_view m } talk_effect_fun_t::func f_learn_martial_art( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var ma_to_learn = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, ma_to_learn]( dialogue const & d ) { @@ -3018,7 +3024,7 @@ talk_effect_fun_t::func f_learn_martial_art( const JsonObject &jo, std::string_v } talk_effect_fun_t::func f_forget_martial_art( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var ma_to_forget = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, ma_to_forget]( dialogue const & d ) { @@ -3027,7 +3033,7 @@ talk_effect_fun_t::func f_forget_martial_art( const JsonObject &jo, std::string_ } talk_effect_fun_t::func f_mutate( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var highest_cat = get_dbl_or_var( jo, member, true, 0 ); const bool use_vitamins = jo.get_bool( "use_vitamins", true ); @@ -3037,7 +3043,7 @@ talk_effect_fun_t::func f_mutate( const JsonObject &jo, std::string_view member, } talk_effect_fun_t::func f_mutate_category( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var mut_cat = get_str_or_var( jo.get_member( member ), member, true, "" ); const bool use_vitamins = jo.get_bool( "use_vitamins", true ); @@ -3047,7 +3053,7 @@ talk_effect_fun_t::func f_mutate_category( const JsonObject &jo, std::string_vie } talk_effect_fun_t::func f_mutate_towards( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var trait = get_str_or_var( jo.get_member( member ), member, true, "" ); str_or_var mut_cat; @@ -3065,7 +3071,7 @@ talk_effect_fun_t::func f_mutate_towards( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_add_bionic( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_bionic = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, new_bionic]( dialogue const & d ) { @@ -3074,7 +3080,7 @@ talk_effect_fun_t::func f_add_bionic( const JsonObject &jo, std::string_view mem } talk_effect_fun_t::func f_lose_bionic( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var old_bionic = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, old_bionic]( dialogue const & d ) { @@ -3083,7 +3089,7 @@ talk_effect_fun_t::func f_lose_bionic( const JsonObject &jo, std::string_view me } talk_effect_fun_t::func f_add_var( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var empty; const std::string var_name = get_talk_varname( jo, member, false, empty ); @@ -3107,7 +3113,7 @@ talk_effect_fun_t::func f_add_var( const JsonObject &jo, std::string_view member } talk_effect_fun_t::func f_remove_var( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var empty; const std::string var_name = get_talk_varname( jo, member, false, empty ); @@ -3214,7 +3220,8 @@ void receive_item( itype_id &item_name, int count, std::string_view container_na } } -talk_effect_fun_t f_spawn_item( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t f_spawn_item( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var item_name = get_str_or_var( jo.get_member( member ), member, true ); str_or_var container_name; @@ -3263,10 +3270,11 @@ talk_effect_fun_t f_spawn_item( const JsonObject &jo, std::string_view member ) return ret; } -talk_effect_fun_t::func f_u_buy_item( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_u_buy_item( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); dbl_or_var cost = get_dbl_or_var( jo, "cost", false, 0 ); dbl_or_var count; if( !jo.has_int( "charges" ) ) { @@ -3307,10 +3315,11 @@ talk_effect_fun_t::func f_u_buy_item( const JsonObject &jo, std::string_view mem }; } -talk_effect_fun_t::func f_u_sell_item( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_u_sell_item( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); dbl_or_var cost = get_dbl_or_var( jo, "cost", false, 0 ); dbl_or_var count; if( !jo.has_int( "charges" ) ) { @@ -3354,7 +3363,7 @@ talk_effect_fun_t::func f_u_sell_item( const JsonObject &jo, std::string_view me } talk_effect_fun_t::func f_consume_item( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var item_name = get_str_or_var( jo.get_member( member ), member, true ); dbl_or_var charges = get_dbl_or_var( jo, "charges", false, 0 ); @@ -3409,7 +3418,7 @@ talk_effect_fun_t::func f_consume_item( const JsonObject &jo, std::string_view m } talk_effect_fun_t::func f_remove_item_with( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var item_name = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, item_name]( dialogue const & d ) { @@ -3420,11 +3429,12 @@ talk_effect_fun_t::func f_remove_item_with( const JsonObject &jo, std::string_vi }; } -talk_effect_fun_t::func f_u_spend_cash( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_u_spend_cash( const JsonObject &jo, std::string_view member, + const std::string_view src ) { dbl_or_var amount = get_dbl_or_var( jo, member ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [amount, true_eocs, false_eocs]( dialogue & d ) { if( d.actor( true )->buy_from( amount.evaluate( d ) ) ) { run_eoc_vector( true_eocs, d ); @@ -3434,7 +3444,8 @@ talk_effect_fun_t::func f_u_spend_cash( const JsonObject &jo, std::string_view m }; } -talk_effect_fun_t::func f_npc_change_faction( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_npc_change_faction( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var faction_name = get_str_or_var( jo.get_member( member ), member, true ); return [faction_name]( dialogue const & d ) { @@ -3442,7 +3453,8 @@ talk_effect_fun_t::func f_npc_change_faction( const JsonObject &jo, std::string_ }; } -talk_effect_fun_t::func f_npc_change_class( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_npc_change_class( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var class_name = get_str_or_var( jo.get_member( member ), member, true ); return [class_name]( dialogue const & d ) { @@ -3450,7 +3462,8 @@ talk_effect_fun_t::func f_npc_change_class( const JsonObject &jo, std::string_vi }; } -talk_effect_fun_t::func f_change_faction_rep( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_change_faction_rep( const JsonObject &jo, std::string_view member, + const std::string_view ) { dbl_or_var rep_change = get_dbl_or_var( jo, member ); return [rep_change]( dialogue & d ) { @@ -3458,7 +3471,8 @@ talk_effect_fun_t::func f_change_faction_rep( const JsonObject &jo, std::string_ }; } -talk_effect_fun_t::func f_add_debt( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_add_debt( const JsonObject &jo, std::string_view member, + const std::string_view ) { std::vector debt_modifiers; for( JsonArray jmod : jo.get_array( member ) ) { @@ -3480,7 +3494,8 @@ talk_effect_fun_t::func f_add_debt( const JsonObject &jo, std::string_view membe }; } -talk_effect_fun_t::func f_toggle_npc_rule( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_toggle_npc_rule( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3488,7 +3503,8 @@ talk_effect_fun_t::func f_toggle_npc_rule( const JsonObject &jo, std::string_vie }; } -talk_effect_fun_t::func f_set_npc_rule( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_set_npc_rule( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3496,7 +3512,8 @@ talk_effect_fun_t::func f_set_npc_rule( const JsonObject &jo, std::string_view m }; } -talk_effect_fun_t::func f_clear_npc_rule( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_clear_npc_rule( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3505,7 +3522,7 @@ talk_effect_fun_t::func f_clear_npc_rule( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_npc_engagement_rule( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3513,7 +3530,8 @@ talk_effect_fun_t::func f_npc_engagement_rule( const JsonObject &jo, }; } -talk_effect_fun_t::func f_npc_aim_rule( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_npc_aim_rule( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3522,7 +3540,7 @@ talk_effect_fun_t::func f_npc_aim_rule( const JsonObject &jo, std::string_view m } talk_effect_fun_t::func f_npc_cbm_reserve_rule( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3531,7 +3549,7 @@ talk_effect_fun_t::func f_npc_cbm_reserve_rule( const JsonObject &jo, } talk_effect_fun_t::func f_npc_cbm_recharge_rule( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { str_or_var rule = get_str_or_var( jo.get_member( member ), member, true ); return [rule]( dialogue const & d ) { @@ -3540,7 +3558,7 @@ talk_effect_fun_t::func f_npc_cbm_recharge_rule( const JsonObject &jo, } talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { dbl_or_var dov_min_radius = get_dbl_or_var( jo, "min_radius", false, 0 ); dbl_or_var dov_max_radius = get_dbl_or_var( jo, "max_radius", false, 0 ); @@ -3595,8 +3613,8 @@ talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_v var_type type = var.type; std::string var_name = var.name; - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [dov_min_radius, dov_max_radius, var_name, outdoor_only, passable_only, target_params, is_npc, type, dov_x_adjust, dov_y_adjust, dov_z_adjust, z_override, true_eocs, false_eocs, @@ -3726,7 +3744,7 @@ talk_effect_fun_t::func f_location_variable( const JsonObject &jo, std::string_v } talk_effect_fun_t::func f_location_variable_adjust( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { dbl_or_var dov_z_adjust = get_dbl_or_var( jo, "z_adjust", false, 0 ); dbl_or_var dov_x_adjust = get_dbl_or_var( jo, "x_adjust", false, 0 ); @@ -3765,7 +3783,7 @@ talk_effect_fun_t::func f_location_variable_adjust( const JsonObject &jo, } talk_effect_fun_t::func f_transform_radius( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var transform = get_str_or_var( jo.get_member( "ter_furn_transform" ), "ter_furn_transform", true ); @@ -3810,7 +3828,8 @@ talk_effect_fun_t::func f_transform_radius( const JsonObject &jo, std::string_vi }; } -talk_effect_fun_t::func f_transform_line( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_transform_line( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var transform = get_str_or_var( jo.get_member( member ), member, true ); var_info first = read_var_info( jo.get_object( "first" ) ); @@ -3826,7 +3845,8 @@ talk_effect_fun_t::func f_transform_line( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_place_override( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_place_override( const JsonObject &jo, std::string_view member, + const std::string_view ) { translation_or_var new_place = get_translation_or_var( jo.get_member( member ), member ); duration_or_var dov_length = get_duration_or_var( jo, "length", true ); @@ -3844,7 +3864,8 @@ talk_effect_fun_t::func f_place_override( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_mapgen_update( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_mapgen_update( const JsonObject &jo, std::string_view member, + const std::string_view ) { mission_target_params target_params = mission_util::parse_mission_om_target( jo ); std::vector update_ids; @@ -3899,7 +3920,8 @@ talk_effect_fun_t::func f_mapgen_update( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_alter_timed_events( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_alter_timed_events( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var key = get_str_or_var( jo.get_member( member ), member, true ); duration_or_var time_in_future = get_duration_or_var( jo, "time_in_future", false, @@ -3909,7 +3931,8 @@ talk_effect_fun_t::func f_alter_timed_events( const JsonObject &jo, std::string_ }; } -talk_effect_fun_t::func f_revert_location( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_revert_location( const JsonObject &jo, std::string_view member, + const std::string_view ) { duration_or_var dov_time_in_future = get_duration_or_var( jo, "time_in_future", true ); str_or_var key; @@ -3950,12 +3973,12 @@ talk_effect_fun_t::func f_revert_location( const JsonObject &jo, std::string_vie } talk_effect_fun_t::func f_npc_goal( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { mission_target_params dest_params = mission_util::parse_mission_om_target( jo.get_object( member ) ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [dest_params, true_eocs, false_eocs, is_npc]( dialogue & d ) { npc *guy = d.actor( is_npc )->get_npc(); if( guy ) { @@ -3981,7 +4004,7 @@ talk_effect_fun_t::func f_npc_goal( const JsonObject &jo, std::string_view membe } talk_effect_fun_t::func f_guard_pos( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { std::optional target_var = read_var_info( jo.get_object( member ) ); bool unique_id = jo.get_bool( "unique_id", false ); @@ -4000,7 +4023,7 @@ talk_effect_fun_t::func f_guard_pos( const JsonObject &jo, std::string_view memb } talk_effect_fun_t::func f_bulk_trade_accept( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var dov_quantity; if( jo.has_member( member ) ) { @@ -4156,7 +4179,8 @@ talk_effect_fun_t::func f_npc_gets_item( bool to_use ) }; } -talk_effect_fun_t::func f_add_mission( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_add_mission( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var mission_id = get_str_or_var( jo.get_member( member ), member, true ); return [mission_id]( dialogue const & d ) { @@ -4164,7 +4188,8 @@ talk_effect_fun_t::func f_add_mission( const JsonObject &jo, std::string_view me }; } -talk_effect_fun_t::func f_u_buy_monster( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_u_buy_monster( const JsonObject &jo, std::string_view member, + const std::string_view src ) { str_or_var monster_type_id = get_str_or_var( jo.get_member( member ), member, true ); dbl_or_var cost = get_dbl_or_var( jo, "cost", false, 0 ); @@ -4176,8 +4201,8 @@ talk_effect_fun_t::func f_u_buy_monster( const JsonObject &jo, std::string_view } else { name.str_val = translation(); } - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [monster_type_id, cost, count, pacified, name, true_eocs, false_eocs]( dialogue & d ) { const mtype_id mtype( monster_type_id.evaluate( d ) ); @@ -4192,7 +4217,7 @@ talk_effect_fun_t::func f_u_buy_monster( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_learn_recipe( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var learned_recipe_id = get_str_or_var( jo.get_member( member ), member, true ); return [learned_recipe_id, is_npc]( dialogue const & d ) { @@ -4202,7 +4227,7 @@ talk_effect_fun_t::func f_learn_recipe( const JsonObject &jo, std::string_view m } talk_effect_fun_t::func f_forget_recipe( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var forgotten_recipe_id = get_str_or_var( jo.get_member( member ), member, true ); return [forgotten_recipe_id, is_npc]( dialogue const & d ) { @@ -4211,7 +4236,8 @@ talk_effect_fun_t::func f_forget_recipe( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_turn_cost( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_turn_cost( const JsonObject &jo, std::string_view member, + const std::string_view ) { duration_or_var cost = get_duration_or_var( jo, member, true ); return [cost]( dialogue & d ) { @@ -4222,7 +4248,8 @@ talk_effect_fun_t::func f_turn_cost( const JsonObject &jo, std::string_view memb }; } -talk_effect_fun_t::func f_npc_first_topic( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_npc_first_topic( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var chat_topic = get_str_or_var( jo.get_member( member ), member, true ); return [chat_topic]( dialogue const & d ) { @@ -4231,7 +4258,7 @@ talk_effect_fun_t::func f_npc_first_topic( const JsonObject &jo, std::string_vie } talk_effect_fun_t::func f_message( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { const bool snippet = jo.get_bool( "snippet", false ); str_or_var snip_id; @@ -4356,7 +4383,7 @@ talk_effect_fun_t::func f_message( const JsonObject &jo, std::string_view member } talk_effect_fun_t::func f_assign_activity( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { duration_or_var dov = get_duration_or_var( jo, "duration", true ); str_or_var act = get_str_or_var( jo.get_member( member ), member, true ); @@ -4369,7 +4396,7 @@ talk_effect_fun_t::func f_assign_activity( const JsonObject &jo, std::string_vie } talk_effect_fun_t::func f_add_wet( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var dov = get_dbl_or_var( jo, member ); return [is_npc, dov]( dialogue & d ) { @@ -4380,7 +4407,8 @@ talk_effect_fun_t::func f_add_wet( const JsonObject &jo, std::string_view member }; } -talk_effect_fun_t::func f_open_dialogue( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_open_dialogue( const JsonObject &jo, std::string_view member, + const std::string_view src ) { std::vector true_eocs; std::vector false_eocs; @@ -4389,8 +4417,8 @@ talk_effect_fun_t::func f_open_dialogue( const JsonObject &jo, std::string_view if( jo.has_object( member ) ) { has_member = true; JsonObject innerJo = jo.get_object( member ); - true_eocs = load_eoc_vector( innerJo, "true_eocs" ); - false_eocs = load_eoc_vector( innerJo, "false_eocs" ); + true_eocs = load_eoc_vector( innerJo, "true_eocs", src ); + false_eocs = load_eoc_vector( innerJo, "false_eocs", src ); topic = get_str_or_var( innerJo.get_member( "topic" ), "topic" ); } return [true_eocs, false_eocs, topic, has_member]( dialogue const & d ) { @@ -4419,10 +4447,11 @@ talk_effect_fun_t::func f_open_dialogue( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_take_control( const JsonObject &jo, std::string_view ) +talk_effect_fun_t::func f_take_control( const JsonObject &jo, std::string_view, + const std::string_view src ) { - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [true_eocs, false_eocs]( dialogue const & d ) { if( !d.actor( false )->get_character()->is_avatar() ) { //only take control if the avatar is alpha run_eoc_vector( false_eocs, d ); @@ -4441,7 +4470,8 @@ talk_effect_fun_t::func f_take_control_menu() }; } -talk_effect_fun_t::func f_sound_effect( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_sound_effect( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var variant = get_str_or_var( jo.get_member( member ), member, true ); str_or_var id = get_str_or_var( jo.get_member( "id" ), "id", true ); @@ -4475,7 +4505,8 @@ talk_effect_fun_t::func f_sound_effect( const JsonObject &jo, std::string_view m }; } -talk_effect_fun_t::func f_give_achievment( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_give_achievment( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var achieve = get_str_or_var( jo.get_member( member ), member, true ); return [achieve]( dialogue const & d ) { @@ -4495,7 +4526,7 @@ talk_effect_fun_t::func f_give_achievment( const JsonObject &jo, std::string_vie } talk_effect_fun_t::func f_mod_healthy( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var dov_amount = get_dbl_or_var( jo, member ); dbl_or_var dov_cap = get_dbl_or_var( jo, "cap" ); @@ -4507,10 +4538,10 @@ talk_effect_fun_t::func f_mod_healthy( const JsonObject &jo, std::string_view me } talk_effect_fun_t::func f_cast_spell( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); bool targeted = jo.get_bool( "targeted", false ); std::optional loc_var; @@ -4587,7 +4618,7 @@ talk_effect_fun_t::func f_cast_spell( const JsonObject &jo, std::string_view mem } talk_effect_fun_t::func f_attack( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var force_technique = get_str_or_var( jo.get_member( member ), member, true ); bool allow_special = jo.get_bool( "allow_special", true ); @@ -4641,7 +4672,8 @@ talk_effect_fun_t::func f_next_weather() }; } -talk_effect_fun_t::func f_set_string_var( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_set_string_var( const JsonObject &jo, std::string_view member, + const std::string_view ) { const bool i18n = jo.get_bool( "i18n", false ); std::vector str_vals; @@ -4676,7 +4708,8 @@ talk_effect_fun_t::func f_set_string_var( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_set_condition( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_set_condition( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var value; value = get_str_or_var( jo.get_member( member ), member ); @@ -4689,7 +4722,7 @@ talk_effect_fun_t::func f_set_condition( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_set_item_category_spawn_rates( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { if( jo.has_array( member ) ) { std::set> rates; @@ -4713,7 +4746,8 @@ talk_effect_fun_t::func f_set_item_category_spawn_rates( const JsonObject &jo, } } -talk_effect_fun_t::func f_assign_mission( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_assign_mission( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var mission_name = get_str_or_var( jo.get_member( member ), member, true ); return [mission_name]( dialogue const & d ) { @@ -4725,7 +4759,8 @@ talk_effect_fun_t::func f_assign_mission( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_finish_mission( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_finish_mission( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var mission_name = get_str_or_var( jo.get_member( member ), member, true ); bool success = false; @@ -4756,7 +4791,7 @@ talk_effect_fun_t::func f_finish_mission( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_remove_active_mission( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { str_or_var mission_name = get_str_or_var( jo.get_member( member ), member, true ); return [mission_name]( dialogue const & d ) { @@ -4772,7 +4807,8 @@ talk_effect_fun_t::func f_remove_active_mission( const JsonObject &jo, }; } -talk_effect_fun_t::func f_offer_mission( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_offer_mission( const JsonObject &jo, std::string_view member, + const std::string_view ) { std::vector mission_names; @@ -4799,7 +4835,7 @@ talk_effect_fun_t::func f_offer_mission( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_set_flag( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var flag = get_str_or_var( jo.get_member( member ), member, true ); @@ -4816,7 +4852,7 @@ talk_effect_fun_t::func f_set_flag( const JsonObject &jo, std::string_view membe } talk_effect_fun_t::func f_unset_flag( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var flag = get_str_or_var( jo.get_member( member ), member, true ); @@ -4833,7 +4869,7 @@ talk_effect_fun_t::func f_unset_flag( const JsonObject &jo, std::string_view mem } talk_effect_fun_t::func f_activate( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var method = get_str_or_var( jo.get_member( member ), member, true ); std::optional target_var; @@ -4870,7 +4906,8 @@ talk_effect_fun_t::func f_activate( const JsonObject &jo, std::string_view membe }; } -talk_effect_fun_t::func f_math( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_math( const JsonObject &jo, std::string_view member, + const std::string_view ) { eoc_math math; math.from_json( jo, member, eoc_math::type_t::assign ); @@ -4880,7 +4917,8 @@ talk_effect_fun_t::func f_math( const JsonObject &jo, std::string_view member ) } -talk_effect_fun_t::func f_transform_item( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_transform_item( const JsonObject &jo, std::string_view member, + const std::string_view ) { str_or_var target_id = get_str_or_var( jo.get_member( member ), member, true ); bool activate = jo.get_bool( "active", false ); @@ -4899,7 +4937,7 @@ talk_effect_fun_t::func f_transform_item( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_make_sound( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { dbl_or_var volume = get_dbl_or_var( jo, "volume", true ); bool ambient = jo.get_bool( "ambient", false ); @@ -4973,9 +5011,10 @@ talk_effect_fun_t::func f_make_sound( const JsonObject &jo, std::string_view mem -talk_effect_fun_t::func f_run_eocs( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_run_eocs( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - std::vector eocs_entries = load_eoc_vector_id_and_var( jo, member ); + std::vector eocs_entries = load_eoc_vector_id_and_var( jo, member, src ); if( eocs_entries.empty() ) { jo.throw_error( "Invalid input for run_eocs" ); @@ -4990,9 +5029,10 @@ talk_effect_fun_t::func f_run_eocs( const JsonObject &jo, std::string_view membe }; } -talk_effect_fun_t::func f_run_eoc_until( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_run_eoc_until( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), "" ); + effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), src ); std::function cond; read_condition( jo, "condition", cond, true ); // The default result of this condition is true @@ -5015,10 +5055,11 @@ talk_effect_fun_t::func f_run_eoc_until( const JsonObject &jo, std::string_view }; } -talk_effect_fun_t::func f_run_eoc_selector( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_run_eoc_selector( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - std::vector eocs = load_eoc_vector_id_and_var( jo, member ); + std::vector eocs = load_eoc_vector_id_and_var( jo, member, src ); if( eocs.empty() ) { jo.throw_error( "Invalid input for run_eocs" ); } @@ -5175,9 +5216,10 @@ talk_effect_fun_t::func f_run_eoc_selector( const JsonObject &jo, std::string_vi } -talk_effect_fun_t::func f_run_eoc_with( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_run_eoc_with( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), "" ); + effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), src ); std::unordered_map context; if( jo.has_object( "variables" ) ) { @@ -5215,7 +5257,7 @@ talk_effect_fun_t::func f_run_eoc_with( const JsonObject &jo, std::string_view m has_alpha_var = false; } - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [eoc, context, alpha_var, beta_var, is_alpha_loc, is_beta_loc, has_alpha_var, has_beta_var, false_eocs]( dialogue const & d ) { @@ -5273,9 +5315,9 @@ talk_effect_fun_t::func f_run_eoc_with( const JsonObject &jo, std::string_view m } talk_effect_fun_t::func f_run_npc_eocs( const JsonObject &jo, - std::string_view member, bool is_npc ) + std::string_view member, const std::string_view src, bool is_npc ) { - std::vector eocs = load_eoc_vector( jo, member ); + std::vector eocs = load_eoc_vector( jo, member, src ); std::vector unique_ids; for( JsonValue jv : jo.get_array( "unique_ids" ) ) { unique_ids.emplace_back( get_str_or_var( jv, "unique_ids" ) ); @@ -5335,9 +5377,9 @@ talk_effect_fun_t::func f_run_npc_eocs( const JsonObject &jo, } talk_effect_fun_t::func f_run_monster_eocs( const JsonObject &jo, - std::string_view member, bool is_npc ) + std::string_view member, const std::string_view src, bool is_npc ) { - std::vector eocs = load_eoc_vector( jo, member ); + std::vector eocs = load_eoc_vector( jo, member, src ); std::vector mtype_ids; for( JsonValue jv : jo.get_array( "mtype_ids" ) ) { mtype_ids.emplace_back( get_str_or_var( jv, "mtype_ids" ) ); @@ -5383,11 +5425,11 @@ talk_effect_fun_t::func f_run_monster_eocs( const JsonObject &jo, talk_effect_fun_t::func f_run_inv_eocs( const JsonObject &jo, - std::string_view member, bool is_npc ) + std::string_view member, const std::string_view src, bool is_npc ) { str_or_var option = get_str_or_var( jo.get_member( member ), member ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); std::vector data; for( const JsonValue &search_data_jo : jo.get_array( "search_data" ) ) { data.emplace_back( search_data_jo ); @@ -5415,11 +5457,11 @@ talk_effect_fun_t::func f_run_inv_eocs( const JsonObject &jo, } talk_effect_fun_t::func f_map_run_item_eocs( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { str_or_var option = get_str_or_var( jo.get_member( member ), member ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); std::vector data; for( const JsonValue &search_data_jo : jo.get_array( "search_data" ) ) { data.emplace_back( search_data_jo ); @@ -5495,7 +5537,8 @@ talk_effect_fun_t::func f_map_run_item_eocs( const JsonObject &jo, std::string_v }; } -talk_effect_fun_t::func f_set_talker( const JsonObject &jo, std::string_view member, bool is_npc ) +talk_effect_fun_t::func f_set_talker( const JsonObject &jo, std::string_view member, + const std::string_view, bool is_npc ) { var_info var = read_var_info( jo.get_object( member ) ); var_type type = var.type; @@ -5524,9 +5567,10 @@ void process_eoc( const effect_on_condition_id &eoc, dialogue &d, } } -talk_effect_fun_t::func f_queue_eocs( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_queue_eocs( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - std::vector eocs_entries = load_eoc_vector_id_and_var( jo, member ); + std::vector eocs_entries = load_eoc_vector_id_and_var( jo, member, src ); if( eocs_entries.empty() ) { jo.throw_error( "Invalid input for queue_eocs" ); } @@ -5543,9 +5587,10 @@ talk_effect_fun_t::func f_queue_eocs( const JsonObject &jo, std::string_view mem }; } -talk_effect_fun_t::func f_queue_eoc_with( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_queue_eoc_with( const JsonObject &jo, std::string_view member, + const std::string_view src ) { - effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), "" ); + effect_on_condition_id eoc = effect_on_conditions::load_inline_eoc( jo.get_member( member ), src ); std::unordered_map context; if( jo.has_object( "variables" ) ) { @@ -5582,7 +5627,7 @@ talk_effect_fun_t::func f_queue_eoc_with( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_weighted_list_eocs( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view src ) { std::vector> eoc_pairs; for( JsonArray ja : jo.get_array( member ) ) { @@ -5593,7 +5638,7 @@ talk_effect_fun_t::func f_weighted_list_eocs( const JsonObject &jo, } else { eoc_weight.min = get_dbl_or_var_part( ja.next_value(), member ); } - eoc_pairs.emplace_back( effect_on_conditions::load_inline_eoc( eoc, "" ), + eoc_pairs.emplace_back( effect_on_conditions::load_inline_eoc( eoc, src ), eoc_weight ); } return [eoc_pairs]( dialogue & d ) { @@ -5608,15 +5653,16 @@ talk_effect_fun_t::func f_weighted_list_eocs( const JsonObject &jo, }; } -talk_effect_fun_t::func f_if( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_if( const JsonObject &jo, std::string_view member, + const std::string_view src ) { std::function cond; talk_effect_t then_effect; talk_effect_t else_effect; read_condition( jo, std::string( member ), cond, false ); - then_effect.load_effect( jo, "then" ); + then_effect.load_effect( jo, "then", src ); if( jo.has_member( "else" ) || jo.has_array( "else" ) ) { - else_effect.load_effect( jo, "else" ); + else_effect.load_effect( jo, "else", src ); } return [cond, then_effect, else_effect]( dialogue & d ) { @@ -5628,14 +5674,15 @@ talk_effect_fun_t::func f_if( const JsonObject &jo, std::string_view member ) }; } -talk_effect_fun_t::func f_switch( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_switch( const JsonObject &jo, std::string_view member, + const std::string_view src ) { dbl_or_var eoc_switch = get_dbl_or_var( jo, member ); std::vector> case_pairs; for( const JsonValue jv : jo.get_array( "cases" ) ) { JsonObject array_case = jv.get_object(); talk_effect_t case_effect; - case_effect.load_effect( array_case, "effect" ); + case_effect.load_effect( array_case, "effect", src ); case_pairs.emplace_back( get_dbl_or_var( array_case, "case" ), case_effect ); } return [eoc_switch, case_pairs]( dialogue & d ) { @@ -5651,12 +5698,13 @@ talk_effect_fun_t::func f_switch( const JsonObject &jo, std::string_view member }; } -talk_effect_fun_t::func f_foreach( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_foreach( const JsonObject &jo, std::string_view member, + const std::string_view src ) { std::string type = jo.get_string( member.data() ); var_info itr = read_var_info( jo.get_object( "var" ) ); talk_effect_t effect; - effect.load_effect( jo, "effect" ); + effect.load_effect( jo, "effect", src ); std::string target; std::vector array; if( jo.has_string( "target" ) ) { @@ -5711,7 +5759,7 @@ talk_effect_fun_t::func f_foreach( const JsonObject &jo, std::string_view member } talk_effect_fun_t::func f_roll_remainder( const JsonObject &jo, - std::string_view member, bool is_npc ) + std::string_view member, const std::string_view src, bool is_npc ) { std::vector list; for( JsonValue jv : jo.get_array( member ) ) { @@ -5724,8 +5772,8 @@ talk_effect_fun_t::func f_roll_remainder( const JsonObject &jo, } else { message.str_val = translation(); } - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [list, type, is_npc, true_eocs, false_eocs, message]( dialogue const & d ) { std::vector not_had; @@ -5788,7 +5836,7 @@ talk_effect_fun_t::func f_roll_remainder( const JsonObject &jo, } talk_effect_fun_t::func f_add_morale( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_type = get_str_or_var( jo.get_member( member ), member, true ); dbl_or_var dov_bonus = get_dbl_or_var( jo, "bonus" ); @@ -5808,7 +5856,7 @@ talk_effect_fun_t::func f_add_morale( const JsonObject &jo, std::string_view mem } talk_effect_fun_t::func f_lose_morale( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var old_morale = get_str_or_var( jo.get_member( member ), member, true ); return [is_npc, old_morale]( dialogue const & d ) { @@ -5816,7 +5864,8 @@ talk_effect_fun_t::func f_lose_morale( const JsonObject &jo, std::string_view me }; } -talk_effect_fun_t::func f_add_faction_trust( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_add_faction_trust( const JsonObject &jo, std::string_view member, + const std::string_view ) { dbl_or_var dov = get_dbl_or_var( jo, member ); return [dov]( dialogue & d ) { @@ -5825,7 +5874,7 @@ talk_effect_fun_t::func f_add_faction_trust( const JsonObject &jo, std::string_v } talk_effect_fun_t::func f_lose_faction_trust( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { dbl_or_var dov = get_dbl_or_var( jo, member ); return [dov]( dialogue & d ) { @@ -5834,7 +5883,7 @@ talk_effect_fun_t::func f_lose_faction_trust( const JsonObject &jo, } talk_effect_fun_t::func f_custom_light_level( const JsonObject &jo, - std::string_view member ) + std::string_view member, const std::string_view ) { dbl_or_var dov = get_dbl_or_var( jo, member, true ); duration_or_var dov_length = get_duration_or_var( jo, "length", false, 0_seconds ); @@ -5852,7 +5901,8 @@ talk_effect_fun_t::func f_custom_light_level( const JsonObject &jo, }; } -talk_effect_fun_t::func f_give_equipment( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_give_equipment( const JsonObject &jo, std::string_view member, + const std::string_view ) { JsonObject jobj = jo.get_object( member ); int allowance = 0; @@ -5883,7 +5933,7 @@ talk_effect_fun_t::func f_give_equipment( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_spawn_monster( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { bool group = jo.get_bool( "group", false ); bool single_target = jo.get_bool( "single_target", false ); @@ -5912,8 +5962,8 @@ talk_effect_fun_t::func f_spawn_monster( const JsonObject &jo, std::string_view jo.read( "spawn_message", spawn_message ); translation spawn_message_plural; jo.read( "spawn_message_plural", spawn_message_plural ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [monster_id, dov_target_range, dov_hallucination_count, dov_real_count, dov_min_radius, dov_max_radius, outdoor_only, indoor_only, group, single_target, dov_lifespan, target_var, spawn_message, spawn_message_plural, true_eocs, false_eocs, open_air_allowed, temporary_drop_items, @@ -6063,7 +6113,7 @@ talk_effect_fun_t::func f_spawn_monster( const JsonObject &jo, std::string_view } talk_effect_fun_t::func f_spawn_npc( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view src, bool is_npc ) { str_or_var sov_npc_class = get_str_or_var( jo.get_member( member ), member ); str_or_var unique_id; @@ -6099,8 +6149,8 @@ talk_effect_fun_t::func f_spawn_npc( const JsonObject &jo, std::string_view memb jo.read( "spawn_message", spawn_message ); translation spawn_message_plural; jo.read( "spawn_message_plural", spawn_message_plural ); - std::vector true_eocs = load_eoc_vector( jo, "true_eocs" ); - std::vector false_eocs = load_eoc_vector( jo, "false_eocs" ); + std::vector true_eocs = load_eoc_vector( jo, "true_eocs", src ); + std::vector false_eocs = load_eoc_vector( jo, "false_eocs", src ); return [sov_npc_class, unique_id, traits, dov_hallucination_count, dov_real_count, dov_min_radius, dov_max_radius, outdoor_only, indoor_only, dov_lifespan, target_var, spawn_message, @@ -6177,7 +6227,7 @@ talk_effect_fun_t::func f_spawn_npc( const JsonObject &jo, std::string_view memb } talk_effect_fun_t::func f_field( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { str_or_var new_field = get_str_or_var( jo.get_member( member ), member, true ); dbl_or_var dov_intensity = get_dbl_or_var( jo, "intensity", false, 1 ); @@ -6214,7 +6264,7 @@ talk_effect_fun_t::func f_field( const JsonObject &jo, std::string_view member, } talk_effect_fun_t::func f_teleport( const JsonObject &jo, std::string_view member, - bool is_npc ) + const std::string_view, bool is_npc ) { std::optional target_var = read_var_info( jo.get_object( member ) ); translation_or_var fail_message; @@ -6268,7 +6318,8 @@ talk_effect_fun_t::func f_wants_to_talk( bool is_npc ) }; } -talk_effect_fun_t::func f_trigger_event( const JsonObject &jo, std::string_view member ) +talk_effect_fun_t::func f_trigger_event( const JsonObject &jo, std::string_view member, + const std::string_view ) { std::string const type_str = jo.get_string( member.data() ); JsonArray const &jargs = jo.get_array( "args" ); @@ -6376,11 +6427,12 @@ void talk_effect_t::update_missions( dialogue &d ) } } -talk_effect_t::talk_effect_t( const JsonObject &jo, const std::string &member_name ) +talk_effect_t::talk_effect_t( const JsonObject &jo, const std::string &member_name, + const std::string_view src ) { - load_effect( jo, member_name ); + load_effect( jo, member_name, src ); if( jo.has_object( "topic" ) ) { - next_topic = load_inline_topic( jo.get_object( "topic" ) ); + next_topic = load_inline_topic( jo.get_object( "topic" ), src ); } else if( jo.has_string( "topic" ) ) { next_topic = talk_topic( jo.get_string( "topic" ) ); } @@ -6494,26 +6546,27 @@ parsers = { { "transform_item", jarg::member, &talk_effect_fun::f_transform_item }, }; -void talk_effect_t::parse_sub_effect( const JsonObject &jo ) +void talk_effect_t::parse_sub_effect( const JsonObject &jo, const std::string_view src ) { for( const sub_effect_parser &p : parsers ) { if( p.has_beta ) { if( p.check( jo ) ) { - set_effect( p.f( jo, p.key_alpha, false ) ); + set_effect( p.f( jo, p.key_alpha, src, false ) ); return; } else if( p.check( jo, true ) ) { - set_effect( p.f( jo, p.key_beta, true ) ); + set_effect( p.f( jo, p.key_beta, src, true ) ); return; } } else if( p.check( jo ) ) { - set_effect( p.f( jo, p.key_alpha, false ) ); + set_effect( p.f( jo, p.key_alpha, src, false ) ); return; } } jo.throw_error( "invalid sub effect syntax: " + jo.str() ); } -void talk_effect_t::parse_string_effect( const std::string &effect_id, const JsonObject &jo ) +void talk_effect_t::parse_string_effect( const std::string &effect_id, const JsonObject &jo, + const std::string_view src ) { static const std::unordered_map static_functions_map = { { @@ -6613,7 +6666,8 @@ void talk_effect_t::parse_string_effect( const std::string &effect_id, const Jso if( effect_id == "u_bulk_trade_accept" || effect_id == "npc_bulk_trade_accept" || effect_id == "u_bulk_donate" || effect_id == "npc_bulk_donate" ) { bool is_npc = effect_id == "npc_bulk_trade_accept" || effect_id == "npc_bulk_donate"; - set_effect( talk_effect_fun_t( talk_effect_fun::f_bulk_trade_accept( jo, effect_id, is_npc ) ) ); + set_effect( talk_effect_fun_t( talk_effect_fun::f_bulk_trade_accept( jo, effect_id, src, + is_npc ) ) ); return; } @@ -6654,11 +6708,11 @@ void talk_effect_t::parse_string_effect( const std::string &effect_id, const Jso } if( effect_id == "open_dialogue" ) { - set_effect( talk_effect_fun_t( talk_effect_fun::f_open_dialogue( jo, "" ) ) ); + set_effect( talk_effect_fun_t( talk_effect_fun::f_open_dialogue( jo, "", src ) ) ); return; } if( effect_id == "take_control" ) { - set_effect( talk_effect_fun_t( talk_effect_fun::f_take_control( jo, "" ) ) ); + set_effect( talk_effect_fun_t( talk_effect_fun::f_take_control( jo, "", src ) ) ); return; } if( effect_id == "take_control_menu" ) { @@ -6676,7 +6730,8 @@ void talk_effect_t::parse_string_effect( const std::string &effect_id, const Jso jo.throw_error_at( effect_id, "unknown effect string" ); } -void talk_effect_t::load_effect( const JsonObject &jo, const std::string &member_name ) +void talk_effect_t::load_effect( const JsonObject &jo, const std::string &member_name, + const std::string_view src ) { if( jo.has_member( "opinion" ) ) { JsonValue jv = jo.get_member( "opinion" ); @@ -6692,18 +6747,18 @@ void talk_effect_t::load_effect( const JsonObject &jo, const std::string &member return; } else if( jo.has_string( member_name ) ) { const std::string type = jo.get_string( member_name ); - parse_string_effect( type, jo ); + parse_string_effect( type, jo, src ); } else if( jo.has_object( member_name ) ) { JsonObject sub_effect = jo.get_object( member_name ); - parse_sub_effect( sub_effect ); + parse_sub_effect( sub_effect, src ); } else if( jo.has_array( member_name ) ) { for( const JsonValue entry : jo.get_array( member_name ) ) { if( entry.test_string() ) { const std::string type = entry.get_string(); - parse_string_effect( type, jo ); + parse_string_effect( type, jo, src ); } else if( entry.test_object() ) { JsonObject sub_effect = entry.get_object(); - parse_sub_effect( sub_effect ); + parse_sub_effect( sub_effect, src ); } else { jo.throw_error_at( member_name, "invalid effect array syntax" ); } @@ -6729,7 +6784,7 @@ talk_response::talk_response() dialogue_spell = spell_id(); } -talk_response::talk_response( const JsonObject &jo ) +talk_response::talk_response( const JsonObject &jo, const std::string_view src ) { if( jo.has_member( "truefalsetext" ) ) { JsonObject truefalse_jo = jo.get_object( "truefalsetext" ); @@ -6748,20 +6803,20 @@ talk_response::talk_response( const JsonObject &jo ) } if( jo.has_member( "success" ) ) { JsonObject success_obj = jo.get_object( "success" ); - success = talk_effect_t( success_obj, "effect" ); + success = talk_effect_t( success_obj, "effect", src ); } else if( jo.has_string( "topic" ) ) { // This is for simple topic switching without a possible failure success.next_topic = talk_topic( jo.get_string( "topic" ) ); - success.load_effect( jo, "effect" ); + success.load_effect( jo, "effect", src ); } else if( jo.has_object( "topic" ) ) { - success.next_topic = load_inline_topic( jo.get_object( "topic" ) ); + success.next_topic = load_inline_topic( jo.get_object( "topic" ), src ); } if( trial && !jo.has_member( "failure" ) ) { jo.throw_error( "the failure effect is mandatory if a talk_trial has been defined" ); } if( jo.has_member( "failure" ) ) { JsonObject failure_obj = jo.get_object( "failure" ); - failure = talk_effect_t( failure_obj, "effect" ); + failure = talk_effect_t( failure_obj, "effect", src ); } // TODO: mission_selected @@ -6769,7 +6824,8 @@ talk_response::talk_response( const JsonObject &jo ) // TODO: style } -json_talk_repeat_response::json_talk_repeat_response( const JsonObject &jo ) +json_talk_repeat_response::json_talk_repeat_response( const JsonObject &jo, + const std::string_view src ) { if( jo.has_bool( "is_npc" ) ) { is_npc = true; @@ -6797,19 +6853,19 @@ json_talk_repeat_response::json_talk_repeat_response( const JsonObject &jo ) } if( jo.has_object( "response" ) ) { JsonObject response_obj = jo.get_object( "response" ); - response = json_talk_response( response_obj ); + response = json_talk_response( response_obj, src ); } else { jo.throw_error( "Repeat response with no response!" ); } } -json_talk_response::json_talk_response( const JsonObject &jo ) - : actual_response( jo ) +json_talk_response::json_talk_response( const JsonObject &jo, const std::string_view src ) + : actual_response( jo, src ) { - load_condition( jo ); + load_condition( jo, src ); } -void json_talk_response::load_condition( const JsonObject &jo ) +void json_talk_response::load_condition( const JsonObject &jo, const std::string_view ) { has_condition_ = jo.has_member( "condition" ); is_switch = jo.get_bool( "switch", false ); @@ -7062,11 +7118,11 @@ dynamic_line_t::dynamic_line_t( const JsonArray &ja ) } json_dynamic_line_effect::json_dynamic_line_effect( const JsonObject &jo, - const std::string &id ) + const std::string &id, const std::string_view src ) { std::function tmp_condition; read_condition( jo, "condition", tmp_condition, true ); - talk_effect_t tmp_effect = talk_effect_t( jo, "effect" ); + talk_effect_t tmp_effect = talk_effect_t( jo, "effect", src ); // if the topic has a sentinel, it means implicitly add a check for the sentinel value // and do not run the effects if it is set. if it is not set, run the effects and // set the sentinel @@ -7096,7 +7152,7 @@ void json_dynamic_line_effect::apply( dialogue &d ) const effect.apply( d ); } -void json_talk_topic::load( const JsonObject &jo ) +void json_talk_topic::load( const JsonObject &jo, const std::string_view src ) { if( jo.has_member( "dynamic_line" ) ) { dynamic_line = dynamic_line_t::from_member( jo, "dynamic_line" ); @@ -7110,10 +7166,10 @@ void json_talk_topic::load( const JsonObject &jo ) } if( jo.has_object( "speaker_effect" ) ) { JsonObject speaker_effect = jo.get_object( "speaker_effect" ); - speaker_effects.emplace_back( speaker_effect, id ); + speaker_effects.emplace_back( speaker_effect, id, src ); } else if( jo.has_array( "speaker_effect" ) ) { for( JsonObject speaker_effect : jo.get_array( "speaker_effect" ) ) { - speaker_effects.emplace_back( speaker_effect, id ); + speaker_effects.emplace_back( speaker_effect, id, src ); } } } @@ -7123,7 +7179,7 @@ void json_talk_topic::load( const JsonObject &jo ) } if( !insert_above_bottom || responses.empty() ) { for( JsonObject response : jo.get_array( "responses" ) ) { - responses.emplace_back( response ); + responses.emplace_back( response, src ); } } else { int dec_count = 0; @@ -7136,14 +7192,14 @@ void json_talk_topic::load( const JsonObject &jo ) dec_count = 2; } for( JsonObject response : jo.get_array( "responses" ) ) { - responses.emplace( responses.end() - dec_count, response ); + responses.emplace( responses.end() - dec_count, response, src ); } } if( jo.has_object( "repeat_responses" ) ) { - repeat_responses.emplace_back( jo.get_object( "repeat_responses" ) ); + repeat_responses.emplace_back( jo.get_object( "repeat_responses" ), src ); } else if( jo.has_array( "repeat_responses" ) ) { for( JsonObject elem : jo.get_array( "repeat_responses" ) ) { - repeat_responses.emplace_back( elem ); + repeat_responses.emplace_back( elem, src ); } } if( responses.empty() ) { @@ -7231,15 +7287,15 @@ void unload_talk_topics() json_talk_topics.clear(); } -void load_talk_topic( const JsonObject &jo ) +void load_talk_topic( const JsonObject &jo, const std::string_view src ) { if( jo.has_array( "id" ) ) { for( auto &id : jo.get_string_array( "id" ) ) { - json_talk_topics[id].load( jo ); + json_talk_topics[id].load( jo, src ); } } else { const std::string id = jo.get_string( "id" ); - json_talk_topics[id].load( jo ); + json_talk_topics[id].load( jo, src ); } } diff --git a/src/text_snippets.cpp b/src/text_snippets.cpp index 6ed5e5a834f97..24f81e83e5c4a 100644 --- a/src/text_snippets.cpp +++ b/src/text_snippets.cpp @@ -74,7 +74,7 @@ void snippet_library::add_snippet_from_json( const std::string &category, const ids.emplace_back( weighted_id{ weight_acc, id } ); snippets_by_id[id] = text; if( jo.has_member( "effect_on_examine" ) ) { - EOC_by_id[id] = talk_effect_t( jo, "effect_on_examine" ); + EOC_by_id[id] = talk_effect_t( jo, "effect_on_examine", "" ); } translation name; optional( jo, false, "name", name ); From de53e81f979bd210c4399a2c8b664ef05f2c2b1e Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:33 +0000 Subject: [PATCH 2/8] text snippets track src snippets can load eocs, and the eocs should have a src defined. --- src/init.cpp | 4 ++-- src/item_factory.cpp | 2 +- src/text_snippets.cpp | 16 +++++++++------- src/text_snippets.h | 8 +++++--- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 76ff135154a96..0bb49026b1952 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -301,8 +301,8 @@ void DynamicDataLoader::initialize() // json/colors.json would be listed here, but it's loaded before the others (see init_colors()) // Non Static Function Access - add( "snippet", []( const JsonObject & jo ) { - SNIPPET.load_snippet( jo ); + add( "snippet", []( const JsonObject & jo, const std::string & src ) { + SNIPPET.load_snippet( jo, src ); } ); add( "item_group", []( const JsonObject & jo ) { item_controller->load_item_group( jo ); diff --git a/src/item_factory.cpp b/src/item_factory.cpp index 5f75230722fcb..c2aee4fcdc9d4 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -4492,7 +4492,7 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: // auto-create a category that is unlikely to already be used and put the // snippets in it. def.snippet_category = "auto:" + def.id.str(); - SNIPPET.add_snippets_from_json( def.snippet_category, jo.get_array( "snippet_category" ) ); + SNIPPET.add_snippets_from_json( def.snippet_category, jo.get_array( "snippet_category" ), src ); } else { def.snippet_category = jo.get_string( "snippet_category", "" ); } diff --git a/src/text_snippets.cpp b/src/text_snippets.cpp index 24f81e83e5c4a..10a9eef1a4b4a 100644 --- a/src/text_snippets.cpp +++ b/src/text_snippets.cpp @@ -14,7 +14,7 @@ snippet_library SNIPPET; -void snippet_library::load_snippet( const JsonObject &jsobj ) +void snippet_library::load_snippet( const JsonObject &jsobj, const std::string &src ) { if( hash_to_id_migration.has_value() ) { debugmsg( "snippet_library::load_snippet called after snippet_library::migrate_hash_to_id." ); @@ -22,13 +22,14 @@ void snippet_library::load_snippet( const JsonObject &jsobj ) hash_to_id_migration = std::nullopt; const std::string category = jsobj.get_string( "category" ); if( jsobj.has_array( "text" ) ) { - add_snippets_from_json( category, jsobj.get_array( "text" ) ); + add_snippets_from_json( category, jsobj.get_array( "text" ), src ); } else { - add_snippet_from_json( category, jsobj ); + add_snippet_from_json( category, jsobj, src ); } } -void snippet_library::add_snippets_from_json( const std::string &category, const JsonArray &jarr ) +void snippet_library::add_snippets_from_json( const std::string &category, const JsonArray &jarr, + const std::string &src ) { if( hash_to_id_migration.has_value() ) { debugmsg( "snippet_library::add_snippets_from_json called after snippet_library::migrate_hash_to_id." ); @@ -45,12 +46,13 @@ void snippet_library::add_snippets_from_json( const std::string &category, const no_id.emplace_back( weighted_translation{ weight_acc, text } ); } else { JsonObject jo = entry.get_object(); - add_snippet_from_json( category, jo ); + add_snippet_from_json( category, jo, src ); } } } -void snippet_library::add_snippet_from_json( const std::string &category, const JsonObject &jo ) +void snippet_library::add_snippet_from_json( const std::string &category, const JsonObject &jo, + const std::string &src ) { if( hash_to_id_migration.has_value() ) { debugmsg( "snippet_library::add_snippet_from_json called after snippet_library::migrate_hash_to_id." ); @@ -74,7 +76,7 @@ void snippet_library::add_snippet_from_json( const std::string &category, const ids.emplace_back( weighted_id{ weight_acc, id } ); snippets_by_id[id] = text; if( jo.has_member( "effect_on_examine" ) ) { - EOC_by_id[id] = talk_effect_t( jo, "effect_on_examine", "" ); + EOC_by_id[id] = talk_effect_t( jo, "effect_on_examine", src ); } translation name; optional( jo, false, "name", name ); diff --git a/src/text_snippets.h b/src/text_snippets.h index 8a94fc14e9179..bec4ca2fa59e4 100644 --- a/src/text_snippets.h +++ b/src/text_snippets.h @@ -23,20 +23,22 @@ class snippet_library /** * Load snippet from the standalone entry, used by the @ref DynamicDataLoader. */ - void load_snippet( const JsonObject &jsobj ); + void load_snippet( const JsonObject &jsobj, const std::string &src ); /** * Load all snippet definitions in the json array into given category. * Entries in the array can be simple strings, or json objects (for the * later see add_snippet_from_json). */ - void add_snippets_from_json( const std::string &category, const JsonArray &jarr ); + void add_snippets_from_json( const std::string &category, const JsonArray &jarr, + const std::string &src ); /** * Load a single snippet text from the json object. The object should have * a "text" member with the text of the snippet. * A "id" member is optional and if present gives the snippet text a id, * stored in snippets_by_id. */ - void add_snippet_from_json( const std::string &category, const JsonObject &jo ); + void add_snippet_from_json( const std::string &category, const JsonObject &jo, + const std::string &src ); /** * Load name list from name.h/cpp */ From 6a3ae63de49156d14ff78d0b111cbace67034ed8 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:38 +0000 Subject: [PATCH 3/8] damage_types track src Damage types have eocs, and right now they're just pretending they don't have a src. Properly write it through. --- src/damage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/damage.cpp b/src/damage.cpp index 010119be717a7..6fda13eb70975 100644 --- a/src/damage.cpp +++ b/src/damage.cpp @@ -112,7 +112,7 @@ static damage_info_order::info_disp read_info_disp( const std::string &s ) } } -void damage_type::load( const JsonObject &jo, std::string_view ) +void damage_type::load( const JsonObject &jo, std::string_view src ) { mandatory( jo, was_loaded, "name", name ); optional( jo, was_loaded, "skill", skill, skill_id::NULL_ID() ); @@ -151,11 +151,11 @@ void damage_type::load( const JsonObject &jo, std::string_view ) } for( JsonValue jv : jo.get_array( "onhit_eocs" ) ) { - onhit_eocs.push_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + onhit_eocs.push_back( effect_on_conditions::load_inline_eoc( jv, std::string( src ) ) ); } for( JsonValue jv : jo.get_array( "ondamage_eocs" ) ) { - ondamage_eocs.push_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + ondamage_eocs.push_back( effect_on_conditions::load_inline_eoc( jv, std::string( src ) ) ); } } From 9aa95220d2a54e4b06828806e64bd8a006a2f0d7 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:42 +0000 Subject: [PATCH 4/8] iexamine actors track src The eoc iexamine actor can obviously load eocs, and so requires a src. --- src/iexamine.h | 2 +- src/iexamine_actors.cpp | 8 ++++---- src/iexamine_actors.h | 6 +++--- src/mapdata.cpp | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/iexamine.h b/src/iexamine.h index 2806f303c5f09..d884de63c2fd8 100644 --- a/src/iexamine.h +++ b/src/iexamine.h @@ -29,7 +29,7 @@ struct iexamine_actor { explicit iexamine_actor( const std::string &type ) : type( type ) {} - virtual void load( const JsonObject & ) = 0; + virtual void load( const JsonObject &, const std::string & ) = 0; virtual void call( Character &, const tripoint & ) const = 0; virtual void finalize() const = 0; diff --git a/src/iexamine_actors.cpp b/src/iexamine_actors.cpp index de9deaaf1e354..3b0218d173358 100644 --- a/src/iexamine_actors.cpp +++ b/src/iexamine_actors.cpp @@ -16,7 +16,7 @@ static const ter_str_id ter_t_door_metal_c( "t_door_metal_c" ); static const ter_str_id ter_t_door_metal_locked( "t_door_metal_locked" ); -void appliance_convert_examine_actor::load( const JsonObject &jo ) +void appliance_convert_examine_actor::load( const JsonObject &jo, const std::string & ) { optional( jo, false, "furn_set", furn_set ); optional( jo, false, "ter_set", ter_set ); @@ -193,7 +193,7 @@ void cardreader_examine_actor::call( Character &you, const tripoint &examp ) con } } -void cardreader_examine_actor::load( const JsonObject &jo ) +void cardreader_examine_actor::load( const JsonObject &jo, const std::string & ) { mandatory( jo, false, "flags", allowed_flags ); optional( jo, false, "consume_card", consume, true ); @@ -257,10 +257,10 @@ void eoc_examine_actor::call( Character &you, const tripoint &examp ) const } } -void eoc_examine_actor::load( const JsonObject &jo ) +void eoc_examine_actor::load( const JsonObject &jo, const std::string &src ) { for( JsonValue jv : jo.get_array( "effect_on_conditions" ) ) { - eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, src ) ); } } diff --git a/src/iexamine_actors.h b/src/iexamine_actors.h index 3ec29e6fc3b78..2cfa9990dc7d8 100644 --- a/src/iexamine_actors.h +++ b/src/iexamine_actors.h @@ -20,7 +20,7 @@ class appliance_convert_examine_actor : public iexamine_actor explicit appliance_convert_examine_actor( const std::string &type = "appliance_convert" ) : iexamine_actor( type ) {} - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; void call( Character &you, const tripoint &examp ) const override; void finalize() const override; @@ -60,7 +60,7 @@ class cardreader_examine_actor : public iexamine_actor explicit cardreader_examine_actor( const std::string &type = "cardreader" ) : iexamine_actor( type ) {} - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; void call( Character &you, const tripoint &examp ) const override; void finalize() const override; @@ -75,7 +75,7 @@ class eoc_examine_actor : public iexamine_actor explicit eoc_examine_actor( const std::string &type = "effect_on_condition" ) : iexamine_actor( type ) {} - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string &src ) override; void call( Character &you, const tripoint &examp ) const override; void finalize() const override; diff --git a/src/mapdata.cpp b/src/mapdata.cpp index 3872a50a7c7c5..2a4a0085d4afe 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -822,7 +822,7 @@ void init_mapdata() add_actor( std::make_unique() ); } -void map_data_common_t::load( const JsonObject &jo, const std::string & ) +void map_data_common_t::load( const JsonObject &jo, const std::string &src ) { if( jo.has_string( "examine_action" ) ) { examine_actor = nullptr; @@ -830,7 +830,7 @@ void map_data_common_t::load( const JsonObject &jo, const std::string & ) } else if( jo.has_object( "examine_action" ) ) { JsonObject data = jo.get_object( "examine_action" ); examine_actor = iexamine_actor_from_jsobj( data ); - examine_actor->load( data ); + examine_actor->load( data, src ); examine_func = iexamine_functions_from_string( "invalid" ); } else if( !was_loaded ) { examine_actor = nullptr; From a64ed3d8fb08422c2cf62624db30fa4c1930ec81 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:45 +0000 Subject: [PATCH 5/8] iuse actors track src The eoc iuse actor loads eocs, and those eocs should have src values. --- src/item_factory.cpp | 24 +++++++------ src/item_factory.h | 8 +++-- src/iuse.h | 2 +- src/iuse_actor.cpp | 80 +++++++++++++++++++++--------------------- src/iuse_actor.h | 82 ++++++++++++++++++++++---------------------- 5 files changed, 100 insertions(+), 96 deletions(-) diff --git a/src/item_factory.cpp b/src/item_factory.cpp index c2aee4fcdc9d4..d7987d7c55c9f 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -1654,7 +1654,7 @@ class iuse_function_wrapper : public iuse_actor return std::make_unique( *this ); } - void load( const JsonObject & ) override {} + void load( const JsonObject &, const std::string & ) override {} }; class iuse_function_wrapper_with_info : public iuse_function_wrapper @@ -4395,8 +4395,8 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: } } - set_use_methods_from_json( jo, "use_action", def.use_methods, def.ammo_scale ); - set_use_methods_from_json( jo, "tick_action", def.tick_action, def.ammo_scale ); + set_use_methods_from_json( jo, src, "use_action", def.use_methods, def.ammo_scale ); + set_use_methods_from_json( jo, src, "tick_action", def.tick_action, def.ammo_scale ); assign( jo, "countdown_interval", def.countdown_interval ); assign( jo, "revert_to", def.revert_to, strict ); @@ -4406,7 +4406,7 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: } else if( jo.has_object( "countdown_action" ) ) { JsonObject tmp = jo.get_object( "countdown_action" ); - use_function fun = usage_from_object( tmp ).second; + use_function fun = usage_from_object( tmp, src ).second; if( fun ) { def.countdown_action = fun; } @@ -4417,7 +4417,7 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: } else if( jo.has_object( "drop_action" ) ) { JsonObject tmp = jo.get_object( "drop_action" ); - use_function fun = usage_from_object( tmp ).second; + use_function fun = usage_from_object( tmp, src ).second; if( fun ) { def.drop_action = fun; } @@ -5189,8 +5189,9 @@ void Item_factory::load_item_group_data( const JsonObject &jsobj, Item_group *ig } } -void Item_factory::set_use_methods_from_json( const JsonObject &jo, const std::string &member, - std::map &use_methods, std::map &ammo_scale ) +void Item_factory::set_use_methods_from_json( const JsonObject &jo, const std::string &src, + const std::string &member, std::map &use_methods, + std::map &ammo_scale ) { if( !jo.has_member( member ) ) { return; @@ -5205,7 +5206,7 @@ void Item_factory::set_use_methods_from_json( const JsonObject &jo, const std::s emplace_usage( use_methods, type ); } else if( entry.test_object() ) { JsonObject obj = entry.get_object(); - std::pair fun = usage_from_object( obj ); + std::pair fun = usage_from_object( obj, src ); if( fun.second ) { use_methods.insert( fun ); if( obj.has_int( "ammo_scale" ) ) { @@ -5229,7 +5230,7 @@ void Item_factory::set_use_methods_from_json( const JsonObject &jo, const std::s emplace_usage( use_methods, type ); } else if( jo.has_object( member ) ) { JsonObject obj = jo.get_object( member ); - std::pair fun = usage_from_object( obj ); + std::pair fun = usage_from_object( obj, src ); if( fun.second ) { use_methods.insert( fun ); if( obj.has_int( "ammo_scale" ) ) { @@ -5253,7 +5254,8 @@ void Item_factory::emplace_usage( std::map &container } } -std::pair Item_factory::usage_from_object( const JsonObject &obj ) +std::pair Item_factory::usage_from_object( const JsonObject &obj, + const std::string &src ) { std::string type = obj.get_string( "type" ); @@ -5271,7 +5273,7 @@ std::pair Item_factory::usage_from_object( const Json return std::make_pair( type, use_function() ); } - method.get_actor_ptr()->load( obj ); + method.get_actor_ptr()->load( obj, src ); return std::make_pair( type, method ); } diff --git a/src/item_factory.h b/src/item_factory.h index b6622d730095e..8a51f583a4d10 100644 --- a/src/item_factory.h +++ b/src/item_factory.h @@ -329,12 +329,14 @@ class Item_factory void emplace_usage( std::map &container, const std::string &iuse_id ); - void set_use_methods_from_json( const JsonObject &jo, const std::string &member, - std::map &use_methods, std::map &ammo_scale ); + void set_use_methods_from_json( const JsonObject &jo, const std::string &src, + const std::string &member, std::map &use_methods, + std::map &ammo_scale ); use_function usage_from_string( const std::string &type ) const; - std::pair usage_from_object( const JsonObject &obj ); + std::pair usage_from_object( const JsonObject &obj, + const std::string & ); /** * Helper function for Item_group loading diff --git a/src/iuse.h b/src/iuse.h index 523d8efc8aabe..010996399dead 100644 --- a/src/iuse.h +++ b/src/iuse.h @@ -285,7 +285,7 @@ class iuse_actor int cost; virtual ~iuse_actor() = default; - virtual void load( const JsonObject &jo ) = 0; + virtual void load( const JsonObject &jo, const std::string &src ) = 0; virtual std::optional use( Character *, item &, const tripoint & ) const = 0; virtual ret_val can_use( const Character &, const item &, const tripoint & ) const; virtual void info( const item &, std::vector & ) const {} diff --git a/src/iuse_actor.cpp b/src/iuse_actor.cpp index 59a2ce367396b..9021ccb9cfa96 100644 --- a/src/iuse_actor.cpp +++ b/src/iuse_actor.cpp @@ -168,7 +168,7 @@ std::unique_ptr iuse_transform::clone() const return std::make_unique( *this ); } -void iuse_transform::load( const JsonObject &obj ) +void iuse_transform::load( const JsonObject &obj, const std::string & ) { obj.read( "target", target, true ); @@ -484,7 +484,7 @@ std::unique_ptr unpack_actor::clone() const return std::make_unique( *this ); } -void unpack_actor::load( const JsonObject &obj ) +void unpack_actor::load( const JsonObject &obj, const std::string & ) { obj.read( "group", unpack_group ); obj.read( "items_fit", items_fit ); @@ -537,7 +537,7 @@ std::unique_ptr message_iuse::clone() const return std::make_unique( *this ); } -void message_iuse::load( const JsonObject &obj ) +void message_iuse::load( const JsonObject &obj, const std::string & ) { obj.read( "name", name ); obj.read( "message", message ); @@ -570,7 +570,7 @@ std::unique_ptr sound_iuse::clone() const return std::make_unique( *this ); } -void sound_iuse::load( const JsonObject &obj ) +void sound_iuse::load( const JsonObject &obj, const std::string & ) { obj.read( "name", name ); obj.read( "sound_message", sound_message ); @@ -625,7 +625,7 @@ static std::vector points_for_gas_cloud( const tripoint ¢er, int r return result; } -void explosion_iuse::load( const JsonObject &obj ) +void explosion_iuse::load( const JsonObject &obj, const std::string & ) { if( obj.has_object( "explosion" ) ) { JsonObject expl = obj.get_object( "explosion" ); @@ -717,7 +717,7 @@ static effect_data load_effect_data( const JsonObject &e ) bodypart_id( e.get_string( "bp", "bp_null" ) ), e.get_bool( "permanent", false ) ); } -void consume_drug_iuse::load( const JsonObject &obj ) +void consume_drug_iuse::load( const JsonObject &obj, const std::string & ) { obj.read( "activation_message", activation_message ); obj.read( "charges_needed", charges_needed ); @@ -855,9 +855,9 @@ std::unique_ptr delayed_transform_iuse::clone() const return std::make_unique( *this ); } -void delayed_transform_iuse::load( const JsonObject &obj ) +void delayed_transform_iuse::load( const JsonObject &obj, const std::string &src ) { - iuse_transform::load( obj ); + iuse_transform::load( obj, src ); obj.get_member( "not_ready_msg" ).read( not_ready_msg ); transform_age = obj.get_int( "transform_age" ); } @@ -883,7 +883,7 @@ std::unique_ptr place_monster_iuse::clone() const return std::make_unique( *this ); } -void place_monster_iuse::load( const JsonObject &obj ) +void place_monster_iuse::load( const JsonObject &obj, const std::string & ) { mtypeid = mtype_id( obj.get_string( "monster_id" ) ); obj.read( "friendly_msg", friendly_msg ); @@ -989,7 +989,7 @@ std::unique_ptr place_npc_iuse::clone() const return std::make_unique( *this ); } -void place_npc_iuse::load( const JsonObject &obj ) +void place_npc_iuse::load( const JsonObject &obj, const std::string & ) { npc_class_id = string_id( obj.get_string( "npc_class_id" ) ); obj.read( "summon_msg", summon_msg ); @@ -1069,7 +1069,7 @@ void deploy_furn_actor::info( const item &, std::vector &dump ) const } } -void deploy_furn_actor::load( const JsonObject &obj ) +void deploy_furn_actor::load( const JsonObject &obj, const std::string & ) { furn_type = furn_str_id( obj.get_string( "furn_type" ) ); } @@ -1170,7 +1170,7 @@ void deploy_appliance_actor::info( const item &, std::vector &dump ) c vpart_appliance_from_item( appliance_base )->name() ) ); } -void deploy_appliance_actor::load( const JsonObject &obj ) +void deploy_appliance_actor::load( const JsonObject &obj, const std::string & ) { mandatory( obj, false, "base", appliance_base ); } @@ -1194,7 +1194,7 @@ std::unique_ptr reveal_map_actor::clone() const return std::make_unique( *this ); } -void reveal_map_actor::load( const JsonObject &obj ) +void reveal_map_actor::load( const JsonObject &obj, const std::string & ) { radius = obj.get_int( "radius" ); obj.get_member( "message" ).read( message ); @@ -1257,7 +1257,7 @@ std::optional reveal_map_actor::use( Character *p, item &it, const tripoint return 0; } -void firestarter_actor::load( const JsonObject &obj ) +void firestarter_actor::load( const JsonObject &obj, const std::string & ) { moves_cost_fast = obj.get_int( "moves", moves_cost_fast ); moves_cost_slow = obj.get_int( "moves_slow", moves_cost_fast * 10 ); @@ -1457,7 +1457,7 @@ std::optional firestarter_actor::use( Character *p, item &it, return 0; } -void salvage_actor::load( const JsonObject &obj ) +void salvage_actor::load( const JsonObject &obj, const std::string & ) { assign( obj, "cost", cost ); assign( obj, "moves_per_part", moves_per_part ); @@ -1785,7 +1785,7 @@ void salvage_actor::cut_up( Character &p, item_location &cut ) const } } -void inscribe_actor::load( const JsonObject &obj ) +void inscribe_actor::load( const JsonObject &obj, const std::string & ) { assign( obj, "cost", cost ); assign( obj, "on_items", on_items ); @@ -1935,7 +1935,7 @@ std::optional inscribe_actor::use( Character *p, item &it, const tripoint & return std::nullopt; } -void fireweapon_off_actor::load( const JsonObject &obj ) +void fireweapon_off_actor::load( const JsonObject &obj, const std::string & ) { obj.read( "target_id", target_id, true ); obj.read( "success_message", success_message ); @@ -1991,7 +1991,7 @@ ret_val fireweapon_off_actor::can_use( const Character &p, const item &it, return ret_val::make_success(); } -void fireweapon_on_actor::load( const JsonObject &obj ) +void fireweapon_on_actor::load( const JsonObject &obj, const std::string & ) { obj.read( "noise_message", noise_message ); obj.get_member( "charges_extinguish_message" ).read( charges_extinguish_message ); @@ -2039,7 +2039,7 @@ std::optional fireweapon_on_actor::use( Character *p, item &it, return 1; } -void manualnoise_actor::load( const JsonObject &obj ) +void manualnoise_actor::load( const JsonObject &obj, const std::string & ) { obj.get_member( "use_message" ).read( use_message ); obj.read( "noise_message", noise_message ); @@ -2076,7 +2076,7 @@ ret_val manualnoise_actor::can_use( const Character &p, const item &it, return ret_val::make_success(); } -void play_instrument_iuse::load( const JsonObject & ) +void play_instrument_iuse::load( const JsonObject &, const std::string & ) { } @@ -2113,7 +2113,7 @@ std::unique_ptr musical_instrument_actor::clone() const return std::make_unique( *this ); } -void musical_instrument_actor::load( const JsonObject &obj ) +void musical_instrument_actor::load( const JsonObject &obj, const std::string & ) { speed_penalty = obj.get_int( "speed_penalty", 10 ); volume = obj.get_int( "volume" ); @@ -2261,7 +2261,7 @@ std::unique_ptr learn_spell_actor::clone() const return std::make_unique( *this ); } -void learn_spell_actor::load( const JsonObject &obj ) +void learn_spell_actor::load( const JsonObject &obj, const std::string & ) { spells = obj.get_string_array( "spells" ); } @@ -2404,7 +2404,7 @@ std::unique_ptr cast_spell_actor::clone() const return std::make_unique( *this ); } -void cast_spell_actor::load( const JsonObject &obj ) +void cast_spell_actor::load( const JsonObject &obj, const std::string & ) { no_fail = obj.get_bool( "no_fail" ); item_spell = spell_id( obj.get_string( "spell_id" ) ); @@ -2478,7 +2478,7 @@ std::unique_ptr holster_actor::clone() const return std::make_unique( *this ); } -void holster_actor::load( const JsonObject &obj ) +void holster_actor::load( const JsonObject &obj, const std::string & ) { obj.read( "holster_prompt", holster_prompt ); obj.read( "holster_msg", holster_msg ); @@ -2633,7 +2633,7 @@ std::unique_ptr ammobelt_actor::clone() const return std::make_unique( *this ); } -void ammobelt_actor::load( const JsonObject &obj ) +void ammobelt_actor::load( const JsonObject &obj, const std::string & ) { belt = itype_id( obj.get_string( "belt" ) ); } @@ -2665,7 +2665,7 @@ std::optional ammobelt_actor::use( Character *p, item &, const tripoint & ) return 0; } -void repair_item_actor::load( const JsonObject &obj ) +void repair_item_actor::load( const JsonObject &obj, const std::string & ) { // Mandatory: for( const std::string line : obj.get_array( "materials" ) ) { @@ -3259,7 +3259,7 @@ std::string repair_item_actor::get_description() const return string_format( _( "Repair %s" ), mats ); } -void heal_actor::load( const JsonObject &obj ) +void heal_actor::load( const JsonObject &obj, const std::string & ) { // Mandatory move_cost = obj.get_int( "move_cost" ); @@ -3770,7 +3770,7 @@ void place_trap_actor::data::load( const JsonObject &obj ) assign( obj, "moves", moves ); } -void place_trap_actor::load( const JsonObject &obj ) +void place_trap_actor::load( const JsonObject &obj, const std::string & ) { assign( obj, "allow_underwater", allow_underwater ); assign( obj, "allow_under_player", allow_under_player ); @@ -3937,7 +3937,7 @@ std::optional place_trap_actor::use( Character *p, item &it, const tripoint return 1; } -void emit_actor::load( const JsonObject &obj ) +void emit_actor::load( const JsonObject &obj, const std::string & ) { assign( obj, "emits", emits ); assign( obj, "scale_qty", scale_qty ); @@ -3977,7 +3977,7 @@ void emit_actor::finalize( const itype_id &my_item_type ) } } -void saw_barrel_actor::load( const JsonObject &jo ) +void saw_barrel_actor::load( const JsonObject &jo, const std::string & ) { assign( jo, "cost", cost ); } @@ -4038,7 +4038,7 @@ std::unique_ptr saw_barrel_actor::clone() const return std::make_unique( *this ); } -void saw_stock_actor::load( const JsonObject &jo ) +void saw_stock_actor::load( const JsonObject &jo, const std::string & ) { assign( jo, "cost", cost ); } @@ -4113,7 +4113,7 @@ std::unique_ptr saw_stock_actor::clone() const return std::make_unique( *this ); } -void molle_attach_actor::load( const JsonObject &jo ) +void molle_attach_actor::load( const JsonObject &jo, const std::string & ) { assign( jo, "size", size ); assign( jo, "moves", moves ); @@ -4180,7 +4180,7 @@ std::unique_ptr molle_detach_actor::clone() const return std::make_unique( *this ); } -void molle_detach_actor::load( const JsonObject &jo ) +void molle_detach_actor::load( const JsonObject &jo, const std::string & ) { assign( jo, "moves", moves ); } @@ -4423,7 +4423,7 @@ void modify_gunmods_actor::finalize( const itype_id &my_item_type ) } } -void link_up_actor::load( const JsonObject &jo ) +void link_up_actor::load( const JsonObject &jo, const std::string & ) { jo.read( "cable_length", cable_length ); jo.read( "charge_rate", charge_rate ); @@ -5148,7 +5148,7 @@ std::unique_ptr deploy_tent_actor::clone() const return std::make_unique( *this ); } -void deploy_tent_actor::load( const JsonObject &obj ) +void deploy_tent_actor::load( const JsonObject &obj, const std::string & ) { assign( obj, "radius", radius ); assign( obj, "wall", wall ); @@ -5253,7 +5253,7 @@ std::optional weigh_self_actor::use( Character *p, item &, const tripoint & return 0; } -void weigh_self_actor::load( const JsonObject &jo ) +void weigh_self_actor::load( const JsonObject &jo, const std::string & ) { assign( jo, "max_weight", max_weight ); } @@ -5263,7 +5263,7 @@ std::unique_ptr weigh_self_actor::clone() const return std::make_unique( *this ); } -void sew_advanced_actor::load( const JsonObject &obj ) +void sew_advanced_actor::load( const JsonObject &obj, const std::string & ) { // Mandatory: for( const std::string line : obj.get_array( "materials" ) ) { @@ -5505,7 +5505,7 @@ std::unique_ptr sew_advanced_actor::clone() const return std::make_unique( *this ); } -void change_scent_iuse::load( const JsonObject &obj ) +void change_scent_iuse::load( const JsonObject &obj, const std::string & ) { scenttypeid = scenttype_id( obj.get_string( "scent_typeid" ) ); if( !scenttypeid.is_valid() ) { @@ -5551,12 +5551,12 @@ std::unique_ptr effect_on_conditons_actor::clone() const return std::make_unique( *this ); } -void effect_on_conditons_actor::load( const JsonObject &obj ) +void effect_on_conditons_actor::load( const JsonObject &obj, const std::string &src ) { obj.read( "description", description ); obj.read( "menu_text", menu_text ); for( JsonValue jv : obj.get_array( "effect_on_conditions" ) ) { - eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, "" ) ); + eocs.emplace_back( effect_on_conditions::load_inline_eoc( jv, src ) ); } } diff --git a/src/iuse_actor.h b/src/iuse_actor.h index 97e0db9669ab3..79eac39c44092 100644 --- a/src/iuse_actor.h +++ b/src/iuse_actor.h @@ -109,7 +109,7 @@ class iuse_transform : public iuse_actor explicit iuse_transform( const std::string &type = "transform" ) : iuse_actor( type ) {} ~iuse_transform() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -138,7 +138,7 @@ class unpack_actor : public iuse_actor explicit unpack_actor( const std::string &type = "unpack" ) : iuse_actor( type ) {} ~unpack_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector &dump ) const override; @@ -156,7 +156,7 @@ class message_iuse : public iuse_actor translation message; ~message_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; std::string get_name() const override; @@ -178,7 +178,7 @@ class sound_iuse : public iuse_actor std::string sound_variant = "default"; ~sound_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; std::string get_name() const override; @@ -216,7 +216,7 @@ class explosion_iuse : public iuse_actor explicit explosion_iuse( const std::string &type = "explosion" ) : iuse_actor( type ) {} ~explosion_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -264,7 +264,7 @@ class consume_drug_iuse : public iuse_actor explicit consume_drug_iuse( const std::string &type = "consume_drug" ) : iuse_actor( type ) {} ~consume_drug_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -299,7 +299,7 @@ class delayed_transform_iuse : public iuse_transform type ) {} ~delayed_transform_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -332,7 +332,7 @@ class place_monster_iuse : public iuse_actor place_monster_iuse() : iuse_actor( "place_monster" ) { } ~place_monster_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -360,7 +360,7 @@ class change_scent_iuse : public iuse_actor change_scent_iuse() : iuse_actor( "change_scent" ) { } ~change_scent_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -379,7 +379,7 @@ class place_npc_iuse : public iuse_actor place_npc_iuse() : iuse_actor( "place_npc" ) { } ~place_npc_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -398,7 +398,7 @@ class deploy_furn_actor : public iuse_actor deploy_furn_actor() : iuse_actor( "deploy_furn" ) {} ~deploy_furn_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -415,7 +415,7 @@ class deploy_appliance_actor : public iuse_actor deploy_appliance_actor() : iuse_actor( "deploy_appliance" ) {} ~deploy_appliance_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -451,7 +451,7 @@ class reveal_map_actor : public iuse_actor explicit reveal_map_actor( const std::string &type = "reveal_map" ) : iuse_actor( type ) {} ~reveal_map_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -488,7 +488,7 @@ class firestarter_actor : public iuse_actor explicit firestarter_actor( const std::string &type = "firestarter" ) : iuse_actor( type ) {} ~firestarter_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -510,7 +510,7 @@ class salvage_actor : public iuse_actor explicit salvage_actor( const std::string &type = "salvage" ) : iuse_actor( type ) {} ~salvage_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; private: @@ -553,7 +553,7 @@ class inscribe_actor : public iuse_actor explicit inscribe_actor( const std::string &type = "inscribe" ) : iuse_actor( type ) {} ~inscribe_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -576,7 +576,7 @@ class fireweapon_off_actor : public iuse_actor fireweapon_off_actor() : iuse_actor( "fireweapon_off" ) {} ~fireweapon_off_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -597,7 +597,7 @@ class fireweapon_on_actor : public iuse_actor explicit fireweapon_on_actor( const std::string &type = "fireweapon_on" ) : iuse_actor( type ) {} ~fireweapon_on_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -618,7 +618,7 @@ class manualnoise_actor : public iuse_actor explicit manualnoise_actor( const std::string &type = "manualnoise" ) : iuse_actor( type ) {} ~manualnoise_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -630,7 +630,7 @@ class play_instrument_iuse : public iuse_actor explicit play_instrument_iuse( const std::string &type = "play_instrument" ) : iuse_actor( type ) {} ~play_instrument_iuse() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -675,7 +675,7 @@ class musical_instrument_actor : public iuse_actor type ) {} ~musical_instrument_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; ret_val can_use( const Character &, const item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -693,7 +693,7 @@ class learn_spell_actor : public iuse_actor explicit learn_spell_actor( const std::string &type = "learn_spell" ) : iuse_actor( type ) {} ~learn_spell_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *p, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -720,7 +720,7 @@ class cast_spell_actor : public iuse_actor explicit cast_spell_actor( const std::string &type = "cast_spell" ) : iuse_actor( type ) {} ~cast_spell_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -747,7 +747,7 @@ class holster_actor : public iuse_actor explicit holster_actor( const std::string &type = "holster" ) : iuse_actor( type ) {} ~holster_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -761,7 +761,7 @@ class ammobelt_actor : public iuse_actor ammobelt_actor() : iuse_actor( "ammobelt" ) {} ~ammobelt_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -852,7 +852,7 @@ class repair_item_actor : public iuse_actor explicit repair_item_actor( const std::string &type = "repair_item" ) : iuse_actor( type ) {} ~repair_item_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -919,7 +919,7 @@ class heal_actor : public iuse_actor explicit heal_actor( const std::string &type = "heal" ) : iuse_actor( type ) {} ~heal_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -966,7 +966,7 @@ class place_trap_actor : public iuse_actor explicit place_trap_actor( const std::string &type = "place_trap" ); ~place_trap_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -980,7 +980,7 @@ class emit_actor : public iuse_actor explicit emit_actor( const std::string &type = "emit_actor" ) : iuse_actor( type ) {} ~emit_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void finalize( const itype_id &my_item_type ) override; @@ -991,7 +991,7 @@ class saw_barrel_actor : public iuse_actor public: explicit saw_barrel_actor( const std::string &type = "saw_barrel" ) : iuse_actor( type ) {} - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint &pnt ) const override; std::unique_ptr clone() const override; @@ -1003,7 +1003,7 @@ class saw_stock_actor : public iuse_actor public: explicit saw_stock_actor( const std::string &type = "saw_stock" ) : iuse_actor( type ) {} - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint &pnt ) const override; std::unique_ptr clone() const override; @@ -1019,7 +1019,7 @@ class molle_attach_actor : public iuse_actor int size; int moves; - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint &pnt ) const override; std::unique_ptr clone() const override; }; @@ -1032,7 +1032,7 @@ class molle_detach_actor : public iuse_actor int moves; - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::optional use( Character *p, item &it, const tripoint &pnt ) const override; std::unique_ptr clone() const override; }; @@ -1042,7 +1042,7 @@ class install_bionic_actor : public iuse_actor public: explicit install_bionic_actor( const std::string &type = "install_bionic" ) : iuse_actor( type ) {} - void load( const JsonObject & ) override {} + void load( const JsonObject &, const std::string & ) override {} std::optional use( Character *p, item &it, const tripoint &pnt ) const override; ret_val can_use( const Character &, const item &it, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -1054,7 +1054,7 @@ class detach_gunmods_actor : public iuse_actor public: explicit detach_gunmods_actor( const std::string &type = "detach_gunmods" ) : iuse_actor( type ) {} - void load( const JsonObject & ) override {} + void load( const JsonObject &, const std::string & ) override {} std::optional use( Character *p, item &it, const tripoint &pnt ) const override; ret_val can_use( const Character &, const item &it, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -1066,7 +1066,7 @@ class modify_gunmods_actor : public iuse_actor public: explicit modify_gunmods_actor( const std::string &type = "modify_gunmods" ) : iuse_actor( type ) {} - void load( const JsonObject & ) override {} + void load( const JsonObject &, const std::string & ) override {} std::optional use( Character *p, item &it, const tripoint &pnt ) const override; ret_val can_use( const Character &, const item &it, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -1098,7 +1098,7 @@ class link_up_actor : public iuse_actor link_up_actor() : iuse_actor( "link_up" ) {} ~link_up_actor() override = default; - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::unique_ptr clone() const override; std::string get_name() const override; void info( const item &, std::vector & ) const override; @@ -1119,7 +1119,7 @@ class deploy_tent_actor : public iuse_actor deploy_tent_actor() : iuse_actor( "deploy_tent" ) {} ~deploy_tent_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; @@ -1138,7 +1138,7 @@ class weigh_self_actor : public iuse_actor explicit weigh_self_actor( const std::string &type = "weigh_self" ) : iuse_actor( type ) {} ~weigh_self_actor() override = default; - void load( const JsonObject &jo ) override; + void load( const JsonObject &jo, const std::string & ) override; std::optional use( Character *p, item &, const tripoint & ) const override; std::unique_ptr clone() const override; void info( const item &, std::vector & ) const override; @@ -1160,7 +1160,7 @@ class sew_advanced_actor : public iuse_actor explicit sew_advanced_actor( const std::string &type = "sew_advanced" ) : iuse_actor( type ) {} ~sew_advanced_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string & ) override; std::optional use( Character *, item &, const tripoint & ) const override; std::unique_ptr clone() const override; }; @@ -1178,7 +1178,7 @@ class effect_on_conditons_actor : public iuse_actor type ) {} ~effect_on_conditons_actor() override = default; - void load( const JsonObject &obj ) override; + void load( const JsonObject &obj, const std::string &src ) override; std::optional use( Character *p, item &it, const tripoint &point ) const override; std::unique_ptr clone() const override; std::string get_name() const override; From 4e4ec0467933d5c178b2a2d2ff6191874fb76214 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:48:50 +0000 Subject: [PATCH 6/8] Fix enchantment inline duplicate check Load source for effects so it's meaningful, then use the built-in mod_tracker + generic_factory support for checking for duplicates. --- src/effect.cpp | 4 ++-- src/effect.h | 4 ++-- src/magic_enchantment.cpp | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/effect.cpp b/src/effect.cpp index 8fcd43e4f2359..a2181aa3dd748 100644 --- a/src/effect.cpp +++ b/src/effect.cpp @@ -1503,7 +1503,7 @@ static const std::unordered_set hardcoded_movement_impairing = {{ } }; -void load_effect_type( const JsonObject &jo ) +void load_effect_type( const JsonObject &jo, const std::string_view src ) { effect_type new_etype; new_etype.id = efftype_id( jo.get_string( "id" ) ); @@ -1605,7 +1605,7 @@ void load_effect_type( const JsonObject &jo ) for( JsonValue jv : jo.get_array( "enchantments" ) ) { std::string enchant_name = "INLINE_ENCH_" + new_etype.id.str() + "_" + std::to_string( enchant_num++ ); - new_etype.enchantments.push_back( enchantment::load_inline_enchantment( jv, "", enchant_name ) ); + new_etype.enchantments.push_back( enchantment::load_inline_enchantment( jv, src, enchant_name ) ); } effect_types[new_etype.id] = new_etype; } diff --git a/src/effect.h b/src/effect.h index 519bd4291bc36..b9f9a3cb6dff2 100644 --- a/src/effect.h +++ b/src/effect.h @@ -103,7 +103,7 @@ struct effect_dur_mod { class effect_type { - friend void load_effect_type( const JsonObject &jo ); + friend void load_effect_type( const JsonObject &jo, std::string_view src ); friend class effect; public: enum class memorial_gender : int { @@ -444,7 +444,7 @@ class effect }; -void load_effect_type( const JsonObject &jo ); +void load_effect_type( const JsonObject &jo, std::string_view src ); void reset_effect_types(); const std::map &get_effect_types(); diff --git a/src/magic_enchantment.cpp b/src/magic_enchantment.cpp index 5bc094b2bfaf9..1b0be70dea650 100644 --- a/src/magic_enchantment.cpp +++ b/src/magic_enchantment.cpp @@ -240,13 +240,10 @@ enchantment_id enchantment::load_inline_enchantment( const JsonValue &jv, if( inline_id.empty() ) { jv.throw_error( "Inline enchantment cannot be created without an id." ); } - if( spell_factory.is_valid( enchantment_id( inline_id ) ) ) { - jv.throw_error( "Inline enchantment " + inline_id + - " cannot be created as an enchantment already has this id." ); - } enchantment inline_enchant; inline_enchant.load( jv.get_object(), src, inline_id ); + mod_tracker::assign_src( inline_enchant, src ); spell_factory.insert( inline_enchant ); return enchantment_id( inline_id ); } else { From 5ec4c0b459e2b6ae58a0f5512292bee88ca9907b Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:49:11 +0000 Subject: [PATCH 7/8] Move recipe categories to generic_factory To enable using copy-from to extend recipe subcategories, so mods that touch the same ones don't overwrite. --- data/json/recipes/recipes.json | 3 + .../recipes/recipes_categories.json | 31 +--- data/mods/DinoMod/recipes/recipes.json | 12 +- .../recipes/psionics_practice.json | 20 +-- src/activity_actor.cpp | 3 +- src/crafting.cpp | 2 +- src/crafting_gui.cpp | 155 +++++++++++------- src/crafting_gui.h | 15 +- src/item_factory.cpp | 4 +- src/itype.h | 2 +- src/iuse.cpp | 5 +- src/output.h | 4 +- src/recipe.cpp | 3 +- src/recipe.h | 2 +- src/recipe_dictionary.cpp | 22 +-- src/recipe_dictionary.h | 7 +- src/type_id.h | 3 + tests/crafting_test.cpp | 4 +- 18 files changed, 158 insertions(+), 139 deletions(-) diff --git a/data/json/recipes/recipes.json b/data/json/recipes/recipes.json index 38e1e1eeb3f74..06248f451ac65 100644 --- a/data/json/recipes/recipes.json +++ b/data/json/recipes/recipes.json @@ -3,6 +3,7 @@ "type": "recipe_category", "id": "CC_*", "//": "This is just a dummy category. No recipes should be added in here.", + "is_wildcard": true, "recipe_subcategories": [ "CSC_*_FAVORITE", "CSC_*_RECENT", "CSC_*_HIDDEN", "CSC_*_NESTED" ] }, { @@ -125,11 +126,13 @@ "type": "recipe_category", "id": "CC_BUILDING", "recipe_subcategories": [ "CSC_ALL", "CSC_BUILDING_BASES", "CSC_BUILDING_EXPANSIONS" ], + "is_building": true, "is_hidden": true }, { "type": "recipe_category", "id": "CC_PRACTICE", + "is_practice": true, "recipe_subcategories": [ "CSC_ALL", "CSC_PRACTICE_SCIENCE", diff --git a/data/mods/Aftershock/recipes/recipes_categories.json b/data/mods/Aftershock/recipes/recipes_categories.json index 2b9bac376a21a..5831b9362d6c8 100644 --- a/data/mods/Aftershock/recipes/recipes_categories.json +++ b/data/mods/Aftershock/recipes/recipes_categories.json @@ -2,36 +2,13 @@ { "type": "recipe_category", "id": "CC_ELECTRONIC", - "recipe_subcategories": [ - "CSC_ALL", - "CSC_ELECTRONIC_CBMS", - "CSC_ELECTRONIC_TOOLS", - "CSC_ELECTRONIC_PARTS", - "CSC_ELECTRONIC_LIGHTING", - "CSC_ELECTRONIC_COMPONENTS", - "CSC_ELECTRONIC_OTHER" - ] + "copy-from": "CC_ELECTRONIC", + "extend": { "recipe_subcategories": [ "CSC_ELECTRONIC_CBMS" ] } }, { "type": "recipe_category", "id": "CC_PRACTICE", - "recipe_subcategories": [ - "CSC_ALL", - "CSC_PRACTICE_SCIENCE", - "CSC_PRACTICE_ELECTRONICS", - "CSC_PRACTICE_FABRICATION", - "CSC_PRACTICE_FOOD", - "CSC_PRACTICE_SURVIVAL", - "CSC_PRACTICE_TAILORING", - "CSC_PRACTICE_ATHLETICS", - "CSC_PRACTICE_COMPUTERS", - "CSC_PRACTICE_DEVICES", - "CSC_PRACTICE_HEALTH", - "CSC_PRACTICE_MECHANICS", - "CSC_PRACTICE_SOCIAL", - "CSC_PRACTICE_MELEE", - "CSC_PRACTICE_RANGED", - "CSC_PRACTICE_PSI" - ] + "copy-from": "CC_PRACTICE", + "extend": { "recipe_subcategories": [ "CSC_PRACTICE_PSI" ] } } ] diff --git a/data/mods/DinoMod/recipes/recipes.json b/data/mods/DinoMod/recipes/recipes.json index adb8642836f1c..bab8f4537615f 100644 --- a/data/mods/DinoMod/recipes/recipes.json +++ b/data/mods/DinoMod/recipes/recipes.json @@ -2,15 +2,7 @@ { "type": "recipe_category", "id": "CC_ANIMALS", - "recipe_subcategories": [ - "CSC_ALL", - "CSC_ANIMALS_BOVINE ARMOR", - "CSC_ANIMALS_CANINE ARMOR", - "CSC_ANIMALS_EQUINE ARMOR", - "CSC_ANIMALS_ELEPHANT ARMOR", - "CSC_ANIMALS_OSTRICH ARMOR", - "CSC_ANIMALS_BEAR ARMOR", - "CSC_ANIMALS_EQUINE STORAGE" - ] + "copy-from": "CC_ANIMALS", + "extend": { "recipe_subcategories": [ "CSC_ANIMALS_ELEPHANT ARMOR", "CSC_ANIMALS_OSTRICH ARMOR", "CSC_ANIMALS_BEAR ARMOR" ] } } ] diff --git a/data/mods/MindOverMatter/recipes/psionics_practice.json b/data/mods/MindOverMatter/recipes/psionics_practice.json index bce81eebdbef9..c3be72f6f6fdb 100644 --- a/data/mods/MindOverMatter/recipes/psionics_practice.json +++ b/data/mods/MindOverMatter/recipes/psionics_practice.json @@ -2,24 +2,8 @@ { "type": "recipe_category", "id": "CC_PRACTICE", - "recipe_subcategories": [ - "CSC_ALL", - "CSC_PRACTICE_SCIENCE", - "CSC_PRACTICE_ELECTRONICS", - "CSC_PRACTICE_FABRICATION", - "CSC_PRACTICE_FOOD", - "CSC_PRACTICE_SURVIVAL", - "CSC_PRACTICE_TAILORING", - "CSC_PRACTICE_ATHLETICS", - "CSC_PRACTICE_COMPUTERS", - "CSC_PRACTICE_DEVICES", - "CSC_PRACTICE_HEALTH", - "CSC_PRACTICE_MECHANICS", - "CSC_PRACTICE_SOCIAL", - "CSC_PRACTICE_MELEE", - "CSC_PRACTICE_RANGED", - "CSC_PRACTICE_METAPHYSICS" - ] + "copy-from": "CC_PRACTICE", + "extend": { "recipe_subcategories": [ "CSC_PRACTICE_METAPHYSICS" ] } }, { "id": "prac_psionics_begin", diff --git a/src/activity_actor.cpp b/src/activity_actor.cpp index 96cbfc71b9c64..c0aa3bcb2612f 100644 --- a/src/activity_actor.cpp +++ b/src/activity_actor.cpp @@ -36,6 +36,7 @@ #include "contents_change_handler.h" #include "coordinates.h" #include "craft_command.h" +#include "crafting_gui.h" #include "creature.h" #include "creature_tracker.h" #include "debug.h" @@ -3768,7 +3769,7 @@ void craft_activity_actor::canceled( player_activity &/*act*/, Character &/*who* } const recipe item_recipe = craft->get_making(); // practice recipe items with no components can be safely removed - if( item_recipe.category == "CC_PRACTICE" && craft->components.empty() ) { + if( item_recipe.category->is_practice && craft->components.empty() ) { craft_item.remove_item(); } } diff --git a/src/crafting.cpp b/src/crafting.cpp index 7a689c9d91b5f..99534f674c6be 100644 --- a/src/crafting.cpp +++ b/src/crafting.cpp @@ -157,7 +157,7 @@ static bool crafting_allowed( const Character &p, const recipe &rec ) return false; } - if( rec.category == "CC_BUILDING" ) { + if( rec.category->is_building ) { add_msg( m_info, _( "Overmap terrain building recipes are not implemented yet!" ) ); return false; } diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index e86a6b14e720e..06a15c5d356e9 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -91,9 +91,24 @@ static const std::map craft_speed_reaso {NORMAL_CRAFTING, to_translation( "craftable" )} }; -// TODO: Convert these globals to handling categories via generic_factory? -static std::vector craft_cat_list; -static std::map > craft_subcat_list; +namespace +{ + +generic_factory craft_cat_list( "recipe_category" ); + +} // namespace + +template<> +const crafting_category &string_id::obj() const +{ + return craft_cat_list.obj( *this ); +} + +template<> +bool string_id::is_valid() const +{ + return craft_cat_list.is_valid( *this ); +} static bool query_is_yes( std::string_view query ); static void draw_hidden_amount( const catacurses::window &w, int amount, int num_recipe ); @@ -127,32 +142,39 @@ static std::string get_cat_unprefixed( const std::string_view prefixed_name ) return std::string( prefixed_name.substr( 3, prefixed_name.size() - 3 ) ); } -void load_recipe_category( const JsonObject &jsobj ) +void load_recipe_category( const JsonObject &jsobj, const std::string &src ) { - const std::string category = jsobj.get_string( "id" ); - const bool is_hidden = jsobj.get_bool( "is_hidden", false ); - - if( category.find( "CC_" ) != 0 ) { - jsobj.throw_error( "Crafting category id has to be prefixed with 'CC_'" ); - } - - if( !is_hidden - && std::find( craft_cat_list.begin(), craft_cat_list.end(), category ) == craft_cat_list.end() - ) { - craft_cat_list.push_back( category ); - } - - const std::string cat_name = get_cat_unprefixed( category ); + craft_cat_list.load( jsobj, src ); +} - craft_subcat_list[category].clear(); - for( const std::string subcat_id : jsobj.get_array( "recipe_subcategories" ) ) { +void crafting_category::load( const JsonObject &jo, const std::string_view ) +{ + // Ensure id is correct + if( id.str().find( "CC_" ) != 0 ) { + jo.throw_error( "Crafting category id has to be prefixed with 'CC_'" ); + } + + optional( jo, was_loaded, "is_hidden", is_hidden, false ); + optional( jo, was_loaded, "is_practice", is_practice, false ); + optional( jo, was_loaded, "is_building", is_building, false ); + optional( jo, was_loaded, "is_wildcard", is_wildcard, false ); + mandatory( jo, was_loaded, "recipe_subcategories", subcategories, + auto_flags_reader<> {} ); + + // Ensure subcategory ids are correct and remove dupes + std::string cat_name = get_cat_unprefixed( id.str() ); + std::unordered_set known; + for( auto it = subcategories.begin(); it != subcategories.end(); ) { + const std::string &subcat_id = *it; if( subcat_id.find( "CSC_" + cat_name + "_" ) != 0 && subcat_id != "CSC_ALL" ) { - jsobj.throw_error( "Crafting sub-category id has to be prefixed with CSC__" ); + jo.throw_error( "Crafting sub-category id has to be prefixed with CSC__" ); } - if( find( craft_subcat_list[category].begin(), craft_subcat_list[category].end(), - subcat_id ) == craft_subcat_list[category].end() ) { - craft_subcat_list[category].push_back( subcat_id ); + if( known.find( subcat_id ) != known.end() ) { + it = subcategories.erase( it ); + continue; } + known.emplace( subcat_id ); + ++it; } } @@ -170,8 +192,7 @@ static std::string get_subcat_unprefixed( const std::string_view cat, void reset_recipe_categories() { - craft_cat_list.clear(); - craft_subcat_list.clear(); + craft_cat_list.reset(); } static bool cannot_gain_skill_or_prof( const Character &crafter, const recipe &recp ) @@ -860,7 +881,7 @@ void recipe_result_info_cache::insert_iteminfo_block_separator( std::vector, bool> -recipes_from_cat( const recipe_subset &available_recipes, const std::string &cat, +recipes_from_cat( const recipe_subset &available_recipes, const crafting_category_id &cat, const std::string &subcat ) { if( subcat == "CSC_*_FAVORITE" ) { @@ -1282,8 +1303,16 @@ std::pair select_crafter_and_crafting_recipe( int & bool is_filtered_unread = false; std::map is_cat_unread; std::map> is_subcat_unread; - tab_list tab( craft_cat_list ); - tab_list subtab( craft_subcat_list[tab.cur()] ); + std::vector crafting_categories; + crafting_categories.reserve( craft_cat_list.size() ); + for( const crafting_category &cat : craft_cat_list.get_all() ) { + if( cat.is_hidden ) { + continue; + } + crafting_categories.emplace_back( cat.id.str() ); + } + tab_list tab( crafting_categories ); + tab_list subtab( crafting_category_id( tab.cur() )->subcategories ); std::map> translated_tab_map; std::map> translated_subtab_map; std::map> list_map; @@ -1330,13 +1359,11 @@ std::pair select_crafter_and_crafting_recipe( int & gotocat.end(), [&goto_recipe]( const recipe * r ) { return r && r->ident() == goto_recipe; } ); - if( gotorec != gotocat.end() && - std::find( craft_cat_list.begin(), craft_cat_list.end(), - goto_recipe->category ) != craft_cat_list.end() ) { - while( tab.cur() != goto_recipe->category ) { + if( gotorec != gotocat.end() && ( *gotorec )->category.is_valid() ) { + while( tab.cur() != goto_recipe->category.str() ) { tab.next(); } - subtab = tab_list( craft_subcat_list[tab.cur()] ); + subtab = tab_list( crafting_category_id( tab.cur() )->subcategories ); chosen = *gotorec; show_hidden = true; keepline = true; @@ -1349,12 +1376,12 @@ std::pair select_crafter_and_crafting_recipe( int & ui.on_redraw( [&]( ui_adaptor & ui ) { if( highlight_unread_recipes && recalc_unread ) { if( filterstring.empty() ) { - for( const std::string &cat : craft_cat_list ) { + for( const std::string &cat : crafting_categories ) { is_cat_unread[cat] = false; - for( const std::string &subcat : craft_subcat_list[cat] ) { + for( const std::string &subcat : crafting_category_id( cat )->subcategories ) { is_subcat_unread[cat][subcat] = false; const std::pair, bool> result = recipes_from_cat( available_recipes, - cat, subcat ); + crafting_category_id( cat ), subcat ); const std::vector &recipes = result.first; const bool include_hidden = result.second; for( const recipe *const rcp : recipes ) { @@ -1583,7 +1610,7 @@ std::pair select_crafter_and_crafting_recipe( int & picking.insert( picking.end(), filtered_recipes.begin(), filtered_recipes.end() ); } else { const std::pair, bool> result = recipes_from_cat( available_recipes, - tab.cur(), subtab.cur() ); + crafting_category_id( tab.cur() ), subtab.cur() ); show_hidden = result.second; if( show_hidden ) { current = result.first; @@ -1722,7 +1749,7 @@ std::pair select_crafter_and_crafting_recipe( int & if( entry.second.contains( local_coord ) ) { tab.set_index( entry.first ); recalc = true; - subtab = tab_list( craft_subcat_list[tab.cur()] ); + subtab = tab_list( crafting_category_id( tab.cur() )->subcategories ); handled = true; } } @@ -1751,8 +1778,9 @@ std::pair select_crafter_and_crafting_recipe( int & std::string start = subtab.cur(); do { subtab.prev(); - } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(), - subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) ); + } while( subtab.cur() != start && + available_recipes.empty_category( crafting_category_id( tab.cur() ), + subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) ); recalc = true; } else if( action == "SCROLL_ITEM_INFO_UP" ) { line_item_info -= scroll_item_info_lines; @@ -1766,7 +1794,7 @@ std::pair select_crafter_and_crafting_recipe( int & mouse_in_window( coord, w_head_tabs ) ) ) { tab.prev(); // Default ALL - subtab = tab_list( craft_subcat_list[tab.cur()] ); + subtab = tab_list( crafting_category_id( tab.cur() )->subcategories ); recalc = true; } else if( action == "RIGHT" || ( action == "SCROLL_DOWN" && mouse_in_window( coord, w_subhead ) ) ) { @@ -1776,14 +1804,15 @@ std::pair select_crafter_and_crafting_recipe( int & std::string start = subtab.cur(); do { subtab.next(); - } while( subtab.cur() != start && available_recipes.empty_category( tab.cur(), - subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) ); + } while( subtab.cur() != start && + available_recipes.empty_category( crafting_category_id( tab.cur() ), + subtab.cur() != "CSC_ALL" ? subtab.cur() : "" ) ); recalc = true; } else if( action == "NEXT_TAB" || ( action == "SCROLL_DOWN" && mouse_in_window( coord, w_head_tabs ) ) ) { tab.next(); // Default ALL - subtab = tab_list( craft_subcat_list[tab.cur()] ); + subtab = tab_list( crafting_category_id( tab.cur() )->subcategories ); recalc = true; } else if( action == "DOWN" ) { if( !previously_toggled_unread ) { @@ -2333,12 +2362,15 @@ static std::map> draw_recipe_tabs( const cata case NORMAL: { std::vector translated_cats; translated_cats.reserve( craft_cat_list.size() ); - for( const std::string &cat : craft_cat_list ) { - if( unread[ cat ] ) { + for( const crafting_category &cat : craft_cat_list.get_all() ) { + if( cat.is_hidden ) { + continue; + } + if( unread[ cat.id.str() ] ) { translated_cats.emplace_back( _( get_cat_unprefixed( - cat ) ).append( "⁺" ) ); + cat.id.str() ) ).append( "⁺" ) ); } else { - translated_cats.emplace_back( _( get_cat_unprefixed( cat ) ) ); + translated_cats.emplace_back( _( get_cat_unprefixed( cat.id.str() ) ) ); } } std::pair, size_t> fitted_tabs = fit_tabs_to_width( getmaxx( w ), @@ -2390,19 +2422,22 @@ static std::map> draw_recipe_subtabs( std::vector translated_subcats; std::vector empty_subcats; std::vector unread_subcats; - translated_subcats.reserve( craft_subcat_list[tab].size() ); - empty_subcats.reserve( craft_subcat_list[tab].size() ); - unread_subcats.reserve( craft_subcat_list[tab].size() ); - for( const std::string &subcat : craft_subcat_list[tab] ) { + crafting_category_id current_cat = crafting_category_id( tab ); + size_t subcats_count = current_cat->subcategories.size(); + translated_subcats.reserve( subcats_count ); + empty_subcats.reserve( subcats_count ); + unread_subcats.reserve( subcats_count ); + for( const std::string &subcat : current_cat->subcategories ) { translated_subcats.emplace_back( _( get_subcat_unprefixed( tab, subcat ) ) ); - empty_subcats.emplace_back( available_recipes.empty_category( tab, - subcat != "CSC_ALL" ? subcat : "" ) ); + empty_subcats.emplace_back( available_recipes.empty_category( + crafting_category_id( tab ), + subcat != "CSC_ALL" ? subcat : "" ) ); unread_subcats.emplace_back( unread[subcat] ); } std::pair, size_t> fitted_subcat_list = fit_tabs_to_width( getmaxx( w ), subtab, translated_subcats ); size_t offset = fitted_subcat_list.second; - if( fitted_subcat_list.first.size() + offset > craft_subcat_list[tab].size() ) { + if( fitted_subcat_list.first.size() + offset > subcats_count ) { break; } // Draw the tabs on each other @@ -2440,9 +2475,9 @@ static std::map> draw_recipe_subtabs( const std::vector *subcategories_for_category( const std::string &category ) { - auto it = craft_subcat_list.find( category ); - if( it != craft_subcat_list.end() ) { - return &it->second; + crafting_category_id cat( category ); + if( !cat.is_valid() ) { + return nullptr; } - return nullptr; + return &cat->subcategories; } diff --git a/src/crafting_gui.h b/src/crafting_gui.h index 0e2039bbe1d85..149cc934dbeec 100644 --- a/src/crafting_gui.h +++ b/src/crafting_gui.h @@ -23,11 +23,24 @@ class recipe; std::pair select_crafter_and_crafting_recipe( int &batch_size_out, const recipe_id &goto_recipe, Character *crafter, std::string filterstring = "" ); -void load_recipe_category( const JsonObject &jsobj ); +void load_recipe_category( const JsonObject &jsobj, const std::string &src ); void reset_recipe_categories(); // Returns nullptr if the category does not exist, or a pointer to its vector // of subcategories it the category does exist const std::vector *subcategories_for_category( const std::string &category ); +struct crafting_category { + crafting_category_id id; + bool was_loaded = false; + + bool is_hidden; + bool is_practice; + bool is_building; + bool is_wildcard; + std::vector subcategories; + + void load( const JsonObject &jo, std::string_view src ); +}; + #endif // CATA_SRC_CRAFTING_GUI_H diff --git a/src/item_factory.cpp b/src/item_factory.cpp index d7987d7c55c9f..b5af8bfff8fc6 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -66,6 +66,8 @@ static const ammo_effect_str_id ammo_effect_SPECIAL_COOKOFF( "SPECIAL_COOKOFF" ) static const ammotype ammo_NULL( "NULL" ); +static const crafting_category_id crafting_category_CC_FOOD( "CC_FOOD" ); + static const damage_type_id damage_bash( "bash" ); static const damage_type_id damage_bullet( "bullet" ); @@ -2666,7 +2668,7 @@ static void load_memory_card_data( memory_card_info &mcd, const JsonObject &jo ) mcd.recipes_categories.emplace( cat ); } } else { - mcd.recipes_categories = { "CC_FOOD" }; + mcd.recipes_categories = { crafting_category_CC_FOOD }; } if( jo.has_member( "secret_recipes" ) ) { mcd.secret_recipes = jo.get_bool( "secret_recipes" ); diff --git a/src/itype.h b/src/itype.h index 5a8dcff50cfee..68afdb3d90008 100644 --- a/src/itype.h +++ b/src/itype.h @@ -1182,7 +1182,7 @@ struct memory_card_info { int recipes_amount; int recipes_level_min; int recipes_level_max; - std::set recipes_categories; + std::set recipes_categories; bool secret_recipes; }; diff --git a/src/iuse.cpp b/src/iuse.cpp index 8a4e5679dee52..32a72b0ada2a8 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -146,6 +146,8 @@ static const construction_str_id construction_constr_pit( "constr_pit" ); static const construction_str_id construction_constr_pit_shallow( "constr_pit_shallow" ); static const construction_str_id construction_constr_water_channel( "constr_water_channel" ); +static const crafting_category_id crafting_category_CC_FOOD( "CC_FOOD" ); + static const efftype_id effect_adrenaline( "adrenaline" ); static const efftype_id effect_antibiotic( "antibiotic" ); static const efftype_id effect_antibiotic_visible( "antibiotic_visible" ); @@ -7569,7 +7571,8 @@ std::optional iuse::multicooker( Character *p, item *it, const tripoint &po int counter = 0; static const std::set multicooked_subcats = { "CSC_FOOD_MEAT", "CSC_FOOD_VEGGI", "CSC_FOOD_PASTA" }; - for( const recipe * const &r : get_avatar().get_learned_recipes().in_category( "CC_FOOD" ) ) { + for( const recipe * const &r : get_avatar().get_learned_recipes().in_category( + crafting_category_CC_FOOD ) ) { if( multicooked_subcats.count( r->subcategory ) > 0 ) { dishes.push_back( r ); const bool can_make = r->deduped_requirements().can_make_with_inventory( diff --git a/src/output.h b/src/output.h index eddd46c7553a3..124874c520099 100644 --- a/src/output.h +++ b/src/output.h @@ -1221,9 +1221,9 @@ class tab_list { private: size_t _index = 0; - std::vector *_list; + const std::vector *_list; public: - explicit tab_list( std::vector &_list ) : _list( &_list ) { + explicit tab_list( const std::vector &_list ) : _list( &_list ) { } void last() { diff --git a/src/recipe.cpp b/src/recipe.cpp index a2515db29da86..06a6e97b290f6 100644 --- a/src/recipe.cpp +++ b/src/recipe.cpp @@ -15,6 +15,7 @@ #include "cata_utility.h" #include "character.h" #include "color.h" +#include "crafting_gui.h" #include "debug.h" #include "enum_traits.h" #include "effect_on_condition.h" @@ -662,7 +663,7 @@ void recipe::add_requirements( const std::vector> std::string recipe::get_consistency_error() const { - if( category == "CC_BUILDING" ) { + if( category.is_valid() && category->is_building ) { if( is_blueprint() || oter_str_id( result_.c_str() ).is_valid() ) { return std::string(); } diff --git a/src/recipe.h b/src/recipe.h index 0a8a7e63f895a..9e9532bf75787 100644 --- a/src/recipe.h +++ b/src/recipe.h @@ -123,7 +123,7 @@ class recipe bool was_loaded = false; bool obsolete = false; - std::string category; + crafting_category_id category; std::string subcategory; translation description; diff --git a/src/recipe_dictionary.cpp b/src/recipe_dictionary.cpp index 0566f6832257c..1aa1417a547c4 100644 --- a/src/recipe_dictionary.cpp +++ b/src/recipe_dictionary.cpp @@ -341,7 +341,8 @@ std::vector recipe_subset::recipes_that_produce( const itype_id return res; } -bool recipe_subset::empty_category( const std::string &cat, const std::string &subcat ) const +bool recipe_subset::empty_category( const crafting_category_id &cat, + const std::string &subcat ) const { if( subcat == "CSC_*_FAVORITE" ) { return uistate.favorite_recipes.empty(); @@ -349,7 +350,7 @@ bool recipe_subset::empty_category( const std::string &cat, const std::string &s return uistate.recent_recipes.empty(); } else if( subcat == "CSC_*_HIDDEN" ) { return uistate.hidden_recipes.empty(); - } else if( cat == "CC_*" ) { + } else if( cat->is_wildcard ) { //any other category in CC_* is populated return false; } @@ -369,7 +370,7 @@ bool recipe_subset::empty_category( const std::string &cat, const std::string &s return true; } -std::vector recipe_subset::in_category( const std::string &cat, +std::vector recipe_subset::in_category( const crafting_category_id &cat, const std::string &subcat ) const { std::vector res; @@ -676,7 +677,7 @@ void recipe_dictionary::check_consistency() for( const auto &e : recipe_dict.recipes ) { const recipe &r = e.second; - if( r.category.empty() ) { + if( r.category.str().empty() ) { if( !r.subcategory.empty() ) { debugmsg( "recipe %s has subcategory but no category", r.ident().str() ); } @@ -684,18 +685,19 @@ void recipe_dictionary::check_consistency() continue; } - const std::vector *subcategories = subcategories_for_category( r.category ); - if( !subcategories ) { - debugmsg( "recipe %s has invalid category %s", r.ident().str(), r.category ); + if( !r.category.is_valid() ) { + debugmsg( "recipe %s has invalid category %s", r.ident().str(), r.category.str() ); continue; } + const std::vector &subcategories = r.category->subcategories; + if( !r.subcategory.empty() ) { - auto it = std::find( subcategories->begin(), subcategories->end(), r.subcategory ); - if( it == subcategories->end() ) { + auto it = std::find( subcategories.begin(), subcategories.end(), r.subcategory ); + if( it == subcategories.end() ) { debugmsg( "recipe %s has subcategory %s which is invalid or doesn't match category %s", - r.ident().str(), r.subcategory, r.category ); + r.ident().str(), r.subcategory, r.category.str() ); } } } diff --git a/src/recipe_dictionary.h b/src/recipe_dictionary.h index 56375fed242d0..ffeef002336f1 100644 --- a/src/recipe_dictionary.h +++ b/src/recipe_dictionary.h @@ -128,11 +128,12 @@ class recipe_subset int get_custom_difficulty( const recipe *r ) const; /** Check if there is any recipes in given category (optionally restricted to subcategory), index which is for nested categories */ - bool empty_category( const std::string &cat, const std::string &subcat = std::string() ) const; + bool empty_category( const crafting_category_id &cat, + const std::string &subcat = std::string() ) const; /** Get all recipes in given category (optionally restricted to subcategory) */ std::vector in_category( - const std::string &cat, + const crafting_category_id &cat, const std::string &subcat = std::string() ) const; /** Returns all recipes which could use component */ @@ -202,7 +203,7 @@ class recipe_subset private: std::set recipes; std::map difficulties; - std::map> category; + std::map> category; std::map> component; }; diff --git a/src/type_id.h b/src/type_id.h index 13685d8e419b9..bfbe45db19c4c 100644 --- a/src/type_id.h +++ b/src/type_id.h @@ -58,6 +58,9 @@ using construction_group_str_id = string_id; struct clothing_mod; using clothing_mod_id = string_id; +struct crafting_category; +using crafting_category_id = string_id; + struct effect_on_condition; using effect_on_condition_id = string_id; diff --git a/tests/crafting_test.cpp b/tests/crafting_test.cpp index ea93639d0200a..a1ce14c96d21a 100644 --- a/tests/crafting_test.cpp +++ b/tests/crafting_test.cpp @@ -44,6 +44,8 @@ static const activity_id ACT_CRAFT( "ACT_CRAFT" ); +static const crafting_category_id crafting_category_CC_FOOD( "CC_FOOD" ); + static const flag_id json_flag_ITEM_BROKEN( "ITEM_BROKEN" ); static const flag_id json_flag_USE_UPS( "USE_UPS" ); @@ -142,7 +144,7 @@ TEST_CASE( "recipe_subset" ) CHECK( subset.get_custom_difficulty( r ) == r->difficulty ); } THEN( "it's in the right category" ) { - const auto cat_recipes( subset.in_category( "CC_FOOD" ) ); + const auto cat_recipes( subset.in_category( crafting_category_CC_FOOD ) ); CHECK( cat_recipes.size() == 1 ); CHECK( std::find( cat_recipes.begin(), cat_recipes.end(), r ) != cat_recipes.end() ); From ea7dc2c8ef05f8d672908fb2f9574dcf9f500840 Mon Sep 17 00:00:00 2001 From: anothersimulacrum Date: Thu, 13 Jun 2024 23:59:17 +0000 Subject: [PATCH 8/8] Re-enable running afs and mom together in all_mods Now that the bugs making them incompatible have been fixed, there's no reason to have the exclusion. --- build-scripts/get_all_mods.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build-scripts/get_all_mods.py b/build-scripts/get_all_mods.py index 1bd473299f718..6072b78d68031 100755 --- a/build-scripts/get_all_mods.py +++ b/build-scripts/get_all_mods.py @@ -11,8 +11,7 @@ mods_this_time = [] exclusions = [ - # #74443 - incompatibility between mindovermatter and aftershock due to bug - ('mindovermatter', 'aftershock') + # Tuple of (mod_id, mod_id) - these two mods will be incompatible ]