diff --git a/data/json/skills.json b/data/json/skills.json index e3f4c99fb7d6d..2f49633e91540 100644 --- a/data/json/skills.json +++ b/data/json/skills.json @@ -12,7 +12,8 @@ "name": "speaking", "description": "Your skill in speaking to other people. Covers ability in boasting, flattery, threats, persuasion, lies, and other facets of interpersonal communication. Works best in conjunction with a high level of intelligence.", "companion_survival_rank_factor": 1, - "display_category": "display_social" + "display_category": "display_social", + "companion_skill_practice": [ { "skill": "recruiting", "weight": 15 }, { "skill": "recruiting", "weight": 70 } ] }, { "type": "skill", @@ -28,7 +29,8 @@ "description": "Your skill in effecting emergency medical treatment. Higher levels allow better use of medicines and items like bandages and first aid kits, and reduce the failure and complication rates of medical procedures.", "companion_survival_rank_factor": 1, "companion_industry_rank_factor": 1, - "display_category": "display_interaction" + "display_category": "display_interaction", + "companion_skill_practice": [ { "skill": "hunting", "weight": 10 }, { "skill": "combat", "weight": 10 } ] }, { "type": "skill", @@ -36,7 +38,8 @@ "name": "mechanics", "description": "Your skill in engineering, maintaining and repairing vehicles and other mechanical systems. This skill covers the craft of items with complex parts, and plays a role in the installation of bionic equipment.", "companion_industry_rank_factor": 1, - "display_category": "display_interaction" + "display_category": "display_interaction", + "companion_skill_practice": [ { "skill": "menial", "weight": 10 }, { "skill": "construction", "weight": 20 } ] }, { "type": "skill", @@ -44,7 +47,8 @@ "name": "trapping", "description": "Your skill in creating, setting, finding and disarming traps safely and effectively. This skill does not affect the evasion of traps that are triggered.", "companion_survival_rank_factor": 1, - "display_category": "display_interaction" + "display_category": "display_interaction", + "companion_skill_practice": [ { "skill": "", "weight": 15 }, { "skill": "gathering", "weight": 15 }, { "skill": "trapping", "weight": 80 } ] }, { "type": "skill", @@ -58,7 +62,8 @@ "ident": "swimming", "name": "swimming", "description": "Your ability to stay afloat and move around in bodies of water. This skill keeps you from drowning, affects your combat effectiveness and speed in deep water, and determines the detriment of swimming with heavier gear.", - "display_category": "display_interaction" + "display_category": "display_interaction", + "companion_skill_practice": [ { "skill": "", "weight": 5 }, { "skill": "gathering", "weight": 5 }, { "skill": "trapping", "weight": 5 } ] }, { "type": "skill", @@ -66,7 +71,14 @@ "name": "fabrication", "description": "Your skill in working with raw materials and shaping them into useful objects. This skill plays an important role in the crafting of many objects.", "companion_industry_rank_factor": 1, - "display_category": "display_crafting" + "display_category": "display_crafting", + "companion_skill_practice": [ + { "skill": "", "weight": 10 }, + { "skill": "gathering", "weight": 10 }, + { "skill": "trapping", "weight": 10 }, + { "skill": "menial", "weight": 60 }, + { "skill": "construction", "weight": 70 } + ] }, { "type": "skill", @@ -74,7 +86,8 @@ "name": "cooking", "description": "Your skill in combining food ingredients to make other, tastier food items. It may also be used in certain chemical mixtures and other, more esoteric tasks.", "companion_industry_rank_factor": 1, - "display_category": "display_crafting" + "display_category": "display_crafting", + "companion_skill_practice": [ { "skill": "menial", "weight": 15 } ] }, { "type": "skill", @@ -82,7 +95,8 @@ "name": "tailoring", "description": "Your skill in the craft and repair of clothing, bags, blankets and other textiles. Affects knitting, sewing, stitching, weaving, and nearly anything else involving a needle and thread.", "companion_industry_rank_factor": 1, - "display_category": "display_crafting" + "display_category": "display_crafting", + "companion_skill_practice": [ { "skill": "menial", "weight": 15 } ] }, { "type": "skill", @@ -90,7 +104,17 @@ "name": "survival", "description": "Your skill in surviving the wilderness, and in crafting various basic survival items. This also covers your ability to skin and butcher animals for meat and hides.", "companion_survival_rank_factor": 1, - "display_category": "display_crafting" + "display_category": "display_crafting", + "companion_skill_practice": [ + { "skill": "", "weight": 80 }, + { "skill": "gathering", "weight": 80 }, + { "skill": "trapping", "weight": 15 }, + { "skill": "hunting", "weight": 15 }, + { "skill": "menial", "weight": 10 }, + { "skill": "construction", "weight": 10 }, + { "skill": "recruiting", "weight": 25 }, + { "skill": "combat", "weight": 10 } + ] }, { "type": "skill", @@ -108,7 +132,14 @@ "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, "companion_survival_rank_factor": 1, - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ + { "skill": "", "weight": 5 }, + { "skill": "gathering", "weight": 5 }, + { "skill": "trapping", "weight": 5 }, + { "skill": "hunting", "weight": 45 }, + { "skill": "combat", "weight": 15 } + ] }, { "type": "skill", @@ -116,7 +147,8 @@ "name": "marksmanship", "description": "Your overall skill in using bows and firearms. With higher levels, this general experience increases accuracy with any bows or firearms, but is secondary to practice with the type of ranged weapon in question.", "tags": [ "combat_skill" ], - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ { "skill": "gathering", "weight": 60 }, { "skill": "combat", "weight": 5 } ] }, { "type": "skill", @@ -132,7 +164,8 @@ "name": "handguns", "description": "Handguns have poor accuracy compared to rifles, but are usually quick to fire and reload faster than other guns. They are very effective at close quarters, though unsuited for long range engagement.", "tags": [ "combat_skill" ], - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ { "skill": "hunting", "weight": 25 } ] }, { "type": "skill", @@ -140,7 +173,8 @@ "name": "rifles", "description": "Rifles have terrific range and accuracy compared to other firearms, but may be slow to fire and reload, and can prove difficult to use in close quarters. Fully automatic rifles can fire rapidly, but are harder to handle properly.", "tags": [ "combat_skill" ], - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ { "skill": "hunting", "weight": 45 } ] }, { "type": "skill", @@ -148,7 +182,8 @@ "name": "shotguns", "description": "Shotguns are easy to shoot and can inflict massive damage, but their effectiveness and accuracy decline rapidly with range. Slugs can be loaded into shotguns to provide greater range, though they are somewhat inaccurate.", "tags": [ "combat_skill" ], - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ { "skill": "hunting", "weight": 25 } ] }, { "type": "skill", @@ -156,7 +191,8 @@ "name": "submachine guns", "description": "Comprised of an automatic rifle carbine designed to fire a pistol cartridge, submachine guns can reload and fire quickly, sometimes in bursts, but they are relatively inaccurate and may be prone to mechanical failures.", "tags": [ "combat_skill" ], - "display_category": "display_ranged" + "display_category": "display_ranged", + "companion_skill_practice": [ { "skill": "hunting", "weight": 25 } ] }, { "type": "skill", @@ -173,7 +209,15 @@ "description": "Your skill and finesse in personal combat, both with and without a weapon. Higher levels can significantly increase the accuracy and effectiveness of your physical attacks.", "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ + { "skill": "", "weight": 5 }, + { "skill": "gathering", "weight": 5 }, + { "skill": "trapping", "weight": 5 }, + { "skill": "hunting", "weight": 10 }, + { "skill": "recruiting", "weight": 5 }, + { "skill": "combat", "weight": 20 } + ] }, { "type": "skill", @@ -182,7 +226,8 @@ "description": "Your skill in fighting with blunt weaponry, from rocks and sticks to baseball bats and the butts of rifles. Skill increases damage, and higher levels will improve the accuracy of an attack.", "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ { "skill": "hunting", "weight": 10 }, { "skill": "combat", "weight": 10 } ] }, { "type": "skill", @@ -191,14 +236,16 @@ "description": "Your skill in fighting with weaponry designed to cut, hack and slash an opponent. Lower levels of skill increase accuracy and damage, while higher levels will help to bypass heavy armor and thick hides.", "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ { "skill": "hunting", "weight": 10 }, { "skill": "combat", "weight": 10 } ] }, { "type": "skill", "ident": "dodge", "name": "dodging", "description": "Your ability to dodge an oncoming threat, be it an enemy's attack, a triggered trap, or a falling rock. This skill is also used in attempts to fall gracefully, and for other acrobatic feats. The first number shown includes modifiers, and the second does not.", - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ { "skill": "hunting", "weight": 15 }, { "skill": "combat", "weight": 20 } ] }, { "type": "skill", @@ -207,7 +254,8 @@ "description": "Your skill in fighting with knives, spears and other such stabbing implements. Skill increases attack accuracy as well as the chance of inflicting a deadly and critical blow.", "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ { "skill": "hunting", "weight": 10 }, { "skill": "combat", "weight": 10 } ] }, { "type": "skill", @@ -217,7 +265,8 @@ "tags": [ "combat_skill" ], "companion_combat_rank_factor": 1, "companion_survival_rank_factor": 1, - "display_category": "display_melee" + "display_category": "display_melee", + "companion_skill_practice": [ { "skill": "hunting", "weight": 10 }, { "skill": "combat", "weight": 10 } ] }, { "type": "skill", diff --git a/src/mission_companion.cpp b/src/mission_companion.cpp index 120e398cd5d9a..6f8b6cddde165 100644 --- a/src/mission_companion.cpp +++ b/src/mission_companion.cpp @@ -75,11 +75,6 @@ const skill_id skill_tailor( "tailor" ); const skill_id skill_cooking( "cooking" ); const skill_id skill_traps( "traps" ); const skill_id skill_archery( "archery" ); -const skill_id skill_rifle( "rifle" ); -const skill_id skill_pistol( "pistol" ); -const skill_id skill_shotgun( "shotgun" ); -const skill_id skill_smg( "smg" ); -const skill_id skill_swimming( "swimming" ); static const trait_id trait_NPC_CONSTRUCTION_LEV_1( "NPC_CONSTRUCTION_LEV_1" ); static const trait_id trait_NPC_CONSTRUCTION_LEV_2( "NPC_CONSTRUCTION_LEV_2" ); @@ -1698,72 +1693,21 @@ void talk_function::companion_skill_trainer( npc &comp, const std::string &skill int checks = 1 + to_minutes( time_worked ) / 10; weighted_int_list skill_practice; - if( skill_tested.empty() || skill_tested == "gathering" ) { - skill_practice.add( skill_survival, 80 ); - skill_practice.add( skill_traps, 15 ); - skill_practice.add( skill_fabrication, 10 ); - skill_practice.add( skill_archery, 5 ); - skill_practice.add( skill_melee, 5 ); - skill_practice.add( skill_swimming, 5 ); - } else if( skill_tested == "trapping" ) { - skill_practice.add( skill_traps, 80 ); - skill_practice.add( skill_survival, 15 ); - skill_practice.add( skill_fabrication, 10 ); - skill_practice.add( skill_archery, 5 ); - skill_practice.add( skill_melee, 5 ); - skill_practice.add( skill_swimming, 5 ); - } else if( skill_tested == "hunting" ) { - skill_practice.add( skill_gun, 60 ); - skill_practice.add( skill_archery, 45 ); - skill_practice.add( skill_rifle, 45 ); - skill_practice.add( skill_pistol, 25 ); - skill_practice.add( skill_shotgun, 25 ); - // who shoots Bambi with an Uzi? - skill_practice.add( skill_smg, 25 ); - skill_practice.add( skill_dodge, 15 ); - skill_practice.add( skill_survival, 15 ); - skill_practice.add( skill_melee, 10 ); - skill_practice.add( skill_firstaid, 10 ); - skill_practice.add( skill_bashing, 10 ); - skill_practice.add( skill_stabbing, 10 ); - skill_practice.add( skill_cutting, 10 ); - skill_practice.add( skill_unarmed, 10 ); - } else if( skill_tested == "menial" ) { - skill_practice.add( skill_fabrication, 60 ); - skill_practice.add( skill_tailor, 15 ); - skill_practice.add( skill_speech, 15 ); - skill_practice.add( skill_cooking, 15 ); - skill_practice.add( skill_survival, 10 ); - skill_practice.add( skill_mechanics, 10 ); - } else if( skill_tested == "construction" ) { - skill_practice.add( skill_fabrication, 70 ); - skill_practice.add( skill_mechanics, 20 ); - skill_practice.add( skill_survival, 10 ); - } else if( skill_tested == "recruiting" ) { - skill_practice.add( skill_speech, 70 ); - skill_practice.add( skill_survival, 25 ); - skill_practice.add( skill_melee, 5 ); - } else if( skill_tested == "combat" ) { + if( skill_tested == "combat" ) { const skill_id best_skill = comp.best_skill(); if( best_skill ) { skill_practice.add( best_skill, 30 ); } - skill_practice.add( skill_melee, 20 ); - skill_practice.add( skill_dodge, 20 ); - skill_practice.add( skill_archery, 15 ); - skill_practice.add( skill_survival, 10 ); - skill_practice.add( skill_firstaid, 10 ); - skill_practice.add( skill_bashing, 10 ); - skill_practice.add( skill_stabbing, 10 ); - skill_practice.add( skill_cutting, 10 ); - skill_practice.add( skill_unarmed, 10 ); - skill_practice.add( skill_gun, 5 ); - } else { - comp.practice( skill_id( skill_tested ), difficulty * to_minutes( time_worked ) / 10 ); - return; } - for( int i = 0; i < checks; i++ ) { - comp.practice( *skill_practice.pick(), difficulty ); + for( Skill &sk : Skill::skills ) { + skill_practice.add( sk.ident(), sk.get_companion_skill_practice( skill_tested ) ); + } + if( skill_practice.empty() ) { + comp.practice( skill_id( skill_tested ), difficulty * to_minutes( time_worked ) / 10 ); + } else { + for( int i = 0; i < checks; i++ ) { + comp.practice( *skill_practice.pick(), difficulty ); + } } } diff --git a/src/skill.cpp b/src/skill.cpp index 6b33df71e62d6..a23dc0c31d77c 100644 --- a/src/skill.cpp +++ b/src/skill.cpp @@ -92,15 +92,22 @@ void Skill::load_skill( JsonObject &jsobj ) return s._ident == ident; } ), end( skills ) ); + std::unordered_map companion_skill_practice; translation name, desc; jsobj.read( "name", name ); jsobj.read( "description", desc ); + JsonArray ja = jsobj.get_array( "companion_skill_practice" ); + while( ja.has_more() ) { + JsonObject jo = ja.next_object(); + companion_skill_practice.emplace( jo.get_string( "skill" ), jo.get_int( "weight" ) ); + } skill_displayType_id display_type = skill_displayType_id( jsobj.get_string( "display_category" ) ); Skill sk( ident, name, desc, jsobj.get_tags( "tags" ), display_type ); sk._companion_combat_rank_factor = jsobj.get_int( "companion_combat_rank_factor", 0 ); sk._companion_survival_rank_factor = jsobj.get_int( "companion_survival_rank_factor", 0 ); sk._companion_industry_rank_factor = jsobj.get_int( "companion_industry_rank_factor", 0 ); + sk._companion_skill_practice = companion_skill_practice; if( sk.is_contextual_skill() ) { contextual_skills[sk.ident()] = sk; diff --git a/src/skill.h b/src/skill.h index fc4a597176423..de73385ed68a8 100644 --- a/src/skill.h +++ b/src/skill.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "calendar.h" #include "string_id.h" @@ -28,6 +29,7 @@ class Skill translation _description; std::set _tags; skill_displayType_id _display_type; + std::unordered_map _companion_skill_practice; // these are not real skills, they depend on context static std::map contextual_skills; int _companion_combat_rank_factor; @@ -59,6 +61,10 @@ class Skill std::string description() const { return _description.translated(); } + int get_companion_skill_practice( const std::string &companion_skill ) const { + return _companion_skill_practice.find( companion_skill ) == _companion_skill_practice.end() ? 0 : + _companion_skill_practice.at( companion_skill ); + } skill_displayType_id display_category() const { return _display_type; }