diff --git a/data/mods/Xedra_Evolved/eocs/give_a_class_eoc.json b/data/mods/Xedra_Evolved/eocs/give_a_class_eoc.json index f6f6b0e5ee7a7..f56897b1065a1 100644 --- a/data/mods/Xedra_Evolved/eocs/give_a_class_eoc.json +++ b/data/mods/Xedra_Evolved/eocs/give_a_class_eoc.json @@ -192,71 +192,34 @@ { "u_lose_trait": "EATER" }, { "u_lose_trait": "INVENTOR" }, { "u_mutate_towards": "DREAMLESS", "category": "ANY", "use_vitamins": false }, - { "u_forget_recipe": "inventor_leg_weight" }, - { "u_forget_recipe": "inventor_jump_boots" }, - { "u_forget_recipe": "inventor_sniper" }, - { "u_forget_recipe": "inventor_shotgun" }, - { "u_forget_recipe": "inventor_pistol" }, - { "u_forget_recipe": "megachette" }, - { "u_forget_recipe": "software_math_inventor" }, - { "u_forget_recipe": "software_electronics_reference_inventor" }, - { "u_forget_recipe": "combatsaw_spear_off" }, + { "u_forget_recipe": "CC_XEDRA", "subcategory": "CSC_XEDRA_ARMOR" }, + { "u_forget_recipe": "inventor_research_energy_1", "//": "CSC_XEDRA_RESEARCH start" }, + { "u_forget_recipe": "inventor_research_energy_2" }, + { "u_forget_recipe": "inventor_research_energy_3" }, { "u_forget_recipe": "inventor_research_base_2" }, - { "u_forget_recipe": "helmet_inventor" }, - { "u_forget_recipe": "inventor_fists" }, - { "u_forget_recipe": "wolf_mask" }, - { "u_forget_recipe": "magnetic_holster" }, - { "u_forget_recipe": "binary_sword" }, - { "u_forget_recipe": "bio_launcher" }, - { "u_forget_recipe": "bio_warhead" }, - { "u_forget_recipe": "trinket_damage" }, + { "u_forget_recipe": "inventor_research_base_3" }, + { "u_forget_recipe": "inventor_research_ai_1" }, + { "u_forget_recipe": "inventor_research_dimension_1" }, + { "u_forget_recipe": "dreamsmith_research" }, + { "u_forget_recipe": "CC_XEDRA", "subcategory": "CSC_XEDRA_ROBOTS" }, + { "u_forget_recipe": "CC_XEDRA", "subcategory": "CSC_XEDRA_TOOLS" }, + { "u_forget_recipe": "CC_XEDRA", "subcategory": "CSC_XEDRA_WEAPONS" }, + { "u_forget_recipe": "trinket_damage", "//": "CSC_XEDRA_MISC start" }, { "u_forget_recipe": "trinket_range" }, { "u_forget_recipe": "trinket_sound" }, { "u_forget_recipe": "choke_wideshot" }, { "u_forget_recipe": "mod_inv_pistol_booster" }, - { "u_forget_recipe": "inventor_research_base_3" }, - { "u_forget_recipe": "inventor_research_energy_1" }, - { "u_forget_recipe": "software_AI" }, { "u_forget_recipe": "stunning_qr_trap" }, - { "u_forget_recipe": "inventor_backpack" }, - { "u_forget_recipe": "vision_halo" }, - { "u_forget_recipe": "sonic_gun" }, - { "u_forget_recipe": "mace_magic" }, { "u_forget_recipe": "stunning_arg_trap" }, - { "u_forget_recipe": "inventor_fists_plus" }, - { "u_forget_recipe": "inventor_plasma_axe_off" }, - { "u_forget_recipe": "inventor_research_energy_1" }, - { "u_forget_recipe": "battery_gun" }, - { "u_forget_recipe": "ray_gun" }, { "u_forget_recipe": "inventor_light_minus_cell" }, { "u_forget_recipe": "inventor_light_cell" }, { "u_forget_recipe": "inventor_medium_cell" }, { "u_forget_recipe": "inventor_heavy_cell" }, - { "u_forget_recipe": "inventor_welder" }, - { "u_forget_recipe": "heater_tool" }, - { "u_forget_recipe": "inventor_electric_fist" }, - { "u_forget_recipe": "inventor_research_energy_2" }, - { "u_forget_recipe": "inventor_glauncher" }, - { "u_forget_recipe": "inventor_glauncher_fire" }, - { "u_forget_recipe": "inventor_glauncher_elec" }, - { "u_forget_recipe": "inventor_glauncher_direct" }, - { "u_forget_recipe": "death_ray" }, { "u_forget_recipe": "inventor_lasmod_mega_capasitor" }, { "u_forget_recipe": "inventor_lasmod_adv_adv_cooler" }, { "u_forget_recipe": "inventor_lasmod_recuperator" }, { "u_forget_recipe": "inventor_lasmod_mega_everything" }, { "u_forget_recipe": "inventor_lasmod_more_capacitors" }, - { "u_forget_recipe": "inventor_research_ai_1" }, - { "u_forget_recipe": "inventor_research_dimension_1" }, - { "u_forget_recipe": "nre_recorder_inventor" }, - { "u_forget_recipe": "aura_force" }, - { "u_forget_recipe": "ray_rifle" }, - { "u_forget_recipe": "ion_gun" }, - { "u_forget_recipe": "accelerator_gun" }, - { "u_forget_recipe": "inventor_grenade_noise_expl" }, - { "u_forget_recipe": "inventor_grenade_noise_emp" }, - { "u_forget_recipe": "inventor_grenade_noise_fire" }, - { "u_forget_recipe": "heater_gun" }, { "u_forget_recipe": "inventor_lasmod_close_range" }, { "u_forget_recipe": "inventor_lasmod_long_range" }, { "u_forget_recipe": "inventor_lasmod_capasitor" }, @@ -265,76 +228,13 @@ { "u_forget_recipe": "inventor_lasmod_radiator" }, { "u_forget_recipe": "inventor_lasmod_chonky_radiator" }, { "u_forget_recipe": "inventor_lasmod_spooky_heat_sink" }, - { "u_forget_recipe": "inventor_research_energy_3" }, - { "u_forget_recipe": "bot_sniperbot" }, - { "u_forget_recipe": "bot_shotgunbot" }, - { "u_forget_recipe": "bot_meleebot" }, - { "u_forget_recipe": "rip_ticket" }, - { "u_forget_recipe": "inventor_warp_grenade" }, - { "u_forget_recipe": "inventor_portal_closer" }, - { "u_forget_recipe": "teleporter_inventor" }, - { "u_forget_recipe": "dreamdross_bo" }, - { "u_forget_recipe": "dreamdross_knife" }, - { "u_forget_recipe": "dreamdross_club" }, - { "u_forget_recipe": "dreamsmith_research" }, { "u_forget_recipe": "dreamdross_lump" }, { "u_forget_recipe": "forged_dreamstuff_ingot" }, - { "u_forget_recipe": "dreamforged_ballistic_plate" }, - { "u_forget_recipe": "dreamforged_ballistic_plate_small" }, - { "u_forget_recipe": "dreamforged_q_staff_ench" }, - { "u_forget_recipe": "dreamforged_longsword_ench" }, - { "u_forget_recipe": "dreamforged_warhammer_ench" }, - { "u_forget_recipe": "dreamforged_spear_ench" }, - { "u_forget_recipe": "dreamforged_halberd_ench" }, - { "u_forget_recipe": "dreamforged_glaive_ench" }, - { "u_forget_recipe": "dreamforged_naginata_ench" }, - { "u_forget_recipe": "dreamforged_mace_ench" }, - { "u_forget_recipe": "dreamforged_morningstar_ench" }, - { "u_forget_recipe": "dreamforged_estoc_ench" }, - { "u_forget_recipe": "dreamforged_arming_sword_ench" }, - { "u_forget_recipe": "dreamforged_broadsword_ench" }, - { "u_forget_recipe": "dreamforged_battleaxe_ench" }, - { "u_forget_recipe": "dreamforged_katana_ench" }, - { "u_forget_recipe": "dreamforged_knife_combat_ench" }, - { "u_forget_recipe": "dreamforged_kris_ench" }, - { "u_forget_recipe": "dreamforged_kukri_ench" }, - { "u_forget_recipe": "dreamforged_nodachi_ench" }, - { "u_forget_recipe": "dreamforged_rapier_ench" }, - { "u_forget_recipe": "dreamforged_tanto_ench" }, - { "u_forget_recipe": "dreamforged_wakizashi_ench" }, - { "u_forget_recipe": "dreamforged_zweihander_ench" }, - { "u_forget_recipe": "dreamforged_khopesh_ench" }, - { "u_forget_recipe": "dreamforged_lucerne_ench" }, - { "u_forget_recipe": "dreamforged_knuckle_ench" }, - { "u_forget_recipe": "dreamforged_fullhelmet_ench" }, - { "u_forget_recipe": "dreamforged_helmet_ench" }, - { "u_forget_recipe": "dreamforged_plate_armor_ench" }, - { "u_forget_recipe": "dreamforged_armguard_plate_ench" }, - { "u_forget_recipe": "dreamforged_boots_ench" }, - { "u_forget_recipe": "dreamforged_longbow" }, - { "u_forget_recipe": "arrow_dreamforged" }, - { "u_forget_recipe": "dreamforged_crossbow" }, - { "u_forget_recipe": "bolt_dreamforged" }, - { "u_forget_recipe": "dreamforged_hacksaw" }, - { "u_forget_recipe": "dreamforged_hammer" }, - { "u_forget_recipe": "dreamforged_halligan" }, - { "u_forget_recipe": "dreamforged_pliers_locking" }, - { "u_forget_recipe": "dreamforged_pickaxe" }, - { "u_forget_recipe": "dreamforged_picklocks" }, - { "u_forget_recipe": "dreamforged_scalpel" }, - { "u_forget_recipe": "dreamforged_e_tool" }, - { "u_forget_recipe": "dreamforged_ax" }, { "u_forget_recipe": "dreamforged_nail" }, - { "u_forget_recipe": "dreamforged_knuckle_berserk" }, - { "u_forget_recipe": "dreamforged_helmet_berserker" }, - { "u_forget_recipe": "dreamforged_armguard_plate_berserk" }, - { "u_forget_recipe": "dreamforged_boots_berserk" }, - { "u_forget_recipe": "dreamforged_fullhelmet_arcane" }, - { "u_forget_recipe": "dreamforged_glaive_healing" }, - { "u_forget_recipe": "dreamforged_tsurugi_speed" }, - { "u_forget_recipe": "dreamforged_q_staff_exp" }, - { "u_forget_recipe": "dreamforged_armguard_plate_gunslinger" }, - { "u_forget_recipe": "dreamforged_bed_of_restful_repose" } + { "u_forget_recipe": "software_math_inventor", "//": "Are these even recipes?" }, + { "u_forget_recipe": "software_electronics_reference_inventor" }, + { "u_forget_recipe": "nre_recorder_inventor" }, + { "u_forget_recipe": "teleporter_inventor" } ] } ] diff --git a/doc/EFFECT_ON_CONDITION.md b/doc/EFFECT_ON_CONDITION.md index effe943855299..a2f84a4308afb 100644 --- a/doc/EFFECT_ON_CONDITION.md +++ b/doc/EFFECT_ON_CONDITION.md @@ -3455,7 +3455,9 @@ Your character or the npc will forget the recipe | Syntax | Optionality | Value | Info | | --- | --- | --- | --- | -| "u_forget_recipe" / "npc_forget_recipe" | **mandatory** | string or [variable object](#variable-object) | recipe, that would be forgotten | +| "u_forget_recipe" / "npc_forget_recipe" | **mandatory** | string or [variable object](#variable-object) | recipe/recipe category to be forgotten | +| "category" | optional, defaults to false unless subcategory is specified | bool | whether the above field should be interpreted as a category instead of a singular recipe | +| "subcategory" | optional | string or [variable object](#variable-object) | recipe subcategory of the specified category to be forgotten | ##### Valid talkers: @@ -3469,6 +3471,16 @@ You forget the recipe `inventor_research_base_1` { "u_forget_recipe": "inventor_research_base_1" } ``` +You forget all recipes in the `CC_XEDRA` category +```json +{ "u_forget_recipe": "CC_XEDRA", "category": true } +``` + +You forget all recipes in the `CC_XEDRA_MISC` subcategory of `CC_XEDRA` +```json +{ "u_forget_recipe": "CC_XEDRA", "subcategory": "CC_XEDRA_MISC" } +``` + You forget a recipe, that was passes by `recipe_id` context value ```json { "u_forget_recipe": { "context_val": "recipe_id" } } diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index cb6da5041bb1a..9f275a0fa5e7b 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -49,7 +49,6 @@ #include "point.h" #include "popup.h" #include "recipe.h" -#include "recipe_dictionary.h" #include "requirements.h" #include "skill.h" #include "string_formatter.h" @@ -885,9 +884,8 @@ void recipe_result_info_cache::insert_iteminfo_block_separator( std::vector, bool> -recipes_from_cat( const recipe_subset &available_recipes, const crafting_category_id &cat, - const std::string &subcat ) +std::pair, bool> recipes_from_cat( const recipe_subset + &available_recipes, const crafting_category_id &cat, const std::string &subcat ) { if( subcat == "CSC_*_FAVORITE" ) { return std::make_pair( available_recipes.favorite(), false ); diff --git a/src/crafting_gui.h b/src/crafting_gui.h index 88fbb1411e504..104f9f6e2e36c 100644 --- a/src/crafting_gui.h +++ b/src/crafting_gui.h @@ -6,6 +6,7 @@ #include #include +#include "recipe_dictionary.h" #include "type_id.h" class Character; @@ -24,6 +25,8 @@ class recipe; std::pair select_crafter_and_crafting_recipe( int &batch_size_out, const recipe_id &goto_recipe, Character *crafter, std::string filterstring = "", bool camp_crafting = false, inventory *inventory_override = nullptr ); +std::pair, bool> recipes_from_cat( const recipe_subset + &available_recipes, const crafting_category_id &cat, const std::string &subcat ); void load_recipe_category( const JsonObject &jsobj, const std::string &src ); void reset_recipe_categories(); diff --git a/src/npctalk.cpp b/src/npctalk.cpp index 941f8128677b6..d2d4601190bc9 100644 --- a/src/npctalk.cpp +++ b/src/npctalk.cpp @@ -29,6 +29,7 @@ #include "computer.h" #include "condition.h" #include "coordinates.h" +#include "crafting_gui.h" #include "creature_tracker.h" #include "debug.h" #include "dialogue_helpers.h" @@ -4753,10 +4754,31 @@ 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, 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 ) { - const recipe_id &r = recipe_id( forgotten_recipe_id.evaluate( d ) ); - d.actor( is_npc )->forget_recipe( r ); + const bool use_subcategory = jo.has_member( "subcategory" ); + const bool forgotten_recipe_is_category = jo.get_bool( "category", false ) || use_subcategory; + str_or_var forgotten_recipe = get_str_or_var( jo.get_member( member ), member, true ); + std::optional forgotten_recipe_subcategory = std::nullopt; + if( use_subcategory ) { + forgotten_recipe_subcategory = get_str_or_var( jo.get_member( "subcategory" ), "subcategory", + true ); + } + + return [forgotten_recipe, forgotten_recipe_is_category, forgotten_recipe_subcategory, + is_npc]( dialogue const & d ) { + if( forgotten_recipe_is_category ) { + const recipe_subset &known_recipes = d.actor( is_npc )->get_character()->get_learned_recipes(); + const crafting_category_id category_to_use( forgotten_recipe.evaluate( d ) ); + const std::string subcategory_to_forget = !forgotten_recipe_subcategory ? "" : + forgotten_recipe_subcategory.value().evaluate( d ); + const std::vector recipes_to_forget = + recipes_from_cat( known_recipes, category_to_use, subcategory_to_forget ).first; + for( const recipe *recipe_to_forget : recipes_to_forget ) { + d.actor( is_npc )->forget_recipe( recipe_to_forget->ident() ); + } + } else { + const recipe_id &r = recipe_id( forgotten_recipe.evaluate( d ) ); + d.actor( is_npc )->forget_recipe( r ); + } }; }