diff --git a/data/json/techniques.json b/data/json/techniques.json index 469ebf5b7009..a4bb1b7c657c 100644 --- a/data/json/techniques.json +++ b/data/json/techniques.json @@ -687,6 +687,7 @@ "melee_allowed": true, "crit_tec": true, "weapon_damage_requirements": [ { "type": "bash", "min": 8 } ], + "weapon_categories_allowed": [ "STILETTOS", "KNIVES", "SHORT_SWORDS", "BATONS", "TONFAS" ], "stun_dur": 1, "mult_bonuses": [ { "stat": "movecost", "scale": 0.6 }, @@ -1310,6 +1311,7 @@ "skill_requirements": [ { "name": "melee", "level": 5 } ], "unarmed_allowed": true, "melee_allowed": true, + "weapon_categories_allowed": [ "STILETTOS", "KNIVES", "1H_HOOKED", "SHORT_SWORDS", "1H_SWORDS", "JAPANESE_SWORDS", "BIONIC_WEAPONRY" ], "crit_tec": true, "stun_dur": 1, "mult_bonuses": [ diff --git a/doc/src/content/docs/en/mod/json/reference/creatures/martialart_json.md b/doc/src/content/docs/en/mod/json/reference/creatures/martialart_json.md index 3d1da171bdc5..9cf4a03deaa5 100644 --- a/doc/src/content/docs/en/mod/json/reference/creatures/martialart_json.md +++ b/doc/src/content/docs/en/mod/json/reference/creatures/martialart_json.md @@ -42,6 +42,7 @@ title: Martial arts & techniques "name" : "phasing strike", // In-game name displayed "unarmed_allowed" : true, // Can an unarmed character use this technique "unarmed_weapons_allowed" : true, // Does this technique require the character to be actually unarmed or does it allow unarmed weapons +"weapon_categories_allowed" : [ "BLADES", "KNIVES" ], // Restrict technique to only these categories of weapons. If omitted, all weapon categories are allowed. Empty hands are always allowed if unarmed_allowed is true. "melee_allowed" : true, // Means that ANY melee weapon can be used, NOT just the martial art's weapons "skill_requirements": [ { "name": "melee", "level": 3 } ], // Skills and their minimum levels required to use this technique. Can be any skill. "weapon_damage_requirements": [ { "type": "bash", "min": 5 } ], // Minimum weapon damage required to use this technique. Can be any damage type. @@ -82,7 +83,8 @@ title: Martial arts & techniques "description" : "+Strength bash armor, +Dexterity acid armor, +Intelligence electricity armor, +Perception fire armor.", // In-game description "buff_duration": 2, // Duration in turns that this buff lasts "unarmed_allowed" : true, // Can this buff be applied to an unarmed character -"unarmed_allowed" : false, // Can this buff be applied to an armed character +"melee_allowed" : false, // Can this buff be applied to an armed character +"weapon_categories_allowed" : [ "BLADES", "KNIVES" ], // Restrict buff to only these categories of weapons. If omitted, all weapon categories are allowed. Empty hands are always allowed if unarmed_allowed is true. "unarmed_weapons_allowed" : true, // Does this buff require the character to be actually unarmed. If true, allows unarmed weapons (brass knuckles, punch daggers) "max_stacks" : 8, // Maximum number of stacks on the buff. Buff bonuses are multiplied by current buff intensity "bonus_blocks": 1 // Extra blocks per turn diff --git a/src/martialarts.cpp b/src/martialarts.cpp index a5521bc5eb22..14a7b1e41370 100644 --- a/src/martialarts.cpp +++ b/src/martialarts.cpp @@ -25,6 +25,7 @@ #include "itype.h" #include "json.h" #include "map.h" +#include "messages.h" #include "output.h" #include "pimpl.h" #include "player.h" @@ -176,6 +177,8 @@ void ma_requirements::load( const JsonObject &jo, const std::string & ) optional( jo, was_loaded, "skill_requirements", min_skill, ma_skill_reader {} ); optional( jo, was_loaded, "weapon_damage_requirements", min_damage, ma_weapon_damage_reader {} ); + optional( jo, was_loaded, "weapon_categories_allowed", weapon_categories_allowed, + auto_flags_reader {} ); } void ma_technique::load( const JsonObject &jo, const std::string &src ) @@ -519,6 +522,18 @@ bool ma_requirements::is_valid_character( const Character &u ) const } } + if( !weapon_categories_allowed.empty() && is_armed ) { + bool valid_weap_cat = false; + for( const weapon_category_id &w_cat : weapon_categories_allowed ) { + if( u.used_weapon().typeId()->weapon_category.count( w_cat ) > 0 ) { + valid_weap_cat = true; + } + } + if( !valid_weap_cat ) { + return false; + } + } + return true; } @@ -572,6 +587,18 @@ std::string ma_requirements::get_description( bool buff ) const }, enumeration_conjunction::none ) + "\n"; } + if( !weapon_categories_allowed.empty() ) { + dump += vgettext( "Weapon category required: ", + "Weapon categories required: ", weapon_categories_allowed.size() ); + dump += enumerate_as_string( weapon_categories_allowed.begin(), + weapon_categories_allowed.end(), []( const weapon_category_id & w_cat ) { + if( !w_cat.is_valid() ) { + return w_cat.str(); + } + return w_cat->name().translated(); + } ) + "\n"; + } + if( !req_buffs.empty() ) { dump += _( "Requires: " ); diff --git a/src/martialarts.h b/src/martialarts.h index fe5268269597..779418243ed6 100644 --- a/src/martialarts.h +++ b/src/martialarts.h @@ -61,6 +61,9 @@ struct ma_requirements { bool strictly_unarmed; // Ignore force_unarmed? bool wall_adjacent; // Does it only work near a wall? + /** Weapon categories compatible with this requirement. If empty, allow any weapon category. */ + std::vector weapon_categories_allowed; + /** Minimum amount of given skill to trigger this bonus */ std::vector> min_skill;