diff --git a/bionics.cpp b/bionics.cpp index fa429b16d4552..f91ece50a8dfc 100644 --- a/bionics.cpp +++ b/bionics.cpp @@ -365,9 +365,10 @@ bool player::install_bionics(game *g, it_bionic* type) std::string bio_name = type->name.substr(5); // Strip off "CBM: " WINDOW* w = newwin(25, 80, 0, 0); - int pl_skill = int_cur + sklevel[sk_electronics] * 4 + - sklevel[sk_firstaid] * 3 + - sklevel[sk_mechanics] * 2; + int pl_skill = int_cur + + skillLevel(Skill::skill("electronics")).level() * 4 + + skillLevel(Skill::skill("firstaid")).level() * 3 + + skillLevel(Skill::skill("mechanics")).level() * 2; int skint = int(pl_skill / 4); int skdec = int((pl_skill * 10) / 4) % 10; @@ -432,9 +433,9 @@ charge mechanism, which must be installed from another CBM.", BATTERY_AMOUNT); ch = getch(); while (ch != 'q' && ch != '\n' && ch != KEY_ESCAPE); if (ch == '\n') { - practice(sk_electronics, (100 - chance_of_success) * 1.5); - practice(sk_firstaid, (100 - chance_of_success) * 1.0); - practice(sk_mechanics, (100 - chance_of_success) * 0.5); + practice(Skill::skill("electronics"), (100 - chance_of_success) * 1.5); + practice(Skill::skill("firstaid"), (100 - chance_of_success) * 1.0); + practice(Skill::skill("mechanics"), (100 - chance_of_success) * 0.5); int success = chance_of_success - rng(1, 100); if (success > 0) { g->add_msg("Successfully installed batteries."); @@ -499,9 +500,9 @@ charge mechanism, which must be installed from another CBM.", BATTERY_AMOUNT); } while (ch != '\n' && ch != 'q' && ch != KEY_ESCAPE); if (ch == '\n') { - practice(sk_electronics, (100 - chance_of_success) * 1.5); - practice(sk_firstaid, (100 - chance_of_success) * 1.0); - practice(sk_mechanics, (100 - chance_of_success) * 0.5); + practice(Skill::skill("electronics"), (100 - chance_of_success) * 1.5); + practice(Skill::skill("firstaid"), (100 - chance_of_success) * 1.0); + practice(Skill::skill("mechanics"), (100 - chance_of_success) * 0.5); bionic_id id = type->options[selection]; int success = chance_of_success - rng(1, 100); if (success > 0) { diff --git a/computer.cpp b/computer.cpp index 4541dc72a4b93..aa822488d64b8 100644 --- a/computer.cpp +++ b/computer.cpp @@ -162,8 +162,8 @@ bool computer::hack_attempt(player *p, int Security) if (Security == -1) Security = security; // Set to main system security if no value passed - p->practice(sk_computer, 5 + Security * 2); - int player_roll = p->sklevel[sk_computer]; + p->practice(Skill::skill("computer"), 5 + Security * 2); + int player_roll = p->skillLevel(Skill::skill("computer")).level(); if (p->int_cur < 8 && one_in(2)) player_roll -= rng(0, 8 - p->int_cur); else if (p->int_cur > 8 && one_in(3)) diff --git a/construction.cpp b/construction.cpp index 6d00e71508f24..ea307bbbe1cdb 100644 --- a/construction.cpp +++ b/construction.cpp @@ -273,7 +273,7 @@ void game::construction_menu() update_info = false; constructable* current_con = constructions[select]; // Print difficulty - int pskill = u.sklevel[sk_carpentry]; + uint32_t pskill = u.skillLevel(Skill::skill("carpentry")).level(); int diff = current_con->difficulty > 0 ? current_con->difficulty : 0; mvwprintz(w_con, 1, 43, (pskill >= diff ? c_white : c_red), "%d ", diff); @@ -431,7 +431,7 @@ bool game::player_can_build(player &p, inventory inv, constructable* con, { // default behavior: return true if any of the stages up to L can be constr'd // if exact_level, require that this level be constructable - if (p.sklevel[sk_carpentry] < con->difficulty) + if (p.skillLevel(Skill::skill("carpentry")) < con->difficulty) return false; if (level < 0) @@ -573,9 +573,9 @@ void game::complete_construction() std::vector player_use; std::vector map_use; - u.practice(sk_carpentry, built->difficulty * 10); + u.practice(Skill::skill("carpentry"), built->difficulty * 10); if (built->difficulty == 0) - u.practice(sk_carpentry, 10); + u.practice(Skill::skill("carpentry"), 10); for (int i = 0; i < 3; i++) { if (!stage.components[i].empty()) consume_items(this, stage.components[i]); diff --git a/crafting.cpp b/crafting.cpp index 95228af9a4993..cd33e0546bc45 100644 --- a/crafting.cpp +++ b/crafting.cpp @@ -30,7 +30,7 @@ recipes.push_back( new recipe(id, result, category, skill1, skill2, difficulty,\ // NON-CRAFTABLE BUT CAN BE DISASSEMBLED (set category to CC_NONCRAFT) -RECIPE(itm_lawnmower, CC_NONCRAFT, sk_null, sk_null, 0, 1000, true); +RECIPE(itm_lawnmower, CC_NONCRAFT, NULL, NULL, 0, 1000, true); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_scrap, 8, NULL); COMP(itm_spring, 2, NULL); @@ -38,101 +38,101 @@ RECIPE(itm_lawnmower, CC_NONCRAFT, sk_null, sk_null, 0, 1000, true); COMP(itm_combustion_tiny, 1, NULL); COMP(itm_pipe, 3, NULL); -RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); +RECIPE(itm_lighter, CC_NONCRAFT, NULL, NULL, 0, 100, true); COMP(itm_pilot_light, 1, NULL); // CRAFTABLE // WEAPONS - RECIPE(itm_lawnmower_machete, CC_WEAPON, sk_null, sk_null, 0, 5000, true); + RECIPE(itm_lawnmower_machete, CC_WEAPON, NULL, NULL, 0, 5000, true); COMP(itm_duct_tape, 50, NULL); COMP(itm_lawnmower_blade, 1, NULL); - RECIPE(itm_lawnmower_halberd, CC_WEAPON, sk_null, sk_null, 0, 5000, true); + RECIPE(itm_lawnmower_halberd, CC_WEAPON, NULL, NULL, 0, 5000, true); COMP(itm_duct_tape, 100, NULL); COMP(itm_lawnmower_blade, 1, NULL); COMP(itm_stick, 1, itm_mop, 1, itm_broom, 1, NULL); - RECIPE(itm_spear_wood, CC_WEAPON, sk_null, sk_null, 0, 800, false); + RECIPE(itm_spear_wood, CC_WEAPON, NULL, NULL, 0, 800, false); TOOL(itm_hatchet, -1, itm_knife_steak, -1, itm_knife_butcher, -1, itm_knife_combat, -1, itm_machete, -1, itm_toolset, -1, NULL); COMP(itm_stick, 1, itm_broom, 1, itm_mop, 1, itm_2x4, 1, itm_pool_cue, 1, NULL); - RECIPE(itm_spear_knife, CC_WEAPON, sk_stabbing, sk_null, 0, 600, true); + RECIPE(itm_spear_knife, CC_WEAPON, Skill::skill("stabbing"), NULL, 0, 600, true); COMP(itm_stick, 1, itm_broom, 1, itm_mop, 1, NULL); COMP(itm_knife_steak, 2, itm_knife_combat, 1, NULL); COMP(itm_string_6, 6, itm_string_36, 1, NULL); - RECIPE(itm_longbow, CC_WEAPON, sk_archery, sk_survival, 2, 15000, true); + RECIPE(itm_longbow, CC_WEAPON, Skill::skill("archery"), Skill::skill("survival"), 2, 15000, true); TOOL(itm_hatchet, -1, itm_knife_steak, -1, itm_knife_butcher, -1, itm_knife_combat, -1, itm_machete, -1, itm_toolset, -1, NULL); COMP(itm_stick, 1, NULL); COMP(itm_string_36, 2, NULL); - RECIPE(itm_arrow_wood, CC_WEAPON, sk_archery, sk_survival, 1, 5000, false); + RECIPE(itm_arrow_wood, CC_WEAPON, Skill::skill("archery"), Skill::skill("survival"), 1, 5000, false); TOOL(itm_hatchet, -1, itm_knife_steak, -1, itm_knife_butcher, -1, itm_knife_combat, -1, itm_machete, -1, itm_toolset, -1, NULL); COMP(itm_stick, 1, itm_broom, 1, itm_mop, 1, itm_2x4, 1, itm_bee_sting, 1, NULL); - RECIPE(itm_nailboard, CC_WEAPON, sk_null, sk_null, 0, 1000, true); + RECIPE(itm_nailboard, CC_WEAPON, NULL, NULL, 0, 1000, true); TOOL(itm_hatchet, -1, itm_hammer, -1, itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_2x4, 1, itm_stick, 1, NULL); COMP(itm_nail, 6, NULL); - RECIPE(itm_nailbat, CC_WEAPON, sk_null, sk_null, 0, 1000, true); + RECIPE(itm_nailbat, CC_WEAPON, NULL, NULL, 0, 1000, true); TOOL(itm_hatchet, -1, itm_hammer, -1, itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_bat, 1, NULL); COMP(itm_nail, 6, NULL); // molotovs use 250ml of flammable liquids - RECIPE(itm_molotov, CC_WEAPON, sk_null, sk_null, 0, 500, false); + RECIPE(itm_molotov, CC_WEAPON, NULL, NULL, 0, 500, false); COMP(itm_rag, 1, NULL); COMP(itm_bottle_glass, 1, itm_flask_glass, 1, NULL); COMP(itm_whiskey, 21, itm_vodka, 21, itm_rum, 21, itm_tequila, 21, itm_gasoline, 200, NULL); - RECIPE(itm_pipebomb, CC_WEAPON, sk_mechanics, sk_null, 1, 750, false); + RECIPE(itm_pipebomb, CC_WEAPON, Skill::skill("mechanics"), NULL, 1, 750, false); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_pipe, 1, NULL); COMP(itm_gasoline, 200, itm_shot_bird, 6, itm_shot_00, 2, itm_shot_slug, 2, NULL); COMP(itm_string_36, 1, itm_string_6, 1, NULL); - RECIPE(itm_shotgun_sawn, CC_WEAPON, sk_gun, sk_null, 1, 2000, false); + RECIPE(itm_shotgun_sawn, CC_WEAPON, Skill::skill("gun"), NULL, 1, 2000, false); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_shotgun_d, 1, itm_remington_870, 1, itm_mossberg_500, 1, NULL); - RECIPE(itm_saiga_sawn, CC_WEAPON, sk_gun, sk_null, 1, 2000, false); + RECIPE(itm_saiga_sawn, CC_WEAPON, Skill::skill("gun"), NULL, 1, 2000, false); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_saiga_12, 1, NULL); - RECIPE(itm_bolt_wood, CC_WEAPON, sk_mechanics, sk_archery, 1, 5000, false); + RECIPE(itm_bolt_wood, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("archery"), 1, 5000, false); TOOL(itm_hatchet, -1, itm_knife_steak, -1, itm_knife_butcher, -1, itm_knife_combat, -1, itm_machete, -1, itm_toolset, -1, NULL); COMP(itm_stick, 1, itm_broom, 1, itm_mop, 1, itm_2x4, 1, itm_bee_sting, 1, NULL); - RECIPE(itm_crossbow, CC_WEAPON, sk_mechanics, sk_archery, 3, 15000, true); + RECIPE(itm_crossbow, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("archery"), 3, 15000, true); TOOL(itm_wrench, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_2x4, 1, itm_stick, 4, NULL); COMP(itm_hose, 1, NULL); - RECIPE(itm_rifle_22, CC_WEAPON, sk_mechanics, sk_gun, 3, 12000, true); + RECIPE(itm_rifle_22, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 3, 12000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_pipe, 1, NULL); COMP(itm_2x4, 1, NULL); - RECIPE(itm_rifle_9mm, CC_WEAPON, sk_mechanics, sk_gun, 3, 14000, true); + RECIPE(itm_rifle_9mm, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 3, 14000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_pipe, 1, NULL); COMP(itm_2x4, 1, NULL); - RECIPE(itm_smg_9mm, CC_WEAPON, sk_mechanics, sk_gun, 5, 18000, true); + RECIPE(itm_smg_9mm, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 5, 18000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_hammer, -1, itm_rock, -1, itm_hatchet, -1, NULL); @@ -141,7 +141,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_2x4, 2, NULL); COMP(itm_nail, 4, NULL); - RECIPE(itm_smg_45, CC_WEAPON, sk_mechanics, sk_gun, 5, 20000, true); + RECIPE(itm_smg_45, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 5, 20000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_hammer, -1, itm_rock, -1, itm_hatchet, -1, NULL); @@ -149,7 +149,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_2x4, 2, NULL); COMP(itm_nail, 4, NULL); - RECIPE(itm_flamethrower_simple, CC_WEAPON, sk_mechanics, sk_gun, 6, 12000, true); + RECIPE(itm_flamethrower_simple, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 6, 12000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_pilot_light, 2, NULL); @@ -157,24 +157,24 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_hose, 2, NULL); COMP(itm_bottle_glass, 4, itm_bottle_plastic, 6, NULL); - RECIPE(itm_launcher_simple, CC_WEAPON, sk_mechanics, sk_launcher, 6, 6000, true); + RECIPE(itm_launcher_simple, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("launcher"), 6, 6000, true); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_pipe, 1, NULL); COMP(itm_2x4, 1, NULL); COMP(itm_nail, 1, NULL); - RECIPE(itm_shot_he, CC_WEAPON, sk_mechanics, sk_gun, 4, 2000, false); + RECIPE(itm_shot_he, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("gun"), 4, 2000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_superglue, 1, NULL); COMP(itm_shot_slug, 4, NULL); COMP(itm_gasoline, 200, NULL); - RECIPE(itm_acidbomb, CC_WEAPON, sk_cooking, sk_null, 1, 10000, false); + RECIPE(itm_acidbomb, CC_WEAPON, Skill::skill("cooking"), NULL, 1, 10000, false); TOOL(itm_hotplate, 5, itm_toolset, 1, NULL); COMP(itm_bottle_glass, 1, itm_flask_glass, 1, NULL); COMP(itm_battery, 500, NULL); - RECIPE(itm_grenade, CC_WEAPON, sk_mechanics, sk_null, 2, 5000, false); + RECIPE(itm_grenade, CC_WEAPON, Skill::skill("mechanics"), NULL, 2, 5000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_pilot_light, 1, NULL); COMP(itm_superglue, 1, itm_string_36, 1, NULL); @@ -183,14 +183,14 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_shot_bird, 6, itm_shot_00, 3, itm_shot_slug, 2, itm_gasoline, 200, itm_gunpowder, 72, NULL); - RECIPE(itm_chainsaw_off, CC_WEAPON, sk_mechanics, sk_null, 4, 20000, true); + RECIPE(itm_chainsaw_off, CC_WEAPON, Skill::skill("mechanics"), NULL, 4, 20000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_hammer, -1, itm_hatchet, -1, NULL); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_motor, 1, NULL); COMP(itm_chain, 1, NULL); - RECIPE(itm_smokebomb, CC_WEAPON, sk_cooking, sk_mechanics, 3, 7500, false); + RECIPE(itm_smokebomb, CC_WEAPON, Skill::skill("cooking"), Skill::skill("mechanics"), 3, 7500, false); TOOL(itm_screwdriver, -1, itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_water, 1, itm_water_clean, 1, itm_salt_water, 1, NULL); COMP(itm_candy, 1, itm_cola, 1, NULL); @@ -199,21 +199,21 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_superglue, 1, NULL); - RECIPE(itm_gasbomb, CC_WEAPON, sk_cooking, sk_mechanics, 4, 8000, false); + RECIPE(itm_gasbomb, CC_WEAPON, Skill::skill("cooking"), Skill::skill("mechanics"), 4, 8000, false); TOOL(itm_screwdriver, -1, itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_bleach, 2, NULL); COMP(itm_ammonia, 2, NULL); COMP(itm_canister_empty, 1, itm_can_food, 1, NULL); COMP(itm_superglue, 1, NULL); - RECIPE(itm_nx17, CC_WEAPON, sk_electronics, sk_mechanics, 8, 40000, true); + RECIPE(itm_nx17, CC_WEAPON, Skill::skill("electronics"), Skill::skill("mechanics"), 8, 40000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 6, itm_toolset, 6, NULL); COMP(itm_vacutainer, 1, NULL); COMP(itm_power_supply, 8, NULL); COMP(itm_amplifier, 8, NULL); - RECIPE(itm_mininuke, CC_WEAPON, sk_mechanics, sk_electronics, 10, 40000, true); + RECIPE(itm_mininuke, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics"), 10, 40000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_can_food, 2, itm_steel_chunk, 2, itm_canister_empty, 1, NULL); @@ -221,7 +221,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_battery, 2, NULL); COMP(itm_power_supply, 1, NULL); - RECIPE(itm_9mm, CC_AMMO, sk_gun, sk_mechanics, 2, 30000, false); + RECIPE(itm_9mm, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 2, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_9mm_casing, 50, NULL); @@ -229,7 +229,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 200, NULL); COMP(itm_lead, 200, NULL); - RECIPE(itm_9mmP, CC_AMMO, sk_gun, sk_mechanics, 4, 30000, false); + RECIPE(itm_9mmP, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 4, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_9mm_casing, 25, NULL); @@ -237,7 +237,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 125, NULL); COMP(itm_lead, 100, NULL); - RECIPE(itm_9mmP2, CC_AMMO, sk_gun, sk_mechanics, 6, 30000, false); + RECIPE(itm_9mmP2, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 6, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_9mm_casing, 10, NULL); @@ -245,7 +245,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 60, NULL); COMP(itm_lead, 40, NULL); - RECIPE(itm_38_special, CC_AMMO, sk_gun, sk_mechanics, 2, 30000, false); + RECIPE(itm_38_special, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 2, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_38_casing, 50, NULL); @@ -253,7 +253,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 250, NULL); COMP(itm_lead, 250, NULL); - RECIPE(itm_38_super, CC_AMMO, sk_gun, sk_mechanics, 4, 30000, false); + RECIPE(itm_38_super, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 4, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_38_casing, 25, NULL); @@ -261,7 +261,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 175, NULL); COMP(itm_lead, 125, NULL); - RECIPE(itm_40sw, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_40sw, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_40_casing, 50, NULL); @@ -269,7 +269,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 300, NULL); COMP(itm_lead, 300, NULL); - RECIPE(itm_10mm, CC_AMMO, sk_gun, sk_mechanics, 5, 30000, false); + RECIPE(itm_10mm, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 5, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_40_casing, 50, NULL); @@ -277,7 +277,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 400, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_44magnum, CC_AMMO, sk_gun, sk_mechanics, 4, 30000, false); + RECIPE(itm_44magnum, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 4, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_44_casing, 50, NULL); @@ -285,7 +285,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 500, NULL); COMP(itm_lead, 500, NULL); - RECIPE(itm_45_acp, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_45_acp, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_45_casing, 50, NULL); @@ -293,7 +293,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 500, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_45_super, CC_AMMO, sk_gun, sk_mechanics, 6, 30000, false); + RECIPE(itm_45_super, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 6, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_45_casing, 10, NULL); @@ -301,7 +301,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 120, NULL); COMP(itm_lead, 100, NULL); - RECIPE(itm_57mm, CC_AMMO, sk_gun, sk_mechanics, 4, 30000, false); + RECIPE(itm_57mm, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 4, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_57mm_casing, 100, NULL); @@ -309,7 +309,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 400, NULL); COMP(itm_lead, 200, NULL); - RECIPE(itm_46mm, CC_AMMO, sk_gun, sk_mechanics, 4, 30000, false); + RECIPE(itm_46mm, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 4, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_46mm_casing, 100, NULL); @@ -317,7 +317,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 400, NULL); COMP(itm_lead, 200, NULL); - RECIPE(itm_762_m43, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_762_m43, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_762_casing, 80, NULL); @@ -325,7 +325,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 560, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_762_m87, CC_AMMO, sk_gun, sk_mechanics, 5, 30000, false); + RECIPE(itm_762_m87, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 5, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_762_casing, 80, NULL); @@ -333,7 +333,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 640, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_223, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_223, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_223_casing, 40, NULL); @@ -341,7 +341,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 160, NULL); COMP(itm_lead, 80, NULL); - RECIPE(itm_556, CC_AMMO, sk_gun, sk_mechanics, 5, 30000, false); + RECIPE(itm_556, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 5, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_223_casing, 40, NULL); @@ -349,7 +349,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 240, NULL); COMP(itm_lead, 80, NULL); - RECIPE(itm_556_incendiary, CC_AMMO, sk_gun, sk_mechanics, 6, 30000, false); + RECIPE(itm_556_incendiary, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 6, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_223_casing, 30, NULL); @@ -357,7 +357,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 180, NULL); COMP(itm_incendiary, 60, NULL); - RECIPE(itm_270, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_270, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_3006_casing, 20, NULL); @@ -365,7 +365,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 200, NULL); COMP(itm_lead, 100, NULL); - RECIPE(itm_3006, CC_AMMO, sk_gun, sk_mechanics, 5, 30000, false); + RECIPE(itm_3006, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 5, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_3006_casing, 10, NULL); @@ -373,7 +373,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 120, NULL); COMP(itm_lead, 80, NULL); - RECIPE(itm_3006_incendiary, CC_AMMO, sk_gun, sk_mechanics, 7, 30000, false); + RECIPE(itm_3006_incendiary, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 7, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_3006_casing, 5, NULL); @@ -381,7 +381,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 60, NULL); COMP(itm_incendiary, 40, NULL); - RECIPE(itm_308, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_308, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_308_casing, 20, NULL); @@ -389,7 +389,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 160, NULL); COMP(itm_lead, 120, NULL); - RECIPE(itm_762_51, CC_AMMO, sk_gun, sk_mechanics, 5, 30000, false); + RECIPE(itm_762_51, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 5, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_308_casing, 20, NULL); @@ -397,7 +397,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 200, NULL); COMP(itm_lead, 120, NULL); - RECIPE(itm_762_51_incendiary, CC_AMMO, sk_gun, sk_mechanics, 6, 30000, false); + RECIPE(itm_762_51_incendiary, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 6, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_308_casing, 10, NULL); @@ -405,7 +405,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 100, NULL); COMP(itm_incendiary, 60, NULL); - RECIPE(itm_shot_bird, CC_AMMO, sk_gun, sk_mechanics, 2, 30000, false); + RECIPE(itm_shot_bird, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 2, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_shot_hull, 25, NULL); @@ -413,7 +413,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 300, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_shot_00, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_shot_00, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_shot_hull, 25, NULL); @@ -421,7 +421,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_gunpowder, 600, NULL); COMP(itm_lead, 400, NULL); - RECIPE(itm_shot_slug, CC_AMMO, sk_gun, sk_mechanics, 3, 30000, false); + RECIPE(itm_shot_slug, CC_AMMO, Skill::skill("gun"), Skill::skill("mechanics"), 3, 30000, false); TOOL(itm_press, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 4, itm_press, 2, NULL); COMP(itm_shot_hull, 25, NULL); @@ -430,7 +430,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, sk_null, sk_null, 0, 100, true); COMP(itm_lead, 400, NULL); /* * We need a some Chemicals which arn't implemented to realistically craft this! -RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); +RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics"), 4, 8000); TOOL(itm_screwdriver, -1, NULL); COMP(itm_can_food, 1, itm_steel_chunk, 1, itm_canister_empty, 1, NULL); COMP(itm_battery, 1, NULL); @@ -441,71 +441,71 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); // FOOD - RECIPE(itm_water_clean, CC_DRINK, sk_cooking, sk_null, 0, 5000, false); + RECIPE(itm_water_clean, CC_DRINK, Skill::skill("cooking"), NULL, 0, 5000, false); TOOL(itm_hotplate, 3, itm_toolset, 1, itm_fire, -1, NULL); TOOL(itm_pan, -1, itm_pot, -1, NULL); COMP(itm_water, 1, NULL); - RECIPE(itm_meat_cooked, CC_FOOD, sk_cooking, sk_null, 0, 5000, false); + RECIPE(itm_meat_cooked, CC_FOOD, Skill::skill("cooking"), NULL, 0, 5000, false); TOOL(itm_hotplate, 7, itm_toolset, 4, itm_fire, -1, NULL); TOOL(itm_pan, -1, itm_pot, -1, itm_spear_wood, -1, NULL); COMP(itm_meat, 1, NULL); - RECIPE(itm_dogfood, CC_FOOD, sk_cooking, sk_null, 4, 10000, false); + RECIPE(itm_dogfood, CC_FOOD, Skill::skill("cooking"), NULL, 4, 10000, false); TOOL(itm_hotplate, 6, itm_toolset, 3, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_meat, 1, NULL); COMP(itm_veggy,1, NULL); COMP(itm_water,1, NULL); - RECIPE(itm_veggy_cooked, CC_FOOD, sk_cooking, sk_null, 0, 4000, false); + RECIPE(itm_veggy_cooked, CC_FOOD, Skill::skill("cooking"), NULL, 0, 4000, false); TOOL(itm_hotplate, 5, itm_toolset, 3, itm_fire, -1, NULL); TOOL(itm_pan, -1, itm_pot, -1, itm_spear_wood, -1, NULL); COMP(itm_veggy, 1, NULL); - RECIPE(itm_spaghetti_cooked, CC_FOOD, sk_cooking, sk_null, 0, 10000, false); + RECIPE(itm_spaghetti_cooked, CC_FOOD, Skill::skill("cooking"), NULL, 0, 10000, false); TOOL(itm_hotplate, 4, itm_toolset, 2, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_spaghetti_raw, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_cooked_dinner, CC_FOOD, sk_cooking, sk_null, 0, 5000, false); + RECIPE(itm_cooked_dinner, CC_FOOD, Skill::skill("cooking"), NULL, 0, 5000, false); TOOL(itm_hotplate, 3, itm_toolset, 2, itm_fire, -1, NULL); COMP(itm_frozen_dinner, 1, NULL); - RECIPE(itm_macaroni_cooked, CC_FOOD, sk_cooking, sk_null, 1, 10000, false); + RECIPE(itm_macaroni_cooked, CC_FOOD, Skill::skill("cooking"), NULL, 1, 10000, false); TOOL(itm_hotplate, 4, itm_toolset, 2, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_macaroni_raw, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_potato_baked, CC_FOOD, sk_cooking, sk_null, 1, 15000, false); + RECIPE(itm_potato_baked, CC_FOOD, Skill::skill("cooking"), NULL, 1, 15000, false); TOOL(itm_hotplate, 3, itm_toolset, 2, itm_fire, -1, NULL); TOOL(itm_pan, -1, itm_pot, -1, NULL); COMP(itm_potato_raw, 1, NULL); - RECIPE(itm_tea, CC_DRINK, sk_cooking, sk_null, 0, 4000, false); + RECIPE(itm_tea, CC_DRINK, Skill::skill("cooking"), NULL, 0, 4000, false); TOOL(itm_hotplate, 2, itm_toolset, 1, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_tea_raw, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_coffee, CC_DRINK, sk_cooking, sk_null, 0, 4000, false); + RECIPE(itm_coffee, CC_DRINK, Skill::skill("cooking"), NULL, 0, 4000, false); TOOL(itm_hotplate, 2, itm_toolset, 1, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_coffee_raw, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_oj, CC_DRINK, sk_cooking, sk_null, 1, 5000, false); + RECIPE(itm_oj, CC_DRINK, Skill::skill("cooking"), NULL, 1, 5000, false); TOOL(itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_orange, 2, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_apple_cider, CC_DRINK, sk_cooking, sk_null, 2, 7000, false); + RECIPE(itm_apple_cider, CC_DRINK, Skill::skill("cooking"), NULL, 2, 7000, false); TOOL(itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_apple, 3, NULL); - RECIPE(itm_long_island, CC_DRINK, sk_cooking, sk_null, 1, 7000, false); + RECIPE(itm_long_island, CC_DRINK, Skill::skill("cooking"), NULL, 1, 7000, false); COMP(itm_cola, 1, NULL); COMP(itm_vodka, 1, NULL); COMP(itm_gin, 1, NULL); @@ -513,36 +513,36 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_tequila, 1, NULL); COMP(itm_triple_sec, 1, NULL); - RECIPE(itm_jerky, CC_FOOD, sk_cooking, sk_null, 3, 30000, false); + RECIPE(itm_jerky, CC_FOOD, Skill::skill("cooking"), NULL, 3, 30000, false); TOOL(itm_hotplate, 10, itm_toolset, 5, itm_fire, -1, NULL); COMP(itm_salt_water, 1, itm_salt, 4, NULL); COMP(itm_meat, 1, NULL); - RECIPE(itm_V8, CC_FOOD, sk_cooking, sk_null, 2, 5000, false); + RECIPE(itm_V8, CC_FOOD, Skill::skill("cooking"), NULL, 2, 5000, false); COMP(itm_tomato, 1, NULL); COMP(itm_broccoli, 1, NULL); COMP(itm_zucchini, 1, NULL); - RECIPE(itm_broth, CC_FOOD, sk_cooking, sk_null, 2, 10000, false); + RECIPE(itm_broth, CC_FOOD, Skill::skill("cooking"), NULL, 2, 10000, false); TOOL(itm_hotplate, 5, itm_toolset, 3, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); COMP(itm_broccoli, 1, itm_zucchini, 1, itm_veggy, 1, NULL); - RECIPE(itm_soup, CC_FOOD, sk_cooking, sk_null, 2, 10000, false); + RECIPE(itm_soup, CC_FOOD, Skill::skill("cooking"), NULL, 2, 10000, false); TOOL(itm_hotplate, 5, itm_toolset, 3, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_broth, 2, NULL); COMP(itm_macaroni_raw, 1, itm_potato_raw, 1, NULL); COMP(itm_tomato, 2, itm_broccoli, 2, itm_zucchini, 2, itm_veggy, 2, NULL); - RECIPE(itm_bread, CC_FOOD, sk_cooking, sk_null, 4, 20000, false); + RECIPE(itm_bread, CC_FOOD, Skill::skill("cooking"), NULL, 4, 20000, false); TOOL(itm_hotplate, 8, itm_toolset, 4, itm_fire, -1, NULL); TOOL(itm_pot, -1, NULL); COMP(itm_flour, 3, NULL); COMP(itm_water, 2, itm_water_clean, 2, NULL); - RECIPE(itm_pie, CC_FOOD, sk_cooking, sk_null, 3, 25000, false); + RECIPE(itm_pie, CC_FOOD, Skill::skill("cooking"), NULL, 3, 25000, false); TOOL(itm_hotplate, 6, itm_toolset, 3, itm_fire, -1, NULL); TOOL(itm_pan, -1, NULL); COMP(itm_flour, 2, NULL); @@ -550,7 +550,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_sugar, 2, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_pizza, CC_FOOD, sk_cooking, sk_null, 3, 20000, false); + RECIPE(itm_pizza, CC_FOOD, Skill::skill("cooking"), NULL, 3, 20000, false); TOOL(itm_hotplate, 8, itm_toolset, 4, itm_fire, -1, NULL); TOOL(itm_pan, -1, NULL); COMP(itm_flour, 2, NULL); @@ -558,31 +558,31 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_sauce_pesto, 1, itm_sauce_red, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_meth, CC_CHEM, sk_cooking, sk_null, 5, 20000, false); + RECIPE(itm_meth, CC_CHEM, Skill::skill("cooking"), NULL, 5, 20000, false); TOOL(itm_hotplate, 15, itm_toolset, 8, itm_fire, -1, NULL); TOOL(itm_bottle_glass, -1, itm_hose, -1, NULL); COMP(itm_dayquil, 2, itm_royal_jelly, 1, NULL); COMP(itm_aspirin, 40, NULL); COMP(itm_caffeine, 20, itm_adderall, 5, itm_energy_drink, 2, NULL); - RECIPE(itm_royal_jelly, CC_CHEM, sk_cooking, sk_null, 5, 5000, false); + RECIPE(itm_royal_jelly, CC_CHEM, Skill::skill("cooking"), NULL, 5, 5000, false); COMP(itm_honeycomb, 1, NULL); COMP(itm_bleach, 2, itm_purifier, 1, NULL); - RECIPE(itm_heroin, CC_CHEM, sk_cooking, sk_null, 6, 2000, false); + RECIPE(itm_heroin, CC_CHEM, Skill::skill("cooking"), NULL, 6, 2000, false); TOOL(itm_hotplate, 3, itm_toolset, 2, itm_fire, -1, NULL); TOOL(itm_pan, -1, itm_pot, -1, NULL); COMP(itm_salt_water, 1, itm_salt, 4, NULL); COMP(itm_oxycodone, 40, NULL); - RECIPE(itm_mutagen, CC_CHEM, sk_cooking, sk_firstaid, 8, 10000, false); + RECIPE(itm_mutagen, CC_CHEM, Skill::skill("cooking"), Skill::skill("firstaid"), 8, 10000, false); TOOL(itm_hotplate, 25, itm_toolset, 12, itm_fire, -1, NULL); COMP(itm_meat_tainted, 3, itm_veggy_tainted, 5, itm_fetus, 1, itm_arm, 2, itm_leg, 2, NULL); COMP(itm_bleach, 2, NULL); COMP(itm_ammonia, 1, NULL); - RECIPE(itm_purifier, CC_CHEM, sk_cooking, sk_firstaid, 9, 10000, false); + RECIPE(itm_purifier, CC_CHEM, Skill::skill("cooking"), Skill::skill("firstaid"), 9, 10000, false); TOOL(itm_hotplate, 25, itm_toolset, 12, itm_fire, -1, NULL); COMP(itm_royal_jelly, 4, itm_mutagen, 2, NULL); COMP(itm_bleach, 3, NULL); @@ -590,51 +590,51 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); // ELECTRONICS - RECIPE(itm_antenna, CC_ELECTRONIC, sk_null, sk_null, 0, 3000, false); + RECIPE(itm_antenna, CC_ELECTRONIC, NULL, NULL, 0, 3000, false); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_knife_butter, 2, NULL); - RECIPE(itm_amplifier, CC_ELECTRONIC, sk_electronics, sk_null, 1, 4000, false); + RECIPE(itm_amplifier, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 1, 4000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_transponder, 2, NULL); - RECIPE(itm_power_supply, CC_ELECTRONIC, sk_electronics, sk_null, 1, 6500, false); + RECIPE(itm_power_supply, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 1, 6500, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 3, itm_toolset, 3, NULL); COMP(itm_amplifier, 2, NULL); COMP(itm_cable, 20, NULL); - RECIPE(itm_receiver, CC_ELECTRONIC, sk_electronics, sk_null, 2, 12000, true); + RECIPE(itm_receiver, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 2, 12000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 4, itm_toolset, 4, NULL); COMP(itm_amplifier, 2, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_transponder, CC_ELECTRONIC, sk_electronics, sk_null, 2, 14000, true); + RECIPE(itm_transponder, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 2, 14000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 7, itm_toolset, 7, NULL); COMP(itm_receiver, 3, NULL); COMP(itm_cable, 5, NULL); - RECIPE(itm_flashlight, CC_ELECTRONIC, sk_electronics, sk_null, 1, 10000, true); + RECIPE(itm_flashlight, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 1, 10000, true); COMP(itm_amplifier, 1, NULL); COMP(itm_scrap, 4, itm_can_drink, 1, itm_bottle_glass, 1, itm_bottle_plastic, 1, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_soldering_iron, CC_ELECTRONIC, sk_electronics, sk_null, 1, 20000, true); + RECIPE(itm_soldering_iron, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 1, 20000, true); COMP(itm_antenna, 1, itm_screwdriver, 1, itm_xacto, 1, itm_knife_butter, 1, NULL); COMP(itm_power_supply, 1, NULL); COMP(itm_scrap, 2, NULL); - RECIPE(itm_battery, CC_ELECTRONIC, sk_electronics, sk_mechanics, 2, 5000, false); + RECIPE(itm_battery, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("mechanics"), 2, 5000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_ammonia, 1, itm_lemon, 1, NULL); COMP(itm_steel_chunk, 1, itm_knife_butter, 1, itm_knife_steak, 1, itm_bolt_steel, 1, itm_scrap, 1, NULL); COMP(itm_can_drink, 1, itm_can_food, 1, NULL); - RECIPE(itm_coilgun, CC_WEAPON, sk_electronics, sk_null, 3, 25000, true); + RECIPE(itm_coilgun, CC_WEAPON, Skill::skill("electronics"), NULL, 3, 25000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 10, itm_toolset, 10, NULL); COMP(itm_pipe, 1, NULL); @@ -643,7 +643,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 6, NULL); COMP(itm_cable, 20, NULL); - RECIPE(itm_radio, CC_ELECTRONIC, sk_electronics, sk_null, 2, 25000, true); + RECIPE(itm_radio, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 2, 25000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 10, itm_toolset, 10, NULL); COMP(itm_receiver, 1, NULL); @@ -651,7 +651,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 5, NULL); COMP(itm_cable, 7, NULL); - RECIPE(itm_water_purifier, CC_ELECTRONIC, sk_mechanics,sk_electronics,3,25000, true); + RECIPE(itm_water_purifier, CC_ELECTRONIC, Skill::skill("mechanics"),Skill::skill("electronics"),3,25000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_element, 2, NULL); COMP(itm_bottle_glass, 2, itm_bottle_plastic, 5, NULL); @@ -659,7 +659,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 3, NULL); COMP(itm_cable, 5, NULL); - RECIPE(itm_hotplate, CC_ELECTRONIC, sk_electronics, sk_null, 3, 30000, true); + RECIPE(itm_hotplate, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 3, 30000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_element, 1, NULL); COMP(itm_amplifier, 1, NULL); @@ -667,14 +667,14 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); itm_knife_butter, 6, itm_muffler, 1, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_tazer, CC_ELECTRONIC, sk_electronics, sk_null, 3, 25000, true); + RECIPE(itm_tazer, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 3, 25000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 10, itm_toolset, 10, NULL); COMP(itm_amplifier, 1, NULL); COMP(itm_power_supply, 1, NULL); COMP(itm_scrap, 2, NULL); - RECIPE(itm_two_way_radio, CC_ELECTRONIC, sk_electronics, sk_null, 4, 30000, true); + RECIPE(itm_two_way_radio, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 4, 30000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 14, itm_toolset, 14, NULL); COMP(itm_amplifier, 1, NULL); @@ -684,7 +684,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 5, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_electrohack, CC_ELECTRONIC, sk_electronics, sk_computer, 4, 35000, true); + RECIPE(itm_electrohack, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("computer"), 4, 35000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 10, itm_toolset, 10, NULL); COMP(itm_processor, 1, NULL); @@ -692,7 +692,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 4, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_EMPbomb, CC_ELECTRONIC, sk_electronics, sk_null, 4, 32000, false); + RECIPE(itm_EMPbomb, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 4, 32000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 6, itm_toolset, 6, NULL); COMP(itm_superglue, 1, itm_string_36, 1, NULL); @@ -700,7 +700,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_power_supply, 1, itm_amplifier, 1, NULL); COMP(itm_cable, 5, NULL); - RECIPE(itm_mp3, CC_ELECTRONIC, sk_electronics, sk_computer, 5, 40000, true); + RECIPE(itm_mp3, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("computer"), 5, 40000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 5, itm_toolset, 5, NULL); COMP(itm_superglue, 1, NULL); @@ -708,7 +708,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_amplifier, 1, NULL); COMP(itm_cable, 2, NULL); - RECIPE(itm_geiger_off, CC_ELECTRONIC, sk_electronics, sk_null, 5, 35000, true); + RECIPE(itm_geiger_off, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 5, 35000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 14, itm_toolset, 14, NULL); COMP(itm_power_supply, 1, NULL); @@ -716,7 +716,7 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 6, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_UPS_off, CC_ELECTRONIC, sk_electronics, sk_null, 5, 45000, true); + RECIPE(itm_UPS_off, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 5, 45000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 24, itm_toolset, 24, NULL); COMP(itm_power_supply, 4, NULL); @@ -724,14 +724,14 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_scrap, 4, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_bionics_battery, CC_ELECTRONIC, sk_electronics, sk_null, 6, 50000, true); + RECIPE(itm_bionics_battery, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 6, 50000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 20, itm_toolset, 20, NULL); COMP(itm_power_supply, 6, itm_UPS_off, 1, NULL); COMP(itm_amplifier, 4, NULL); COMP(itm_plut_cell, 1, NULL); - RECIPE(itm_teleporter, CC_ELECTRONIC, sk_electronics, sk_null, 8, 50000, true); + RECIPE(itm_teleporter, CC_ELECTRONIC, Skill::skill("electronics"), NULL, 8, 50000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 16, itm_toolset, 16, NULL); @@ -743,118 +743,118 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); // ARMOR - RECIPE(itm_thread, CC_ARMOR, sk_tailor, sk_null, 1, 3000, false); + RECIPE(itm_thread, CC_ARMOR, Skill::skill("tailor"), NULL, 1, 3000, false); TOOL(itm_knife_combat, -1, itm_knife_steak, -1, itm_scissors, -1, NULL); COMP(itm_string_6, 1, NULL); - RECIPE(itm_mocassins, CC_ARMOR, sk_tailor, sk_null, 1, 30000, false); + RECIPE(itm_mocassins, CC_ARMOR, Skill::skill("tailor"), NULL, 1, 30000, false); TOOL(itm_sewing_kit, 5, NULL); COMP(itm_fur, 2, NULL); - RECIPE(itm_boots_fit, CC_ARMOR, sk_tailor, sk_null, 2, 35000, false); + RECIPE(itm_boots_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 2, 35000, false); TOOL(itm_sewing_kit, 10, NULL); COMP(itm_leather, 4, NULL); - RECIPE(itm_jeans_fit, CC_ARMOR, sk_tailor, sk_null, 2, 45000, false); + RECIPE(itm_jeans_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 2, 45000, false); TOOL(itm_sewing_kit, 10, NULL); COMP(itm_rag, 6, NULL); - RECIPE(itm_pants_cargo_fit, CC_ARMOR, sk_tailor, sk_null, 3, 48000, false); + RECIPE(itm_pants_cargo_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 48000, false); TOOL(itm_sewing_kit, 16, NULL); COMP(itm_rag, 8, NULL); - RECIPE(itm_pants_leather, CC_ARMOR, sk_tailor, sk_null, 4, 50000, false); + RECIPE(itm_pants_leather, CC_ARMOR, Skill::skill("tailor"), NULL, 4, 50000, false); TOOL(itm_sewing_kit, 10, NULL); COMP(itm_leather, 10, NULL); - RECIPE(itm_tank_top, CC_ARMOR, sk_tailor, sk_null, 2, 38000, false); + RECIPE(itm_tank_top, CC_ARMOR, Skill::skill("tailor"), NULL, 2, 38000, false); TOOL(itm_sewing_kit, 4, NULL); COMP(itm_rag, 4, NULL); - RECIPE(itm_hoodie_fit, CC_ARMOR, sk_tailor, sk_null, 3, 40000, false); + RECIPE(itm_hoodie_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 40000, false); TOOL(itm_sewing_kit, 14, NULL); COMP(itm_rag, 12, NULL); - RECIPE(itm_trenchcoat_fit, CC_ARMOR, sk_tailor, sk_null, 3, 42000, false); + RECIPE(itm_trenchcoat_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 42000, false); TOOL(itm_sewing_kit, 24, NULL); COMP(itm_rag, 11, NULL); - RECIPE(itm_coat_fur, CC_ARMOR, sk_tailor, sk_null, 4, 100000, false); + RECIPE(itm_coat_fur, CC_ARMOR, Skill::skill("tailor"), NULL, 4, 100000, false); TOOL(itm_sewing_kit, 20, NULL); COMP(itm_fur, 10, NULL); - RECIPE(itm_jacket_leather_fit, CC_ARMOR, sk_tailor, sk_null, 5, 150000, false); + RECIPE(itm_jacket_leather_fit, CC_ARMOR, Skill::skill("tailor"), NULL, 5, 150000, false); TOOL(itm_sewing_kit, 30, NULL); COMP(itm_leather, 16, NULL); - RECIPE(itm_gloves_light, CC_ARMOR, sk_tailor, sk_null, 1, 10000, false); + RECIPE(itm_gloves_light, CC_ARMOR, Skill::skill("tailor"), NULL, 1, 10000, false); TOOL(itm_sewing_kit, 2, NULL); COMP(itm_rag, 2, NULL); - RECIPE(itm_gloves_fingerless, CC_ARMOR, sk_tailor, sk_null, 0, 16000, false); + RECIPE(itm_gloves_fingerless, CC_ARMOR, Skill::skill("tailor"), NULL, 0, 16000, false); TOOL(itm_scissors, -1, itm_knife_combat, -1, itm_knife_steak, -1, NULL); COMP(itm_gloves_leather, 1, NULL); - RECIPE(itm_gloves_leather, CC_ARMOR, sk_tailor, sk_null, 2, 16000, false); + RECIPE(itm_gloves_leather, CC_ARMOR, Skill::skill("tailor"), NULL, 2, 16000, false); TOOL(itm_sewing_kit, 6, NULL); COMP(itm_leather, 2, NULL); - RECIPE(itm_mask_filter, CC_ARMOR, sk_mechanics, sk_tailor, 1, 5000, true); + RECIPE(itm_mask_filter, CC_ARMOR, Skill::skill("mechanics"), Skill::skill("tailor"), 1, 5000, true); COMP(/*itm_filter, 1, */itm_bag_plastic, 2, itm_bottle_plastic, 1, NULL); COMP(itm_rag, 2, itm_muffler, 1, itm_bandana, 2, itm_wrapper, 4, NULL); - RECIPE(itm_mask_gas, CC_ARMOR, sk_tailor, sk_null, 3, 20000, true); + RECIPE(itm_mask_gas, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 20000, true); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_goggles_ski, 1, itm_goggles_swim, 2, NULL); COMP(/*itm_filter, 3, */itm_mask_filter, 3, itm_muffler, 1, NULL); COMP(itm_hose, 1, NULL); - RECIPE(itm_glasses_safety, CC_ARMOR, sk_tailor, sk_null, 1, 8000, false); + RECIPE(itm_glasses_safety, CC_ARMOR, Skill::skill("tailor"), NULL, 1, 8000, false); TOOL(itm_scissors, -1, itm_xacto, -1, itm_knife_steak, -1, itm_knife_combat, -1, itm_toolset, -1, NULL); COMP(itm_string_36, 1, itm_string_6, 2, NULL); COMP(itm_bottle_plastic, 1, NULL); - RECIPE(itm_goggles_nv, CC_ARMOR, sk_electronics, sk_tailor, 5, 40000, true); + RECIPE(itm_goggles_nv, CC_ARMOR, Skill::skill("electronics"), Skill::skill("tailor"), 5, 40000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_goggles_ski, 1, itm_goggles_welding, 1, itm_mask_gas, 1, NULL); COMP(itm_power_supply, 1, NULL); COMP(itm_amplifier, 3, NULL); COMP(itm_scrap, 5, NULL); - RECIPE(itm_hat_fur, CC_ARMOR, sk_tailor, sk_null, 2, 40000, false); + RECIPE(itm_hat_fur, CC_ARMOR, Skill::skill("tailor"), NULL, 2, 40000, false); TOOL(itm_sewing_kit, 8, NULL); COMP(itm_fur, 3, NULL); - RECIPE(itm_armguard_metal, CC_ARMOR, sk_tailor, sk_null, 4, 30000, false); + RECIPE(itm_armguard_metal, CC_ARMOR, Skill::skill("tailor"), NULL, 4, 30000, false); TOOL(itm_hammer, -1, itm_toolset, -1, NULL); COMP(itm_string_36, 1, itm_string_6, 4, NULL); COMP(itm_steel_chunk, 2, NULL); - RECIPE(itm_armguard_chitin, CC_ARMOR, sk_tailor, sk_null, 3, 30000, false); + RECIPE(itm_armguard_chitin, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 30000, false); COMP(itm_string_36, 1, itm_string_6, 4, NULL); COMP(itm_chitin_piece, 2, NULL); - RECIPE(itm_helmet_chitin, CC_ARMOR, sk_tailor, sk_null, 6, 60000, false); + RECIPE(itm_helmet_chitin, CC_ARMOR, Skill::skill("tailor"), NULL, 6, 60000, false); COMP(itm_string_36, 1, itm_string_6, 5, NULL); COMP(itm_chitin_piece, 5, NULL); - RECIPE(itm_armor_chitin, CC_ARMOR, sk_tailor, sk_null, 7, 100000, false); + RECIPE(itm_armor_chitin, CC_ARMOR, Skill::skill("tailor"), NULL, 7, 100000, false); COMP(itm_string_36, 2, itm_string_6, 12, NULL); COMP(itm_chitin_piece, 15, NULL); - RECIPE(itm_backpack, CC_ARMOR, sk_tailor, sk_null, 3, 50000, false); + RECIPE(itm_backpack, CC_ARMOR, Skill::skill("tailor"), NULL, 3, 50000, false); TOOL(itm_sewing_kit, 20, NULL); COMP(itm_rag, 20, itm_fur, 16, itm_leather, 12, NULL); // MISC - RECIPE(itm_curtain, CC_MISC, sk_null, sk_null, 0, 10000, false); + RECIPE(itm_curtain, CC_MISC, NULL, NULL, 0, 10000, false); TOOL(itm_sewing_kit, 50, NULL); COMP(itm_rag, 20, NULL); COMP(itm_stick, 1, itm_pool_cue, 1, itm_spear_wood, 1, itm_2x4, 1, NULL); - RECIPE(itm_vehicle_controls, CC_MISC, sk_mechanics, sk_null, 3, 30000, true); + RECIPE(itm_vehicle_controls, CC_MISC, Skill::skill("mechanics"), NULL, 3, 30000, true); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); TOOL(itm_hammer, -1, itm_toolset, -1, NULL); TOOL(itm_welder, 50, itm_toolset, 5, NULL); @@ -863,125 +863,125 @@ RECIPE(itm_c4, CC_WEAPON, sk_mechanics, sk_electronics, 4, 8000); COMP(itm_steel_chunk, 12, NULL); COMP(itm_wire, 3, NULL); - RECIPE(itm_string_36, CC_MISC, sk_null, sk_null, 0, 5000, false); + RECIPE(itm_string_36, CC_MISC, NULL, NULL, 0, 5000, false); COMP(itm_string_6, 6, NULL); - RECIPE(itm_rope_6, CC_MISC, sk_tailor, sk_null, 2, 5000, false); + RECIPE(itm_rope_6, CC_MISC, Skill::skill("tailor"), NULL, 2, 5000, false); COMP(itm_string_36, 6, NULL); - RECIPE(itm_rope_30, CC_MISC, sk_tailor, sk_null, 2, 5000, false); + RECIPE(itm_rope_30, CC_MISC, Skill::skill("tailor"), NULL, 2, 5000, false); COMP(itm_rope_6, 5, NULL); - RECIPE(itm_torch, CC_MISC, sk_null, sk_null, 0, 2000, false); + RECIPE(itm_torch, CC_MISC, NULL, NULL, 0, 2000, false); COMP(itm_stick, 1, itm_2x4, 1, itm_splinter, 1, itm_pool_cue, 1, itm_torch_done, 1, NULL); COMP(itm_gasoline, 1, itm_vodka, 1, itm_rum, 1, itm_whiskey, 1, itm_tequila, 1, NULL); COMP(itm_rag, 1, NULL); - RECIPE(itm_candle, CC_MISC, sk_null, sk_null, 0, 5000, false); + RECIPE(itm_candle, CC_MISC, NULL, NULL, 0, 5000, false); TOOL(itm_lighter, 5, itm_fire, -1, itm_toolset, 1, NULL); COMP(itm_can_food, -1, NULL); COMP(itm_wax, 2, NULL); COMP(itm_string_6, 1, NULL); - RECIPE(itm_crack, CC_MISC, sk_cooking, sk_null, 4, 30000,false); + RECIPE(itm_crack, CC_MISC, Skill::skill("cooking"), NULL, 4, 30000,false); TOOL(itm_pot, -1, NULL); TOOL(itm_fire, -1, itm_hotplate, 8, itm_toolset, 2, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); COMP(itm_coke, 12, NULL); COMP(itm_ammonia, 1, NULL); - RECIPE(itm_poppy_sleep, CC_MISC, sk_cooking, sk_survival, 2, 5000, false); + RECIPE(itm_poppy_sleep, CC_MISC, Skill::skill("cooking"), Skill::skill("survival"), 2, 5000, false); TOOL(itm_pot, -1, itm_rock, -1, NULL); TOOL(itm_fire, -1, NULL); COMP(itm_poppy_bud, 2, NULL); COMP(itm_poppy_flower, 1, NULL); - RECIPE(itm_poppy_pain, CC_MISC, sk_cooking, sk_survival, 2, 5000, false); + RECIPE(itm_poppy_pain, CC_MISC, Skill::skill("cooking"), Skill::skill("survival"), 2, 5000, false); TOOL(itm_pot, -1, itm_rock, -1, NULL); TOOL(itm_fire, -1, NULL); COMP(itm_poppy_bud, 2, NULL); COMP(itm_poppy_flower, 2, NULL); - RECIPE(itm_carspike, CC_MISC, sk_null, sk_null, 0, 3000, false); + RECIPE(itm_carspike, CC_MISC, NULL, NULL, 0, 3000, false); TOOL(itm_hammer, -1, itm_toolset, -1, NULL); COMP(itm_spear_knife, 1, itm_knife_combat, 1, itm_knife_steak, 3, itm_steel_chunk, 3, itm_scrap, 9, NULL); - RECIPE(itm_carblade, CC_MISC, sk_null, sk_null, 0, 3000, false); + RECIPE(itm_carblade, CC_MISC, NULL, NULL, 0, 3000, false); TOOL(itm_hammer, -1, itm_toolset, -1, NULL); COMP(itm_broadsword, 1, itm_machete, 1, itm_pike, 1, itm_lawnmower_blade, 1, NULL); - RECIPE(itm_superglue, CC_MISC, sk_cooking, sk_null, 2, 12000, false); + RECIPE(itm_superglue, CC_MISC, Skill::skill("cooking"), NULL, 2, 12000, false); TOOL(itm_hotplate, 5, itm_toolset, 1, itm_fire, -1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); COMP(itm_bleach, 1, itm_ant_egg, 1, NULL); - RECIPE(itm_steel_lump, CC_MISC, sk_mechanics, sk_null, 0, 5000, true); + RECIPE(itm_steel_lump, CC_MISC, Skill::skill("mechanics"), NULL, 0, 5000, true); TOOL(itm_welder, 20, NULL); COMP(itm_steel_chunk, 4, NULL); - RECIPE(itm_frame, CC_MISC, sk_mechanics, sk_null, 1, 8000, true); + RECIPE(itm_frame, CC_MISC, Skill::skill("mechanics"), NULL, 1, 8000, true); TOOL(itm_welder, 50, NULL); COMP(itm_steel_lump, 3, NULL); - RECIPE(itm_steel_plate, CC_MISC, sk_mechanics, sk_null,4, 12000, true); + RECIPE(itm_steel_plate, CC_MISC, Skill::skill("mechanics"), NULL,4, 12000, true); TOOL(itm_welder, 100, NULL); COMP(itm_steel_lump, 8, NULL); - RECIPE(itm_spiked_plate, CC_MISC, sk_mechanics, sk_null, 4, 12000, true); + RECIPE(itm_spiked_plate, CC_MISC, Skill::skill("mechanics"), NULL, 4, 12000, true); TOOL(itm_welder, 120, NULL); COMP(itm_steel_lump, 8, NULL); COMP(itm_steel_chunk, 4, itm_scrap, 8, NULL); - RECIPE(itm_hard_plate, CC_MISC, sk_mechanics, sk_null, 4, 12000, true); + RECIPE(itm_hard_plate, CC_MISC, Skill::skill("mechanics"), NULL, 4, 12000, true); TOOL(itm_welder, 300, NULL); COMP(itm_steel_lump, 24, NULL); - RECIPE(itm_crowbar, CC_MISC, sk_mechanics, sk_null, 1, 1000, false); + RECIPE(itm_crowbar, CC_MISC, Skill::skill("mechanics"), NULL, 1, 1000, false); TOOL(itm_hatchet, -1, itm_hammer, -1, itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_pipe, 1, NULL); - RECIPE(itm_bayonet, CC_MISC, sk_gun, sk_null, 1, 500, true); + RECIPE(itm_bayonet, CC_MISC, Skill::skill("gun"), NULL, 1, 500, true); COMP(itm_carspike, 1, NULL); COMP(itm_string_36, 1, NULL); - RECIPE(itm_tripwire, CC_MISC, sk_traps, sk_null, 1, 500, false); + RECIPE(itm_tripwire, CC_MISC, Skill::skill("traps"), NULL, 1, 500, false); COMP(itm_string_36, 1, NULL); COMP(itm_superglue, 1, NULL); - RECIPE(itm_board_trap, CC_MISC, sk_traps, sk_null, 2, 2500, true); + RECIPE(itm_board_trap, CC_MISC, Skill::skill("traps"), NULL, 2, 2500, true); TOOL(itm_hatchet, -1, itm_hammer, -1, itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_2x4, 3, NULL); COMP(itm_nail, 20, NULL); - RECIPE(itm_beartrap, CC_MISC, sk_mechanics, sk_traps, 2, 3000, true); + RECIPE(itm_beartrap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"), 2, 3000, true); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_scrap, 3, NULL); COMP(itm_spring, 1, NULL); - RECIPE(itm_crossbow_trap, CC_MISC, sk_mechanics, sk_traps, 3, 4500, true); + RECIPE(itm_crossbow_trap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"), 3, 4500, true); COMP(itm_crossbow, 1, NULL); COMP(itm_bolt_steel, 1, itm_bolt_wood, 4, NULL); COMP(itm_string_6, 2, itm_string_36, 1, NULL); - RECIPE(itm_shotgun_trap, CC_MISC, sk_mechanics, sk_traps, 3, 5000, true); + RECIPE(itm_shotgun_trap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"), 3, 5000, true); COMP(itm_shotgun_sawn, 1, NULL); COMP(itm_shot_00, 2, NULL); COMP(itm_string_36, 1, itm_string_6, 2, NULL); - RECIPE(itm_blade_trap, CC_MISC, sk_mechanics, sk_traps, 4, 8000, true); + RECIPE(itm_blade_trap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"), 4, 8000, true); TOOL(itm_wrench, -1, itm_toolset, -1, NULL); COMP(itm_motor, 1, NULL); COMP(itm_machete, 1, NULL); COMP(itm_string_36, 1, NULL); -RECIPE(itm_boobytrap, CC_MISC, sk_mechanics, sk_traps,3,5000, false); +RECIPE(itm_boobytrap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"),3,5000, false); COMP(itm_grenade,1,NULL); COMP(itm_string_6,1,NULL); COMP(itm_can_food,1,NULL); - RECIPE(itm_landmine, CC_WEAPON, sk_traps, sk_mechanics, 5, 10000, false); + RECIPE(itm_landmine, CC_WEAPON, Skill::skill("traps"), Skill::skill("mechanics"), 5, 10000, false); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_superglue, 1, NULL); COMP(itm_can_food, 1, itm_steel_chunk, 1, itm_canister_empty, 1, itm_scrap, 4, NULL); @@ -989,27 +989,27 @@ RECIPE(itm_boobytrap, CC_MISC, sk_mechanics, sk_traps,3,5000, false); COMP(itm_shot_bird, 30, itm_shot_00, 15, itm_shot_slug, 12, itm_gasoline, 600, itm_grenade, 1, itm_gunpowder, 72, NULL); - RECIPE(itm_bandages, CC_MISC, sk_firstaid, sk_null, 1, 500, false); + RECIPE(itm_bandages, CC_MISC, Skill::skill("firstaid"), NULL, 1, 500, false); COMP(itm_rag, 3, NULL); COMP(itm_superglue, 1, itm_duct_tape, 5, NULL); COMP(itm_vodka, 1, itm_rum, 1, itm_whiskey, 1, itm_tequila, 1, NULL); - RECIPE(itm_silencer, CC_MISC, sk_mechanics, sk_null, 1, 650, false); + RECIPE(itm_silencer, CC_MISC, Skill::skill("mechanics"), NULL, 1, 650, false); TOOL(itm_hacksaw, -1, itm_toolset, -1, NULL); COMP(itm_muffler, 1, itm_rag, 4, NULL); COMP(itm_pipe, 1, NULL); - RECIPE(itm_pheromone, CC_MISC, sk_cooking, sk_null, 3, 1200, false); + RECIPE(itm_pheromone, CC_MISC, Skill::skill("cooking"), NULL, 3, 1200, false); TOOL(itm_hotplate, 18, itm_toolset, 9, itm_fire, -1, NULL); COMP(itm_meat_tainted, 1, NULL); COMP(itm_ammonia, 1, NULL); - RECIPE(itm_laser_pack, CC_MISC, sk_electronics, sk_null, 5, 10000, true); + RECIPE(itm_laser_pack, CC_MISC, Skill::skill("electronics"), NULL, 5, 10000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); COMP(itm_superglue, 1, NULL); COMP(itm_plut_cell, 1, NULL); - RECIPE(itm_bot_manhack, CC_MISC, sk_electronics, sk_computer, 6, 8000, true); + RECIPE(itm_bot_manhack, CC_MISC, Skill::skill("electronics"), Skill::skill("computer"), 6, 8000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 10, itm_toolset, 10, NULL); COMP(itm_carspike, 2, NULL); @@ -1019,7 +1019,7 @@ RECIPE(itm_boobytrap, CC_MISC, sk_mechanics, sk_traps,3,5000, false); // COMP(itm_battery, 400, itm_plut_cell, 1, NULL); // COMP(itm_scrap, 15, NULL); - RECIPE(itm_bot_turret, CC_MISC, sk_electronics, sk_computer, 7, 9000, true); + RECIPE(itm_bot_turret, CC_MISC, Skill::skill("electronics"), Skill::skill("computer"), 7, 9000, true); TOOL(itm_screwdriver, -1, itm_toolset, -1, NULL); TOOL(itm_soldering_iron, 14, itm_toolset, 14, NULL); COMP(itm_smg_9mm, 1, itm_uzi, 1, itm_tec9, 1, itm_calico, 1, itm_hk_mp5, 1, @@ -1124,17 +1124,17 @@ Press ? to describe object. Press to attempt to craft object."); if (current.size() > 0) { nc_color col = (available[line] ? c_white : c_dkgray); mvwprintz(w_data, 0, 30, col, "Primary skill: %s", - (current[line]->sk_primary == sk_null ? "N/A" : - skill_name(current[line]->sk_primary).c_str())); + (current[line]->sk_primary == NULL ? "N/A" : + current[line]->sk_primary->name().c_str())); mvwprintz(w_data, 1, 30, col, "Secondary skill: %s", - (current[line]->sk_secondary == sk_null ? "N/A" : - skill_name(current[line]->sk_secondary).c_str())); + (current[line]->sk_secondary == NULL ? "N/A" : + current[line]->sk_secondary->name().c_str())); mvwprintz(w_data, 2, 30, col, "Difficulty: %d", current[line]->difficulty); - if (current[line]->sk_primary == sk_null) + if (current[line]->sk_primary == NULL) mvwprintz(w_data, 3, 30, col, "Your skill level: N/A"); else mvwprintz(w_data, 3, 30, col, "Your skill level: %d", - u.sklevel[current[line]->sk_primary]); + u.skillLevel(current[line]->sk_primary).level()); if (current[line]->time >= 1000) mvwprintz(w_data, 4, 30, col, "Time to complete: %d minutes", int(current[line]->time / 1000)); @@ -1429,10 +1429,10 @@ void game::pick_recipes(std::vector ¤t, for (int i = 0; i < recipes.size(); i++) { // Check if the category matches the tab, and we have the requisite skills if (recipes[i]->category == tab && - (recipes[i]->sk_primary == sk_null || - u.sklevel[recipes[i]->sk_primary] >= recipes[i]->difficulty) && - (recipes[i]->sk_secondary == sk_null || - u.sklevel[recipes[i]->sk_secondary] > 0)) + (recipes[i]->sk_primary == NULL || + u.skillLevel(recipes[i]->sk_primary) >= recipes[i]->difficulty) && + (recipes[i]->sk_secondary == NULL || + u.skillLevel(recipes[i]->sk_secondary) > 0)) { if (recipes[i]->difficulty >= 0) current.push_back(recipes[i]); @@ -1493,11 +1493,11 @@ void game::complete_craft() recipe* making = recipes[u.activity.index]; // Which recipe is it? // # of dice is 75% primary skill, 25% secondary (unless secondary is null) - int skill_dice = u.sklevel[making->sk_primary] * 3; - if (making->sk_secondary == sk_null) - skill_dice += u.sklevel[making->sk_primary]; + int skill_dice = u.skillLevel(making->sk_primary).level() * 3; + if (making->sk_secondary == NULL) + skill_dice += u.skillLevel(making->sk_primary).level(); else - skill_dice += u.sklevel[making->sk_secondary]; + skill_dice += u.skillLevel(making->sk_secondary).level(); // Sides on dice is 16 plus your current intelligence int skill_sides = 16 + u.int_cur; @@ -1507,9 +1507,9 @@ void game::complete_craft() int skill_roll = dice(skill_dice, skill_sides); int diff_roll = dice(diff_dice, diff_sides); - if (making->sk_primary != sk_null) + if (making->sk_primary) u.practice(making->sk_primary, making->difficulty * 5 + 20); - if (making->sk_secondary != sk_null) + if (making->sk_secondary) u.practice(making->sk_secondary, 5); // Messed up badly; waste some components. @@ -1902,11 +1902,11 @@ void game::complete_disassemble() // adapting original crafting formula to check if disassembly was successful // # of dice is 75% primary skill, 25% secondary (unless secondary is null) - int skill_dice = 2 + u.sklevel[dis->sk_primary] * 3; - if (dis->sk_secondary == sk_null) - skill_dice += u.sklevel[dis->sk_primary]; + int skill_dice = 2 + u.skillLevel(dis->sk_primary).level() * 3; + if (dis->sk_secondary == NULL) + skill_dice += u.skillLevel(dis->sk_primary).level(); else - skill_dice += u.sklevel[dis->sk_secondary]; + skill_dice += u.skillLevel(dis->sk_secondary).level(); // Sides on dice is 16 plus your current intelligence int skill_sides = 16 + u.int_cur; @@ -1914,9 +1914,9 @@ void game::complete_disassemble() int diff_sides = 24; // 16 + 8 (default intelligence) // disassembly only nets a bit of practice - if (dis->sk_primary != sk_null) + if (dis->sk_primary) u.practice(dis->sk_primary, (dis->difficulty) * 2); - if (dis->sk_secondary != sk_null) + if (dis->sk_secondary) u.practice(dis->sk_secondary, 2); for (int j = 0; j < 5; j++) diff --git a/crafting.h b/crafting.h index 1bd54d1636179..8b96a9b9e52a7 100644 --- a/crafting.h +++ b/crafting.h @@ -31,23 +31,31 @@ struct component component(itype_id TYPE, int COUNT) : type (TYPE), count (COUNT) {} }; -struct recipe -{ - int id; - itype_id result; - craft_cat category; - skill sk_primary; - skill sk_secondary; - int difficulty; - int time; - bool reversible; // can the item be disassembled? - - std::vector tools[5]; - std::vector components[10]; - - recipe() { id = 0; result = itm_null; category = CC_NULL; sk_primary = sk_null; - sk_secondary = sk_null; difficulty = 0; time = 0; reversible = false; } - recipe(int pid, itype_id pres, craft_cat cat, skill p1, skill p2, int pdiff, +struct recipe { + int id; + itype_id result; + craft_cat category; + Skill *sk_primary; + Skill *sk_secondary; + int difficulty; + int time; + bool reversible; // can the item be disassembled? + + std::vector tools[5]; + std::vector components[10]; + + recipe() { + id = 0; + result = itm_null; + category = CC_NULL; + sk_primary = NULL; + sk_secondary = NULL; + difficulty = 0; + time = 0; + reversible = false; + } + +recipe(int pid, itype_id pres, craft_cat cat, Skill *p1, Skill *p2, int pdiff, int ptime, bool preversible) : id (pid), result (pres), category (cat), sk_primary (p1), sk_secondary (p2), difficulty (pdiff), time (ptime), reversible (preversible) {} diff --git a/data/raw/skills.json b/data/raw/skills.json new file mode 100644 index 0000000000000..05f25e3c42d8d --- /dev/null +++ b/data/raw/skills.json @@ -0,0 +1,142 @@ +[ + [ + "null", + "null", + "The skill of true Zen." + ], + [ + "dodge", + "dodge", + "Your skill at dodging, whether it be from an attack, a trap, or a natural\noccurrence. It is also used when attempting to fall gracefully, or in other\nacrobatic feats." + ], + [ + "melee", + "melee", + "Your skill at hand-to-hand combat, both with and without a weapon. At low\nlevels this merely increases your chance to hit, but at higher levels it also\nincreases the damage done significantly." + ], + [ + "unarmed", + "unarmed combat", + "Your skill at combat without a weapon. While at low levels, unarmed combat is\na good way to die quickly, those skilled in it can eventually use throws and\ncrushing blows to quickly dispatch enemies." + ], + [ + "bashing", + "bashing weapons", + "Your skill at combat with weapons that club or bash your enemies. This\nincludes everything from rocks to baseball bats, and even the butt of rifles.\nThis increases damage, and at higher levels will improve your chance to hit." + ], + [ + "cutting", + "cutting weapons", + "Your skill at combat with weapons that cut or slice your enemies. At first\nthis will simply slightly increase accuracy and damage; later on it will\nhelp you bypass armor and thick hides." + ], + [ + "stabbing", + "piercing weapons", + "Your skill at combat that involves piercing weapons. This includes spears,\nwhich only have a stabbing attack, and things like knives, which can cut or\npierce. This increases your accuracy and chance of a deadly critical." + ], + [ + "throw", + "throwing", + "Your skill at throwing items and getting them to go where you want. Increases\nboth accuracy and, at higher levels, range." + ], + [ + "gun", + "firearms", + "Your general skill at firearms. This increases your accuracy with any gun,\nbut not as much as the skill associated with the gun in question." + ], + [ + "pistol", + "handguns", + "Your skill with handguns. These have poor accuracy, but generally are fired\nand reloaded faster than other guns, and are good in close quarters." + ], + [ + "shotgun", + "shotguns", + "Your skill with shotguns. Shot is easy to hit with, and does massive damage,\nbut has short range. Shotguns may also be loaded with slugs, which go further\nand do as much damage, but are not very accurate." + ], + [ + "smg", + "submachine guns", + "Your skill with submachine guns and machine pistols. Halfway between a pistol\nand an assault rifle, these weapons fire and reload quickly, and may fire in\nbursts, but they are not very accurate." + ], + [ + "rifle", + "rifles", + "Your skill with rifles, both assault rifles and semi-auto hunting rifles.\nThese have terrific range and accuracy, but are very slow to fire and reload,\nand are not very good in close quarters." + ], + [ + "archery", + "archery", + "Your skill with all kinds of bows, from crossbows to handmade long bows.\nThese are quiet, but require some amount of strength to use, and are not\nterribly accurate. They can only be deadly in skilled hands." + ], + [ + "launcher", + "grenade launcher", + "Your skill with grenade launchers, whether standalone or as a rifle mod.\nThese launchers fire a variety of 40mm grenades with different uses,\nbut they and their rounds are hard to find." + ], + [ + "computer", + "computers", + "Your skill with computers, both in terms of legitimate use, and hacking. This\nwill help you use complex systems, and bypass their security." + ], + [ + "mechanics", + "mechanics", + "Your skill with repairs to mechanical systems, and the crafting of many items\nthat use complex parts, but are not electronics." + ], + [ + "electronics", + "electronics", + "Your skill with repairs to electrical systems, and the crafting of many items\nthat use electrical parts." + ], + [ + "cooking", + "cooking", + "Your skill in combining food ingredients to make other, tastier food items.\nThis may also be used in mixing chemicals and other more esoteric tasks." + ], + [ + "carpentry", + "construction", + "Your general knowledge in construction. This is used primarily when building\nterrain, via the * screen." + ], + [ + "survival", + "survival", + "Your skill in wilderness survival. This helps you butcher meat from a corpse\nand craft various basic survival items. High levels may allow you to remove\npoison from tainted meat. Also used for skinning corpses to acquire pelts." + ], + [ + "traps", + "traps", + "Your skill at setting and disarming traps safely and effectively. Note that\nthis does not help you detect traps, or avoid their effects if you activate\nthem." + ], + [ + "tailor", + "tailoring", + "Your skill at repairing clothing, and at higher levels, creating clothing\nfrom basic materials. Generally a sewing kit is needed. Also applies to\nother methods of clothing repair and textile crafting." + ], + [ + "firstaid", + "first aid", + "Your skill at emergency medical treatment, such as that from first aid kits\nand bandages. High levels of this skill may help heal more HP. Some drugs\nmay be more effective as well." + ], + [ + "speech", + "speech", + "Your skill at talking to people, convincing them of things, lying, and many\nothers. Works best in conjunction with a high intelligence." + ], + [ + "barter", + "barter", + "Your skill at getting a good deal when trading with others. Very high levels\nmight even see you getting freebies." + ], + [ + "swimming", + "swimming", + "Your skill at swimming. This affects speed, your ability to swim while\nwearing clothes or carrying weights, and in-water combat." + ], + [ + "driving", + "driving", + "Your skill at driving. This affects how well you can control a vehicle,\nas well as the penalty of shooting while driving." + ] +] diff --git a/defense.cpp b/defense.cpp index 189ad6bc24533..b579ea721152d 100644 --- a/defense.cpp +++ b/defense.cpp @@ -1184,11 +1184,12 @@ void draw_caravan_items(WINDOW *w, game *g, std::vector *items, wrefresh(w); } -int caravan_price(player &u, int price) -{ - if (u.sklevel[sk_barter] > 10) +int caravan_price(player &u, int price) { + Skill *barterSkill = Skill::skill("barter"); + + if (u.skillLevel(barterSkill) > 10) return int( double(price) * .5); - return int( double(price) * (1.0 - double(u.sklevel[sk_barter]) * .05)); + return int( double(price) * (1.0 - double(u.skillLevel(barterSkill).level()) * .05)); } void defense_game::spawn_wave(game *g) diff --git a/game.cpp b/game.cpp index bac4ab68a1524..aee74e00a3368 100644 --- a/game.cpp +++ b/game.cpp @@ -692,53 +692,38 @@ bool game::do_turn() refresh(); } - update_skills(); + rustCheck(); if (turn % 10 == 0) u.update_morale(); return false; } -void game::update_skills() -{ -// SKILL TURNS/-- -// 1 4096 -// 2 2048 -// 3 1024 -// 4 512 -// 5 256 -// 6 128 -// 7+ 64 - for (int i = 0; i < num_skill_types; i++) { - int tmp = u.sklevel[i] > 7 ? 7 : u.sklevel[i]; +void game::rustCheck() { + if (OPTIONS[OPT_SKILL_RUST] == 2) + return; - if (OPTIONS[OPT_SKILL_RUST] == 0 || OPTIONS[OPT_SKILL_RUST] == 1) - { - if (u.sklevel[i] > 0 && turn % (8192 / int(pow(2, double(tmp - 1)))) == 0 && - (( u.has_trait(PF_FORGETFUL) && one_in(3)) || - (!u.has_trait(PF_FORGETFUL) && one_in(4)) )) { + for (EACH_SKILL) { + uint32_t skillLevel = u.skillLevel(*aSkill).level(); + uint32_t forgetCap = skillLevel > 7 ? 7 : skillLevel; - if (u.has_bionic(bio_memory) && u.power_level > 0) { + if (skillLevel > 0 && turn % (8192 / int(pow(2, double(forgetCap - 1))))) { + if (rng(1,12) % (u.has_trait(PF_FORGETFUL) ? 3 : 4)) { + if (u.has_bionic(bio_memory) && u.power_level > 0) { if (one_in(5)) - u.power_level--; - } - else - u.skexercise[i]--; + u.power_level--; + } else { + if (OPTIONS[OPT_SKILL_RUST] == 0 || u.skillLevel(*aSkill).exercise() > 0) { + uint32_t newLevel; + u.skillLevel(*aSkill).rust(newLevel); + + if (newLevel < skillLevel) { + add_msg("Your skill in %s has reduced to %d!", (*aSkill)->name().c_str(), newLevel); + } + } } - if (OPTIONS[OPT_SKILL_RUST] == 1 && u.skexercise[i] < 0) - u.skexercise[i] = 0; - } - if (u.skexercise[i] < -100) { - u.sklevel[i]--; - add_msg("Your skill in %s has reduced to %d!", - skill_name(skill(i)).c_str(), u.sklevel[i]); - u.skexercise[i] = 0; - } else if (u.skexercise[i] >= 100) { - u.sklevel[i]++; - add_msg("Your skill in %s has increased to %d!", - skill_name(skill(i)).c_str() ,u.sklevel[i]); - u.skexercise[i] = 0; + } + } } - } } void game::process_events() @@ -808,19 +793,20 @@ void game::process_activity() u.add_morale(MORALE_BOOK, reading->fun * 5, reading->fun * 15, reading); } - if (u.sklevel[reading->type] < reading->level) { - add_msg("You learn a little about %s!", skill_name(reading->type).c_str()); + if (u.skillLevel(reading->type) < reading->level) { + add_msg("You learn a little about %s!", reading->type->name().c_str()); int min_ex = reading->time / 10 + u.int_cur / 4, - max_ex = reading->time / 5 + u.int_cur / 2 - u.sklevel[reading->type]; + max_ex = reading->time / 5 + u.int_cur / 2 - u.skillLevel(reading->type).level(); if (min_ex < 1) min_ex = 1; if (max_ex < 2) max_ex = 2; if (max_ex > 10) max_ex = 10; - u.skexercise[reading->type] += rng(min_ex, max_ex); - if (u.sklevel[reading->type] + - (u.skexercise[reading->type] >= 100 ? 1 : 0) >= reading->level) + + u.skillLevel(reading->type).readBook(min_ex, max_ex, reading->level); + + if (u.skillLevel(reading->type) == reading->level) add_msg("You can no longer learn from this %s.", reading->name.c_str()); } break; @@ -2119,8 +2105,8 @@ z.size(), events.size()); break; case 11: - for (int i = 0; i < num_skill_types; i++) - u.sklevel[i] += 3; + for (EACH_SKILL) + u.skillLevel(*aSkill).level(u.skillLevel(*aSkill).level() + 3); break; case 12: @@ -2152,12 +2138,8 @@ z.size(), events.size()); int(p->personality.bravery) << " Collector: " << int(p->personality.collector) << " Altruism: " << int(p->personality.altruism) << std::endl; - for (int i = 0; i < num_skill_types; i++) { - data << skill_name( skill(i) ) << ": " << p->sklevel[i]; - if (i % 2 == 1) - data << std::endl; - else - data << "\t"; + for (EACH_SKILL) { + data << (*aSkill)->name() << ": " << p->skillLevel(*aSkill) << std::endl; } full_screen_popup(data.str().c_str()); @@ -4074,8 +4056,8 @@ void game::smash() add_msg(extra.c_str()); sound(u.posx, u.posy, 18, bashsound); u.moves -= 80; - if (u.sklevel[sk_melee] == 0) - u.practice(sk_melee, rng(0, 1) * rng(0, 1)); + if (u.skillLevel(Skill::skill("melee")) == 0) + u.practice(Skill::skill("melee"), rng(0, 1) * rng(0, 1)); if (u.weapon.made_of(GLASS) && rng(0, u.weapon.volume() + 3) < u.weapon.volume()) { add_msg("Your %s shatters!", u.weapon.tname(this).c_str()); @@ -4383,9 +4365,11 @@ void game::examine() u.power_level > 0 && query_yn("Use fingerhack on the reader?")); if (using_electrohack || using_fingerhack) { + Skill *computerSkill = Skill::skill("computer"); + u.moves -= 500; - u.practice(sk_computer, 20); - int success = rng(u.sklevel[sk_computer]/4 - 2, u.sklevel[sk_computer] * 2); + u.practice(computerSkill, 20); + int success = rng(u.skillLevel(computerSkill).level() / 4 - 2, u.skillLevel(computerSkill).level() * 2); success += rng(-3, 3); if (using_fingerhack) success++; @@ -5828,7 +5812,7 @@ void game::plthrow() u.i_rem(ch); u.moves -= 125; - u.practice(sk_throw, 10); + u.practice(Skill::skill("throw"), 10); throw_item(u, x, y, thrown, trajectory); } @@ -5945,18 +5929,20 @@ void game::plfire(bool burst) burst = true; // Train up our skill + Skill *gunSkill = Skill::skill("gun"); + it_gun* firing = dynamic_cast(u.weapon.type); int num_shots = 1; if (burst) num_shots = u.weapon.burst_size(); if (num_shots > u.weapon.num_charges()) num_shots = u.weapon.num_charges(); - if (u.sklevel[firing->skill_used] == 0 || + if (u.skillLevel(firing->skill_used) == 0 || (firing->ammo != AT_BB && firing->ammo != AT_NAIL)) u.practice(firing->skill_used, 4 + (num_shots / 2)); - if (u.sklevel[sk_gun] == 0 || + if (u.skillLevel(gunSkill) == 0 || (firing->ammo != AT_BB && firing->ammo != AT_NAIL)) - u.practice(sk_gun, 5); + u.practice(gunSkill, 5); fire(u, x, y, trajectory, burst); } @@ -6009,6 +5995,10 @@ void game::complete_butcher(int index) int factor = u.butcher_factor(); int pieces, pelts; double skill_shift = 0.; + + Skill *survivalSkill = Skill::skill("survival"); + uint32_t sSkillLevel = u.skillLevel(survivalSkill).level(); + switch (corpse->size) { case MS_TINY: pieces = 1; pelts = 1; break; case MS_SMALL: pieces = 2; pelts = 3; break; @@ -6016,10 +6006,10 @@ void game::complete_butcher(int index) case MS_LARGE: pieces = 8; pelts = 10; break; case MS_HUGE: pieces = 16; pelts = 18; break; } - if (u.sklevel[sk_survival] < 3) - skill_shift -= rng(0, 8 - u.sklevel[sk_survival]); + if (sSkillLevel < 3) + skill_shift -= rng(0, 8 - sSkillLevel); else - skill_shift += rng(0, u.sklevel[sk_survival]); + skill_shift += rng(0, sSkillLevel); if (u.dex_cur < 8) skill_shift -= rng(0, 8 - u.dex_cur) / 4; else @@ -6032,7 +6022,7 @@ void game::complete_butcher(int index) int practice = 4 + pieces; if (practice > 20) practice = 20; - u.practice(sk_survival, practice); + u.practice(survivalSkill, practice); pieces += int(skill_shift); if (skill_shift < 5) // Lose some pelts @@ -6365,8 +6355,9 @@ void game::chat() u.moves -= 100; } -void game::pldrive(int x, int y) -{ +void game::pldrive(int x, int y) { + Skill *drivingSkill = Skill::skill("driving"); + if (run_mode == 2) { // Monsters around and we don't wanna run add_msg("Monster spotted--run mode is on! " "(Press '!' to turn it off or ' to ignore monster.)"); @@ -6394,7 +6385,7 @@ void game::pldrive(int x, int y) } veh->turn (15 * x); if (veh->skidding && veh->valid_wheel_config()) { - if (rng (0, 40) < u.dex_cur + u.sklevel[sk_driving] * 2) { + if (rng (0, 40) < u.dex_cur + u.skillLevel(drivingSkill).level() * 2) { add_msg ("You regain control of the %s.", veh->name.c_str()); veh->skidding = false; veh->move.init (veh->turn_dir); @@ -6403,7 +6394,7 @@ void game::pldrive(int x, int y) u.moves = 0; if (x != 0 && veh->velocity != 0 && one_in(4)) - u.practice(sk_driving, 1); + u.practice(drivingSkill, 1); } void game::plmove(int x, int y) @@ -6548,10 +6539,12 @@ void game::plmove(int x, int y) // Adjust recoil down if (u.recoil > 0) { - if (int(u.str_cur / 2) + u.sklevel[sk_gun] >= u.recoil) + Skill *gunSkill = Skill::skill("gun"); + + if (int(u.str_cur / 2) + u.skillLevel(gunSkill).level() >= u.recoil) u.recoil = 0; else { - u.recoil -= int(u.str_cur / 2) + u.sklevel[sk_gun]; + u.recoil -= int(u.str_cur / 2) + u.skillLevel(gunSkill).level(); u.recoil = int(u.recoil / 2); } } @@ -6731,7 +6724,7 @@ void game::plswim(int x, int y) u.rem_disease(DI_ONFIRE); } int movecost = u.swim_speed(); - u.practice(sk_swimming, 1); + u.practice(Skill::skill("swimming"), 1); if (movecost >= 500) { if (!u.underwater) { add_msg("You sink%s!", (movecost >= 400 ? " like a rock" : "")); diff --git a/game.h b/game.h index 6e66247e752b6..d20e1b87339c3 100644 --- a/game.h +++ b/game.h @@ -341,7 +341,7 @@ class game // Routine loop functions, approximately in order of execution void cleanup_dead(); // Delete any dead NPCs/monsters void monmove(); // Monster movement - void update_skills(); // Degrades practice levels, checks & upgrades skills + void rustCheck(); // Degrades practice levels void process_events(); // Processes and enacts long-term events void process_activity(); // Processes and enacts the player's activity void update_weather(); // Updates the temperature and weather patten diff --git a/item.cpp b/item.cpp index 4cd26e83ef2eb..e1fcb4cad6177 100644 --- a/item.cpp +++ b/item.cpp @@ -354,7 +354,6 @@ std::string item::info(bool showtext) "\n Range: " << int(ammo->range) << "\n Accuracy: " << int(100 - ammo->accuracy) << "\n Recoil: " << int(ammo->recoil) << "\n Count: " << int(contents[0].charges); - } else if (is_gun()) { it_gun* gun = dynamic_cast(type); @@ -364,8 +363,8 @@ std::string item::info(bool showtext) ammo_dam = curammo->damage; ammo_recoil = curammo->recoil; } - - dump << " Skill used: " << skill_name(gun->skill_used) << "\n Ammunition: " << + + dump << " Skill used: " << gun->skill_used->name() << "\n Ammunition: " << clip_size() << " rounds of " << ammo_name(ammo_type()); dump << "\n Damage: "; @@ -389,7 +388,7 @@ std::string item::info(bool showtext) dump << " per round"; if (burst_size() == 0) { - if (gun->skill_used == sk_pistol && has_flag(IF_RELOAD_ONE)) + if (gun->skill_used == Skill::skill("pistol") && has_flag(IF_RELOAD_ONE)) dump << "\n Revolver."; else dump << "\n Semi-automatic."; @@ -456,15 +455,15 @@ std::string item::info(bool showtext) } else if (is_book()) { it_book* book = dynamic_cast(type); - if (book->type == sk_null) + if (!book->type) dump << " Just for fun.\n"; else { - dump << " Can bring your " << skill_name(book->type) << " skill to " << + dump << " Can bring your " << book->type->name() << " skill to " << int(book->level) << std::endl; if (book->req == 0) dump << " It can be understood by beginners.\n"; else - dump << " Requires " << skill_name(book->type) << " level " << + dump << " Requires " << book->type->name() << " level " << int(book->req) << " to understand.\n"; } dump << " Requires intelligence of " << int(book->intel) << " to easily read." << std::endl; @@ -546,9 +545,10 @@ nc_color item::color(player *u) } } else if (is_book()) { it_book* tmp = dynamic_cast(type); - if (tmp->type !=sk_null && tmp->intel <= u->int_cur + u->sklevel[tmp->type] && + if (tmp->type && tmp->intel <= u->int_cur + u->skillLevel(tmp->type).level() && (tmp->intel == 0 || !u->has_trait(PF_ILLITERATE)) && - tmp->req <= u->sklevel[tmp->type] && tmp->level > u->sklevel[tmp->type]) + (u->skillLevel(tmp->type) >= tmp->req) && + (u->skillLevel(tmp->type) < tmp->level)) ret = c_ltblue; } return ret; @@ -831,7 +831,7 @@ bool item::has_technique(technique_id tech, player *p) it_style *style = dynamic_cast(type); for (int i = 0; i < style->moves.size(); i++) { if (style->moves[i].tech == tech && - (p == NULL || p->sklevel[sk_unarmed] >= style->moves[i].level)) + (!p || p->skillLevel(Skill::skill("unarmed")) >= style->moves[i].level)) return true; } } @@ -927,7 +927,7 @@ int item::weapon_value(int skills[num_skill_types]) gun_value += int(gun->clip / 3); gun_value -= int(gun->accuracy / 5); gun_value *= (.5 + (.3 * skills[sk_gun])); - gun_value *= (.3 + (.7 * skills[gun->skill_used])); + gun_value *= (.3 + (.7 * skills[gun->skill_used->id()])); /// TODO: FIXME my_value += gun_value; } @@ -987,9 +987,9 @@ style_move item::style_data(technique_id tech) bool item::is_two_handed(player *u) { - if (is_gun() && (dynamic_cast(type))->skill_used != sk_pistol) - return true; - return (weight() > u->str_cur * 4); + if (is_gun() && (dynamic_cast(type))->skill_used != Skill::skill("pistol")) + return true; + return (weight() > u->str_cur * 4); } bool item::made_of(material mat) @@ -1057,7 +1057,7 @@ bool item::is_ammo() bool item::is_food(player *u) { - if (u == NULL) + if (!u) return is_food(); if( is_null() ) @@ -1227,7 +1227,7 @@ int item::reload_time(player &u) if (spare_mag != -1 && contents[spare_mag].charges > 0) ret -= double(ret) * 0.9; } - double skill_bonus = double(u.sklevel[reloading->skill_used]) * .075; + double skill_bonus = double(u.skillLevel(reloading->skill_used).level()) * .075; if (skill_bonus > .75) skill_bonus = .75; ret -= double(ret) * skill_bonus; @@ -1363,9 +1363,9 @@ int item::noise() int ret = 0; if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); - if (gunmod != NULL && gunmod->curammo != NULL) + if (gunmod && gunmod->curammo) ret = gunmod->curammo->damage; - } else if (curammo != NULL) + } else if (curammo) ret = curammo->damage; ret *= .8; if (ret >= 5) @@ -1404,14 +1404,14 @@ int item::recoil(bool with_ammo) // Just use the raw ammo recoil for now. if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); - if (gunmod != NULL && gunmod->curammo != NULL) + if (gunmod && gunmod->curammo) return gunmod->curammo->recoil; else return 0; } it_gun* gun = dynamic_cast(type); int ret = gun->recoil; - if (with_ammo && curammo != NULL) + if (with_ammo && curammo) ret += curammo->recoil; for (int i = 0; i < contents.size(); i++) { if (contents[i].is_gunmod()) @@ -1427,7 +1427,7 @@ int item::range(player *p) // Just use the raw ammo range for now. if(mode == IF_MODE_AUX) { item* gunmod = active_gunmod(); - if(gunmod != NULL && gunmod->curammo != NULL) + if(gunmod && gunmod->curammo) return gunmod->curammo->range; else return 0; @@ -1435,12 +1435,12 @@ int item::range(player *p) int ret = (curammo?curammo->range:0); - if (has_flag(IF_STR8_DRAW) && p != NULL) { + if (has_flag(IF_STR8_DRAW) && p) { if (p->str_cur < 4) return 0; else if (p->str_cur < 8) ret -= 2 * (8 - p->str_cur); - } else if (has_flag(IF_STR10_DRAW) && p != NULL) { + } else if (has_flag(IF_STR10_DRAW) && p) { if (p->str_cur < 5) return 0; else if (p->str_cur < 10) @@ -1589,7 +1589,7 @@ bool item::reload(player &u, int index) // Determine what we're reloading, the gun, a spare magazine, or another gunmod. // Prefer the active gunmod if there is one item* gunmod = active_gunmod(); - if (gunmod != NULL && gunmod->ammo_type() == ammo_to_use->ammo_type() && + if (gunmod && gunmod->ammo_type() == ammo_to_use->ammo_type() && (gunmod->charges <= 0 || gunmod->curammo->id == ammo_to_use->typeId())) { reload_target = gunmod; // Then prefer the gun itself @@ -1737,7 +1737,7 @@ std::ostream & operator<<(std::ostream & out, const item & it) int item::typeId() { - if ( type == NULL ) + if (!type) return itm_null; return type->id; } diff --git a/itype.h b/itype.h index 84c444b58ff42..5e2317b0546f7 100644 --- a/itype.h +++ b/itype.h @@ -542,7 +542,7 @@ struct it_ammo : public itype struct it_gun : public itype { ammotype ammo; - skill skill_used; + Skill *skill_used; signed char dmg_bonus; signed char accuracy; signed char recoil; @@ -560,7 +560,7 @@ struct it_gun : public itype signed char pmelee_dam, signed char pmelee_cut, signed char pm_to_hit, unsigned pitem_flags, - skill pskill_used, ammotype pammo, signed char pdmg_bonus, + Skill *pskill_used, ammotype pammo, signed char pdmg_bonus, signed char paccuracy, signed char precoil, unsigned char pdurability, unsigned char pburst, int pclip, int preload_time) :itype(pid, prarity, pprice, pname, pdes, psym, pcolor, pm1, pm2, @@ -669,7 +669,7 @@ struct it_armor : public itype struct it_book : public itype { - skill type; // Which skill it upgrades + Skill *type; // Which skill it upgrades unsigned char level; // The value it takes the skill to unsigned char req; // The skill level required to understand it signed char fun; // How fun reading this is @@ -684,7 +684,7 @@ struct it_book : public itype signed char pmelee_dam, signed char pmelee_cut, signed char pm_to_hit, unsigned pitem_flags, - skill ptype, unsigned char plevel, unsigned char preq, + Skill *ptype, unsigned char plevel, unsigned char preq, signed char pfun, unsigned char pintel, unsigned char ptime) :itype(pid, prarity, pprice, pname, pdes, psym, pcolor, pm1, pm2, pvolume, pweight, pmelee_dam, pmelee_cut, pm_to_hit, pitem_flags) { diff --git a/itypedef.cpp b/itypedef.cpp index e404f260f71c8..b931cc5b77f30 100644 --- a/itypedef.cpp +++ b/itypedef.cpp @@ -2344,19 +2344,19 @@ recoil,durability,burst,clip,reload_time)) // NAME RAR PRC COLOR MAT1 MAT2 GUN("nail gun", 12, 100,c_ltblue, IRON, MNULL, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_pistol, AT_NAIL, 4, 22, 12, 1, 0, 20, 0, 8, 5, 100, 450, "\ + Skill::skill("pistol"), AT_NAIL, 4, 22, 12, 1, 0, 20, 0, 8, 5, 100, 450, "\ A tool used to drive nails into wood or other material. It could also be\n\ used as a ad-hoc weapon, or to practice your handgun skill up to level 1.", mfb(IF_MODE_BURST)); GUN("BB gun", 10, 100,c_ltblue, IRON, WOOD, - sk_rifle, AT_BB, 8, 16, 9, 2, 0, 6, -5, 7, 0, 20, 500, "\ + Skill::skill("rifle"), AT_BB, 8, 16, 9, 2, 0, 6, -5, 7, 0, 20, 500, "\ Popular among children. It's fairly accurate, but BBs deal nearly no damage.\n\ It could be used to practice your rifle skill up to level 1.", 0); GUN("crossbow", 2,1000,c_green, IRON, WOOD, - sk_archery, AT_BOLT, 6, 9, 11, 1, 0, 18, 0, 6, 0, 1, 800, "\ + Skill::skill("archery"), AT_BOLT, 6, 9, 11, 1, 0, 18, 0, 6, 0, 1, 800, "\ A slow-loading hand weapon that launches bolts. Stronger people can reload\n\ it much faster. Bolts fired from this weapon have a good chance of remaining\n\ intact for re-use.", @@ -2365,21 +2365,21 @@ mfb(IF_STR_RELOAD)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("compound bow", 2,1400,c_yellow, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_archery, AT_ARROW,12, 8, 8, 1, 0, 20, 0, 6, 0, 1, 100, "\ + Skill::skill("archery"), AT_ARROW,12, 8, 8, 1, 0, 20, 0, 6, 0, 1, 100, "\ A bow with wheels that fires high velocity arrows. Weaker people can use\n\ compound bows more easily. Arrows fired from this weapon have a good chance\n\ of remaining intact for re-use.", mfb(IF_STR8_DRAW)|mfb(IF_RELOAD_AND_SHOOT)); GUN("longbow", 5, 800,c_yellow, WOOD, MNULL, - sk_archery, AT_ARROW,8, 4, 10, 0, 0, 12, 0, 6, 0, 1, 80, "\ + Skill::skill("archery"), AT_ARROW,8, 4, 10, 0, 0, 12, 0, 6, 0, 1, 80, "\ A six-foot wooden bow that fires feathered arrows. This takes a fair amount\n\ of strength to draw. Arrows fired from this weapon have a good chance of\n\ remaining intact for re-use.", mfb(IF_STR10_DRAW)|mfb(IF_RELOAD_AND_SHOOT)); GUN("pipe rifle: .22", 0, 800,c_ltblue, IRON, WOOD, -sk_rifle, AT_22, 9, 13, 10, 2, -2, 15, 2, 6, 0, 1, 250, "\ +Skill::skill("rifle"), AT_22, 9, 13, 10, 2, -2, 15, 2, 6, 0, 1, 250, "\ A home-made rifle. It is simply a pipe attached to a stock, with a hammer to\n\ strike the single round it holds.", 0); @@ -2387,25 +2387,25 @@ strike the single round it holds.", // NAME RAR PRC COLOR MAT1 MAT2 GUN("pipe rifle: 9mm", 0, 900,c_ltblue, IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_rifle, AT_9MM, 10, 16, 10, 2, -2, 15, 2, 6, 0, 1, 250, "\ + Skill::skill("rifle"), AT_9MM, 10, 16, 10, 2, -2, 15, 2, 6, 0, 1, 250, "\ A home-made rifle. It is simply a pipe attached to a stock, with a hammer to\n\ strike the single round it holds.", 0); GUN("pipe SMG: 9mm", 0, 1050,c_ltblue, IRON, WOOD, - sk_smg, AT_9MM, 5, 8, 6, -1, 0, 30, 6, 5, 4, 10, 400, "\ + Skill::skill("smg"), AT_9MM, 5, 8, 6, -1, 0, 30, 6, 5, 4, 10, 400, "\ A home-made machine pistol. It features a rudimentary blowback system, which\n\ allows for small bursts.", mfb(IF_MODE_BURST)); GUN("pipe SMG: .45", 0, 1150,c_ltblue, IRON, WOOD, - sk_smg, AT_45, 6, 9, 7, -1, 0, 30, 6, 5, 3, 8, 400, "\ + Skill::skill("smg"), AT_45, 6, 9, 7, -1, 0, 30, 6, 5, 3, 8, 400, "\ A home-made machine pistol. It features a rudimentary blowback system, which\n\ allows for small bursts.", mfb(IF_MODE_BURST)); GUN("SIG Mosquito", 5,1200,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_22, 1, 6, 9, 1, 1, 28, 4, 8, 0, 10, 350, "\ + Skill::skill("pistol"), AT_22, 1, 6, 9, 1, 1, 28, 4, 8, 0, 10, 350, "\ A popular, very small .22 pistol. \"Ergonomically designed to give the best\n\ shooting experience.\" --SIG Sauer official website", 0); @@ -2413,19 +2413,19 @@ shooting experience.\" --SIG Sauer official website", // NAME RAR PRC COLOR MAT1 MAT2 GUN("S&W 22A", 5,1250,c_dkgray, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_pistol, AT_22, 1, 10, 9, 1, 1, 25, 5, 7, 0, 10, 300, "\ + Skill::skill("pistol"), AT_22, 1, 10, 9, 1, 1, 25, 5, 7, 0, 10, 300, "\ A popular .22 pistol. \"Ideal for competitive target shooting or recreational\n\ shooting.\" --Smith & Wesson official website", 0); GUN("Glock 19", 7,1400,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_9MM, 2, 5, 8, 1, 0, 24, 6, 6, 0, 15, 300, "\ + Skill::skill("pistol"), AT_9MM, 2, 5, 8, 1, 0, 24, 6, 6, 0, 15, 300, "\ Possibly the most popular pistol in existance. The Glock 19 is often derided\n\ for its plastic contruction, but it is easy to shoot.", 0); GUN("USP 9mm", 6,1450,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_9MM, 2, 6, 8, 1, -1, 25, 5, 9, 0, 15, 350, "\ + Skill::skill("pistol"), AT_9MM, 2, 6, 8, 1, -1, 25, 5, 9, 0, 15, 350, "\ A popular 9mm pistol, widely used among law enforcement. Extensively tested\n\ for durability, it has been found to stay accurate even after subjected to\n\ extreme abuse.", @@ -2434,25 +2434,25 @@ extreme abuse.", // NAME RAR PRC COLOR MAT1 MAT2 GUN("S&W 619", 4,1450,c_dkgray, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_pistol, AT_38, 2, 9, 9, 1, 2, 23, 4, 8, 0, 7, 75, "\ + Skill::skill("pistol"), AT_38, 2, 9, 9, 1, 2, 23, 4, 8, 0, 7, 75, "\ A seven-round .38 revolver sold by Smith & Wesson. It features a fixed rear\n\ sight and a reinforced frame.", mfb(IF_RELOAD_ONE)); GUN("Taurus Pro .38", 4,1500,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_38, 2, 6, 8, 1, 1, 22, 6, 7, 0, 10, 350, "\ + Skill::skill("pistol"), AT_38, 2, 6, 8, 1, 1, 22, 6, 7, 0, 10, 350, "\ A popular .38 pistol. Designed with numerous safety features and built from\n\ high-quality, durable materials.", 0); GUN("SIG Pro .40", 4,1500,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_40, 2, 6, 8, 1, 1, 22, 8, 7, 0, 12, 350, "\ + Skill::skill("pistol"), AT_40, 2, 6, 8, 1, 1, 22, 8, 7, 0, 12, 350, "\ Originally marketed as a lightweight and compact alternative to older SIG\n\ handguns, the Pro .40 is popular among European police forces.", 0); GUN("S&W 610", 2,1460,c_dkgray, STEEL, WOOD, - sk_pistol, AT_40, 2, 10, 10, 1, 2, 23, 6, 8, 0, 6, 60, "\ + Skill::skill("pistol"), AT_40, 2, 10, 10, 1, 2, 23, 6, 8, 0, 6, 60, "\ The Smith and Wesson 610 is a classic six-shooter revolver chambered for 10mm\n\ rounds, or for S&W's own .40 round.", mfb(IF_RELOAD_ONE)); @@ -2460,28 +2460,28 @@ mfb(IF_RELOAD_ONE)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("Ruger Redhawk", 3,1560,c_dkgray, STEEL, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_pistol, AT_44, 2, 12, 10, 1, 2, 21, 6, 8, 0, 6, 80, "\ + Skill::skill("pistol"), AT_44, 2, 12, 10, 1, 2, 21, 6, 8, 0, 6, 80, "\ One of the most powerful handguns in the world when it was released in 1979,\n\ the Redhawk offers very sturdy contruction, with an appearance that is\n\ reminiscent of \"Wild West\" revolvers.", mfb(IF_RELOAD_ONE)); GUN("Desert Eagle .44", 2,1750,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_44, 4, 17, 14, 1, 4, 35, 3, 7, 0, 10, 400, "\ + Skill::skill("pistol"), AT_44, 4, 17, 14, 1, 4, 35, 3, 7, 0, 10, 400, "\ One of the most recognizable handguns due to its popularity in movies, the\n\ \"Deagle\" is better known for its menacing appearance than its performace.\n\ It's highly innaccurate, but its heavy weight reduces recoil.", 0); GUN("USP .45", 6,1600,c_dkgray, STEEL, PLASTIC, - sk_pistol, AT_45, 2, 7, 9, 1, 1, 25, 8, 9, 0, 12, 350, "\ + Skill::skill("pistol"), AT_45, 2, 7, 9, 1, 1, 25, 8, 9, 0, 12, 350, "\ A popular .45 pistol, widely used among law enforcement. Extensively tested\n\ for durability, it has been found to stay accurate even after subjected to\n\ extreme abuse.", 0); GUN("M1911", 5,1680,c_ltgray, STEEL, PLASTIC, - sk_pistol, AT_45, 3, 10, 12, 1, 6, 25, 9, 7, 0, 7, 300, "\ + Skill::skill("pistol"), AT_45, 3, 10, 12, 1, 6, 25, 9, 7, 0, 7, 300, "\ The M1911 was the standard-issue sidearm from the US Military for most of the\n\ 20th Century. It remains one of the most popular .45 pistols today.", 0); @@ -2489,26 +2489,26 @@ The M1911 was the standard-issue sidearm from the US Military for most of the\n\ // NAME RAR PRC COLOR MAT1 MAT2 GUN("FN Five-Seven", 2,1550,c_ltgray, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_pistol, AT_57, 2, 5, 6, 0, 2, 13, 6, 8, 0, 20, 300, "\ + Skill::skill("pistol"), AT_57, 2, 5, 6, 0, 2, 13, 6, 8, 0, 20, 300, "\ Designed to work with FN's proprietary 5.7x28mm round, the Five-Seven is a\n\ lightweight pistol with a very high capacity, best used against armored\n\ opponents.", 0); GUN("H&K UCP", 2,1500,c_ltgray, STEEL, PLASTIC, - sk_pistol, AT_46, 2, 5, 6, 0, 2, 12, 6, 8, 0, 20, 300, "\ + Skill::skill("pistol"), AT_46, 2, 5, 6, 0, 2, 12, 6, 8, 0, 20, 300, "\ Designed to work with H&K's proprietary 4.6x30mm round, the UCP is a small\n\ pistol with a very high capacity, best used against armored opponents.", 0); GUN("sawn-off shotgun", 1, 700,c_red, IRON, WOOD, - sk_shotgun, AT_SHOT, 6, 10, 14, 2, 4, 40, 15, 4, 0, 2, 100, "\ + Skill::skill("shotgun"), AT_SHOT, 6, 10, 14, 2, 4, 40, 15, 4, 0, 2, 100, "\ The barrels of shotguns are often sawed in half to make it more maneuverable\n\ and concealable. This has the added effect of reducing accuracy greatly.", mfb(IF_RELOAD_ONE)); GUN("sawn-off Saiga 12", 1, 700,c_red, IRON, WOOD, - sk_shotgun, AT_SHOT, 6, 10, 14, 2, 4, 40, 15, 4, 0, 10, 100, "\ + Skill::skill("shotgun"), AT_SHOT, 6, 10, 14, 2, 4, 40, 15, 4, 0, 10, 100, "\ The Saiga-12 shotgun is designed on the same Kalishnikov pattern as the AK47\n\ rifle. It reloads with a magazine, rather than one shell at a time like most\n\ shotguns. This one has had the barrel cut short, vastly reducing accuracy\n\ @@ -2518,27 +2518,27 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("single barrel shotgun",1,600,c_red,IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_shotgun, AT_SHOT,12, 20, 14, 3, 0, 6, 5, 6, 0, 1, 100, "\ + Skill::skill("shotgun"), AT_SHOT,12, 20, 14, 3, 0, 6, 5, 6, 0, 1, 100, "\ An old shotgun, possibly antique. It is little more than a barrel, a wood\n\ stock, and a hammer to strike the cartridge. Its simple design keeps it both\n\ light and accurate.", 0); GUN("double barrel shotgun",2,1050,c_red,IRON, WOOD, - sk_shotgun, AT_SHOT,12, 26, 15, 3, 0, 7, 4, 7, 2, 2, 100, "\ + Skill::skill("shotgun"), AT_SHOT,12, 26, 15, 3, 0, 7, 4, 7, 2, 2, 100, "\ An old shotgun, possibly antique. It is little more than a pair of barrels,\n\ a wood stock, and a hammer to strike the cartridges.", mfb(IF_RELOAD_ONE)|mfb(IF_MODE_BURST)); GUN("Remington 870", 9,2200,c_red, STEEL, PLASTIC, - sk_shotgun, AT_SHOT,16, 30, 17, 3, 5, 10, 0, 8, 3, 6, 100, "\ + Skill::skill("shotgun"), AT_SHOT,16, 30, 17, 3, 5, 10, 0, 8, 3, 6, 100, "\ One of the most popular shotguns on the market, the Remington 870 is used by\n\ hunters and law enforcement agencies alike thanks to its high accuracy and\n\ muzzle velocity.", mfb(IF_RELOAD_ONE)|mfb(IF_MODE_BURST)); GUN("Mossberg 500", 5,2250,c_red, STEEL, PLASTIC, - sk_shotgun, AT_SHOT,15, 30, 17, 3, 0, 13, -2, 9, 3, 8, 80, "\ + Skill::skill("shotgun"), AT_SHOT,15, 30, 17, 3, 0, 13, -2, 9, 3, 8, 80, "\ The Mossberg 500 is a popular series of pump-action shotguns, often acquired\n\ for military use. It is noted for its high durability and low recoil.", mfb(IF_RELOAD_ONE)|mfb(IF_MODE_BURST)); @@ -2546,21 +2546,21 @@ mfb(IF_RELOAD_ONE)|mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("Saiga-12", 3,2300,c_red, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_shotgun, AT_SHOT,15, 36, 17, 3, 0, 17, 2, 7, 4, 10, 500, "\ + Skill::skill("shotgun"), AT_SHOT,15, 36, 17, 3, 0, 17, 2, 7, 4, 10, 500, "\ The Saiga-12 shotgun is designed on the same Kalishnikov pattern as the AK47\n\ rifle. It reloads with a magazine, rather than one shell at a time like most\n\ shotguns.", mfb(IF_MODE_BURST)); GUN("American-180", 2,1600,c_cyan, STEEL, MNULL, - sk_smg, AT_22, 12, 23, 11, 0, 2, 20, 0, 6, 30,165, 500, "\ + Skill::skill("smg"), AT_22, 12, 23, 11, 0, 2, 20, 0, 6, 30,165, 500, "\ The American-180 is a submachine gun developed in the 1960's which fires .22\n\ LR, unusual for an SMG. Though the round is low-powered, the high rate of\n\ fire and large magazine makes the 180 a formidable weapon.", mfb(IF_MODE_BURST)); GUN("Uzi 9mm", 8,2080,c_cyan, STEEL, MNULL, - sk_smg, AT_9MM, 6, 29, 10, 1, 0, 25, -2, 7, 12, 32, 450, "\ + Skill::skill("smg"), AT_9MM, 6, 29, 10, 1, 0, 25, -2, 7, 12, 32, 450, "\ The Uzi 9mm has enjoyed immense popularity, selling more units than any other\n\ submachine gun. It is widely used as a personal defense weapon, or as a\n\ primary weapon by elite frontline forces.", @@ -2569,14 +2569,14 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("TEC-9", 10,1750,c_cyan, STEEL, MNULL, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_smg, AT_9MM, 5, 12, 9, 1, 3, 24, 0, 6, 8, 32, 400, "\ + Skill::skill("smg"), AT_9MM, 5, 12, 9, 1, 3, 24, 0, 6, 8, 32, 400, "\ The TEC-9 is a machine pistol made of cheap polymers and machine stamped\n\ parts. Its rise in popularity among criminals is largely due to its\n\ intimidating looks and low price.", mfb(IF_MODE_BURST)); GUN("Calico M960", 6,2400,c_cyan, STEEL, MNULL, - sk_smg, AT_9MM, 7, 19, 9, 1, -3, 28, -4, 6, 20, 50, 500, "\ + Skill::skill("smg"), AT_9MM, 7, 19, 9, 1, -3, 28, -4, 6, 20, 50, 500, "\ The Calico M960 is an automatic carbine with a unique circular magazine which\n\ allows for high capacities and reduced recoil.", mfb(IF_MODE_BURST)); @@ -2584,14 +2584,14 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("H&K MP5", 12,2800,c_cyan, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_smg, AT_9MM, 12, 26, 10, 2, 1, 18, -3, 8, 8, 30, 400, "\ + Skill::skill("smg"), AT_9MM, 12, 26, 10, 2, 1, 18, -3, 8, 8, 30, 400, "\ The Heckler & Koch MP5 is one of the most widely-used submachine guns in the\n\ world, and has been adopted by special police forces and militaries alike.\n\ Its high degree of accuracy and low recoil are universally praised.", mfb(IF_MODE_BURST)); GUN("MAC-10", 14,1800,c_cyan, STEEL, MNULL, - sk_smg, AT_45, 4, 25, 8, 1, -4, 28, 0, 7, 30, 30, 450, "\ + Skill::skill("smg"), AT_45, 4, 25, 8, 1, -4, 28, 0, 7, 30, 30, 450, "\ The MAC-10 is a popular machine pistol originally designed for military use.\n\ For many years they were the most inexpensive automatic weapon in the US, and\n\ enjoyed great popularity among criminals less concerned with quality firearms." @@ -2599,7 +2599,7 @@ enjoyed great popularity among criminals less concerned with quality firearms." mfb(IF_MODE_BURST)); GUN("H&K UMP45", 12,3000,c_cyan, STEEL, PLASTIC, - sk_smg, AT_45, 13, 20, 11, 1, 0, 13, -3, 8, 4, 25, 450, "\ + Skill::skill("smg"), AT_45, 13, 20, 11, 1, 0, 13, -3, 8, 4, 25, 450, "\ Developed as a successor to the MP5 submachine gun, the UMP45 retains the\n\ earlier model's supreme accuracy and low recoil, but in the higher .45 caliber." , @@ -2608,20 +2608,20 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("TDI Vector", 4,4200,c_cyan, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_smg, AT_45, 13, 20, 9, 0, -2, 15,-14, 7, 8, 30, 450, "\ + Skill::skill("smg"), AT_45, 13, 20, 9, 0, -2, 15,-14, 7, 8, 30, 450, "\ The TDI Vector is a submachine gun with a unique in-line design which makes\n\ recoil very managable, even in the powerful .45 caliber.", mfb(IF_MODE_BURST)); GUN("FN P90", 7,4000,c_cyan, STEEL, PLASTIC, - sk_smg, AT_57, 14, 22, 10, 1, 0, 22, -8, 8, 20, 50, 500, "\ + Skill::skill("smg"), AT_57, 14, 22, 10, 1, 0, 22, -8, 8, 20, 50, 500, "\ The first in a new genre of guns, termed \"personal defense weapons.\" FN\n\ designed the P90 to use their proprietary 5.7x28mm ammunition. It is made\n\ for firing bursts manageably.", mfb(IF_MODE_BURST)); GUN("H&K MP7", 5,3400,c_cyan, STEEL, PLASTIC, - sk_smg, AT_46, 7, 17, 7, 1, 0, 21,-10, 8, 20, 20, 450, "\ + Skill::skill("smg"), AT_46, 7, 17, 7, 1, 0, 21,-10, 8, 20, 20, 450, "\ Designed by Heckler & Koch as a competitor to the FN P90, as well as a\n\ successor to the extremely popular H&K MP5. Using H&K's proprietary 4.6x30mm\n\ ammunition, it is designed for burst fire.", @@ -2630,21 +2630,21 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("Marlin 39A", 14,1600,c_brown,IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_rifle, AT_22, 11, 26, 12, 3, 3, 10, -5, 8, 0, 19, 90, "\ + Skill::skill("rifle"), AT_22, 11, 26, 12, 3, 3, 10, -5, 8, 0, 19, 90, "\ The oldest and longest-produced shoulder firearm in the world. Though it\n\ fires the weak .22 round, it is highly accurate and damaging, and has\n\ essentially no recoil.", mfb(IF_RELOAD_ONE)); GUN("Ruger 10/22", 12,1650,c_brown,IRON, WOOD, - sk_rifle, AT_22, 11, 23, 12, 3, 0, 8, -5, 8, 0, 10, 500, "\ + Skill::skill("rifle"), AT_22, 11, 23, 12, 3, 0, 8, -5, 8, 0, 10, 500, "\ A popular and highly accurate .22 rifle. At the time of its introduction in\n\ 1964, it was one of the first modern .22 rifles designed for quality, and not\n\ as a gun for children.", 0); GUN("Browning BLR", 8,3500,c_brown,IRON, WOOD, - sk_rifle, AT_3006,12, 28, 12, 3, -3, 6, -4, 7, 0, 4, 100, "\ + Skill::skill("rifle"), AT_3006,12, 28, 12, 3, -3, 6, -4, 7, 0, 4, 100, "\ A very popular rifle for hunting and sniping. Its low ammo capacity is\n\ offset by the very powerful .30-06 round it fires.", mfb(IF_RELOAD_ONE)); @@ -2652,28 +2652,28 @@ mfb(IF_RELOAD_ONE)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("Remington 700", 14,3200,c_brown,IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_rifle, AT_3006,12, 34, 13, 3, 7, 9, -3, 8, 0, 4, 75, "\ + Skill::skill("rifle"), AT_3006,12, 34, 13, 3, 7, 9, -3, 8, 0, 4, 75, "\ A very popular and durable hunting or sniping rifle. Popular among SWAT\n\ and US Marine snipers. Highly damaging, but perhaps not as accurate as the\n\ competing Browning BLR.", mfb(IF_RELOAD_ONE)); GUN("SKS", 12,3000,c_brown,IRON, WOOD, - sk_rifle, AT_762, 12, 34, 13, 3, 0, 5, -4, 8, 0, 10, 450, "\ + Skill::skill("rifle"), AT_762, 12, 34, 13, 3, 0, 5, -4, 8, 0, 10, 450, "\ Developed by the Soviets in 1945, this rifle was quickly replaced by the\n\ full-auto AK47. However, due to its superb accuracy and low recoil, this gun\n\ maintains immense popularity.", 0); GUN("Ruger Mini-14", 12,3200,c_brown,IRON, WOOD, - sk_rifle, AT_223, 12, 26, 12, 3, 4, 5, -4, 8, 0, 10, 500, "\ + Skill::skill("rifle"), AT_223, 12, 26, 12, 3, 4, 5, -4, 8, 0, 10, 500, "\ A small, lightweight semi-auto carbine designed for military use. Its superb\n\ accuracy and low recoil makes it more suitable than full-auto rifles for some\n\ situations.", 0); GUN("Savage 111F", 10,3280,c_brown,STEEL, PLASTIC, - sk_rifle, AT_308, 12, 26, 13, 3, 6, 4,-11, 9, 0, 3, 100, "\ + Skill::skill("rifle"), AT_308, 12, 26, 13, 3, 6, 4,-11, 9, 0, 3, 100, "\ A very accurate rifle chambered for the powerful .308 round. Its very low\n\ ammo capacity is offset by its accuracy and near-complete lack of recoil.", mfb(IF_RELOAD_ONE)); @@ -2681,14 +2681,14 @@ mfb(IF_RELOAD_ONE)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("H&K G3", 15,5050,c_blue, IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_rifle, AT_308, 16, 40, 13, 2, 8, 10, 4, 8, 10, 20, 550, "\ + Skill::skill("rifle"), AT_308, 16, 40, 13, 2, 8, 10, 4, 8, 10, 20, 550, "\ An early battle rifle developed after the end of WWII. The G3 is designed to\n\ unload large amounts of deadly ammunition, but it is less suitable over long\n\ ranges.", mfb(IF_MODE_BURST)); GUN("H&K G36", 17,5100,c_blue, IRON, PLASTIC, - sk_rifle, AT_223, 15, 32, 13, 2, 6, 8, 5, 8, 15, 30, 500, "\ + Skill::skill("rifle"), AT_223, 15, 32, 13, 2, 6, 8, 5, 8, 15, 30, 500, "\ Designed as a replacement for the early H&K G3 battle rifle, the G36 is more\n\ accurate, and uses the much-lighter .223 round, allowing for a higher ammo\n\ capacity.", @@ -2697,13 +2697,13 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("AK-47", 16,4000,c_blue, IRON, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_rifle, AT_762, 16, 38, 14, 2, 0, 11, 4, 9, 8, 30, 475, "\ + Skill::skill("rifle"), AT_762, 16, 38, 14, 2, 0, 11, 4, 9, 8, 30, 475, "\ One of the most recognizable assault rifles ever made, the AK-47 is renowned\n\ for its durability even under the worst conditions.", mfb(IF_MODE_BURST)); GUN("FN FAL", 16,4500,c_blue, IRON, WOOD, - sk_rifle, AT_308, 19, 36, 14, 2, 7, 13, -2, 8, 10, 20, 550, "\ + Skill::skill("rifle"), AT_308, 19, 36, 14, 2, 7, 13, -2, 8, 10, 20, 550, "\ A Belgian-designed battle rifle, the FN FAL is not very accurate for a rifle,\n\ but its high fire rate and powerful .308 ammunition have made it one of the\n\ most widely-used battle rifles in the world.", @@ -2712,20 +2712,20 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("Bushmaster ACR", 4,4200,c_blue, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_rifle, AT_223, 15, 27, 18, 2, 2, 10, -2, 8, 3, 30, 475, "\ + Skill::skill("rifle"), AT_223, 15, 27, 18, 2, 2, 10, -2, 8, 3, 30, 475, "\ This carbine was developed for military use in the early 21st century. It is\n\ damaging and accurate, though its rate of fire is a bit slower than competing\n\ .223 carbines.", mfb(IF_MODE_BURST)); GUN("AR-15", 9,4000,c_blue, STEEL, PLASTIC, - sk_rifle, AT_223, 19, 28, 12, 2, 0, 6, 0, 7, 10, 30, 500, "\ + Skill::skill("rifle"), AT_223, 19, 28, 12, 2, 0, 6, 0, 7, 10, 30, 500, "\ A widely used assault rifle and the father of popular rifles such as the M16.\n\ It is light and accurate, but not very durable.", mfb(IF_MODE_BURST)); GUN("M4A1", 7,4400,c_blue, STEEL, PLASTIC, - sk_rifle, AT_223, 14, 24, 13, 2, 4, 7, 2, 6, 10, 30, 475, "\ + Skill::skill("rifle"), AT_223, 14, 24, 13, 2, 4, 7, 2, 6, 10, 30, 475, "\ A popular carbine, long used by the US military. Though accurate, small, and\n\ lightweight, it is infamous for its fragility, particularly in less-than-\n\ ideal terrain.", @@ -2734,21 +2734,21 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("FN SCAR-L", 6,4800,c_blue, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_rifle, AT_223, 15, 29, 18, 2, 1, 6, -4, 8, 10, 30, 500, "\ + Skill::skill("rifle"), AT_223, 15, 29, 18, 2, 1, 6, -4, 8, 10, 30, 500, "\ A modular assault rifle designed for use by US Special Ops units. The 'L' in\n\ its name stands for light, as it uses the lightweight .223 round. It is very\n\ accurate and low on recoil.", mfb(IF_MODE_BURST)); GUN("FN SCAR-H", 5,4950,c_blue, STEEL, PLASTIC, - sk_rifle, AT_308, 16, 32, 20, 2, 1, 8, -4, 8, 8, 20, 550, "\ + Skill::skill("rifle"), AT_308, 16, 32, 20, 2, 1, 8, -4, 8, 8, 20, 550, "\ A modular assault rifle designed for use by US Special Ops units. The 'H' in\n\ its name stands for heavy, as it uses the powerful .308 round. It is fairly\n\ accurate and low on recoil.", mfb(IF_MODE_BURST)); GUN("Steyr AUG", 6,4900,c_blue, STEEL, PLASTIC, - sk_rifle, AT_223, 14, 32, 17, 1, -3, 7, -8, 8, 6, 30, 550, "\ + Skill::skill("rifle"), AT_223, 14, 32, 17, 1, -3, 7, -8, 8, 6, 30, 550, "\ The Steyr AUG is an Austrian assault rifle that uses a bullpup design. It is\n\ used in the armed forces and police forces of many nations, and enjoys\n\ low recoil and high accuracy.", @@ -2756,7 +2756,7 @@ mfb(IF_MODE_BURST)); GUN("M249", 1,7500,c_ltred,STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_rifle, AT_223, 32, 68, 27, -4, -6, 20, 6, 7, 30,200, 750, "\ + Skill::skill("rifle"), AT_223, 32, 68, 27, -4, -6, 20, 6, 7, 30,200, 750, "\ The M249 is a mountable machine gun used by the US military and SWAT teams.\n\ Quite innaccurate and difficult to control, the M249 is designed to fire many\n\ rounds very quickly.", @@ -2765,21 +2765,21 @@ mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("V29 laser pistol", 1,7200,c_magenta,STEEL,PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP - sk_pistol, AT_FUSION,4, 6, 5, 1, -2, 20, 0, 8, 0, 20, 200, "\ + Skill::skill("pistol"), AT_FUSION,4, 6, 5, 1, -2, 20, 0, 8, 0, 20, 200, "\ The V29 laser pistol was designed in the mid-21st century, and was one of the\n\ first firearms to use fusion as its ammunition. It is larger than most\n\ traditional handguns, but displays no recoil whatsoever.", 0); GUN("FTK-93 fusion gun", 1,9800,c_magenta,STEEL, PLASTIC, - sk_rifle, AT_FUSION,18,20, 10, 1, 40, 10, 0, 9, 0, 2, 600, "\ + Skill::skill("rifle"), AT_FUSION,18,20, 10, 1, 40, 10, 0, 9, 0, 2, 600, "\ A very powerful fusion rifle developed shortly before the influx of monsters.\n\ It can only hold two rounds at a time, but a special superheating unit causes\n\ its bolts to be extremely deadly.", 0); GUN("NX-17 charge rifle",1,12000,c_magenta,STEEL, PLASTIC, - sk_rifle, AT_NULL, 13,16, 8, -1, 0, 6, 0, 8, 0, 10, 0, "\ + Skill::skill("rifle"), AT_NULL, 13,16, 8, -1, 0, 6, 0, 8, 0, 10, 0, "\ A multi-purpose rifle, designed for use in conjunction with a unified power\n\ supply, or UPS. It does not reload normally; instead, press fire once to\n\ start charging it from your UPS, then again to unload the charge.", @@ -2788,19 +2788,19 @@ mfb(IF_CHARGE)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("simple flamethr.",1,1600,c_pink, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_shotgun, AT_GAS, 16, 8, 8, -1, -5, 6, 0, 6, 0,800, 800, "\ + Skill::skill("shotgun"), AT_GAS, 16, 8, 8, -1, -5, 6, 0, 6, 0,800, 800, "\ A simple, home-made flamethrower. While its capacity is not superb, it is\n\ more than capable of igniting terrain and monsters alike.", mfb(IF_FIRE_100)); GUN("flamethrower", 1,3800,c_pink, STEEL, MNULL, - sk_shotgun, AT_GAS, 20, 14, 10, -2, 0, 4, 0, 8, 4,1600, 900, "\ + Skill::skill("shotgun"), AT_GAS, 20, 14, 10, -2, 0, 4, 0, 8, 4,1600, 900, "\ A large flamethrower with substantial gas reserves. Very menacing and\n\ deadly.", mfb(IF_FIRE_100)); GUN("tube 40mm launcher",0, 400,c_ltred,STEEL, WOOD, - sk_launcher, AT_40MM,12, 20, 13, -1, 0, 16, 0, 6, 0, 1, 350, "\ + Skill::skill("launcher"), AT_40MM,12, 20, 13, -1, 0, 16, 0, 6, 0, 1, 350, "\ A simple, home-made grenade launcher. Basically a tube with a pin firing\n\ mechanism to activate the grenade.", 0); @@ -2808,21 +2808,21 @@ mechanism to activate the grenade.", // NAME RAR PRC COLOR MAT1 MAT2 GUN("M79 launcher", 5,4000,c_ltred,STEEL, WOOD, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_launcher, AT_40MM,14, 24, 16, -1, 3, 4, -5, 8, 0, 1, 250, "\ + Skill::skill("launcher"), AT_40MM,14, 24, 16, -1, 3, 4, -5, 8, 0, 1, 250, "\ A widely-used grenade launcher which first saw use by American forces in the\n\ Vietnam war. Though mostly replaced by more modern launchers, the M79 still\n\ sees use with many units worldwide.", 0); GUN("M320 launcher", 10,8500,c_ltred,STEEL, MNULL, - sk_launcher, AT_40MM, 5, 13, 6, 0, 0, 12, 5, 9, 0, 1, 150, "\ + Skill::skill("launcher"), AT_40MM, 5, 13, 6, 0, 0, 12, 5, 9, 0, 1, 150, "\ Developed by Heckler & Koch, the M320 grenade launcher has the functionality\n\ of larger launchers in a very small package. However, its smaller size\n\ contributes to a lack of accuracy.", 0); GUN("Milkor MGL", 6,10400,c_ltred,STEEL, MNULL, - sk_launcher, AT_40MM, 24, 45, 13, -1, 0, 5, -2, 8, 2, 6, 300, "\ + Skill::skill("launcher"), AT_40MM, 24, 45, 13, -1, 0, 5, -2, 8, 2, 6, 300, "\ The Milkor Multi-Grenade Launcher is designed to compensate for the drawback\n\ of single-shot grenade launchers by allowing sustained heavy firepower.\n\ However, it is still slow to reload and must be used with careful planning.", @@ -2831,20 +2831,20 @@ mfb(IF_RELOAD_ONE)|mfb(IF_MODE_BURST)); // NAME RAR PRC COLOR MAT1 MAT2 GUN("coilgun", 1, 200,c_ltblue, IRON, MNULL, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP RELOAD - sk_pistol, AT_NAIL, 6, 30, 10, -1, 8, 10, 0, 5, 0, 100, 600, "\ + Skill::skill("pistol"), AT_NAIL, 6, 30, 10, -1, 8, 10, 0, 5, 0, 100, 600, "\ A homemade gun, using electromagnets to accelerate a ferromagnetic\n\ projectile to high velocity. Powered by UPS.", mfb(IF_USE_UPS)); GUN("H&K G80 Railgun", 2,9200,c_ltblue,STEEL, MNULL, - sk_rifle, AT_12MM,12, 36, 12, 1, 5, 15, 0, 8, 0, 20, 550, "\ + Skill::skill("rifle"), AT_12MM,12, 36, 12, 1, 5, 15, 0, 8, 0, 20, 550, "\ Developed by Heckler & Koch in 2033, the railgun magnetically propels\n\ a ferromagnetic projectile using an alternating current. This makes it\n\ silent while still deadly. Powered by UPS.", mfb(IF_USE_UPS)); GUN("Boeing XM-P Plasma Rifle", 1,13000,c_ltblue,STEEL, MNULL, - sk_rifle, AT_PLASMA,15, 40, 12, 1, 5, 5, 0, 8, 5, 25, 700, "\ + Skill::skill("rifle"), AT_PLASMA,15, 40, 12, 1, 5, 5, 0, 8, 5, 25, 700, "\ Boeing developed the focused plasma weaponry together with DARPA. It heats\n\ hydrogen to create plasma and envelops it with polymers to reduce blooming.\n\ While powerful, it suffers from short range. Powered by UPS.", @@ -3086,146 +3086,146 @@ color,mat1,mat2,volume,wgt,melee_dam,0,to_hit,0,type,level,req,fun,intel,time)) BOOK("Playboy", 20, 30,c_pink, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 1, 1, -3, 1, sk_null, 0, 0, 1, 0, 10, "\ + 1, 1, -3, 1, NULL, 0, 0, 1, 0, 10, "\ You can read it for the articles. Or not."); BOOK("US Weekly", 40, 40,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_speech, 1, 0, 1, 3, 8, "\ + 1, 1, -3, 1, Skill::skill("speech"), 1, 0, 1, 3, 8, "\ Weekly news about a bunch of famous people who're all (un)dead now."); BOOK("TIME magazine", 35, 40,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_null, 0, 0, 2, 7, 10, "\ + 1, 1, -3, 1, NULL, 0, 0, 2, 7, 10, "\ Current events concerning a bunch of people who're all (un)dead now."); BOOK("Top Gear magazine", 40, 45,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_driving, 1, 0, 1, 2, 8, "\ + 1, 1, -3, 1, Skill::skill("driving"), 1, 0, 1, 2, 8, "\ Lots of articles about cars and driving techniques."); BOOK("Bon Appetit", 30, 45,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_cooking, 1, 0, 1, 5, 8, "\ + 1, 1, -3, 1, Skill::skill("cooking"), 1, 0, 1, 5, 8, "\ Exciting recipes and restaurant reviews. Full of handy tips about cooking."); BOOK("Birdhouse Monthly", 30, 45,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_carpentry, 1, 0, 1, 5, 8, "\ + 1, 1, -3, 1, Skill::skill("carpentry"), 1, 0, 1, 5, 8, "\ A riveting periodical all about birdhouses and their construction."); BOOK("Guns n Ammo", 20, 48,c_pink, PAPER, MNULL, - 1, 1, -3, 1, sk_gun, 1, 0, 1, 2, 7, "\ + 1, 1, -3, 1, Skill::skill("gun"), 1, 0, 1, 2, 7, "\ Reviews of firearms, and various useful tips about their use."); BOOK("romance novel", 30, 55,c_ltblue, PAPER, MNULL, - 4, 1, -2, 0, sk_null, 0, 0, 2, 4, 15, "\ + 4, 1, -2, 0, NULL, 0, 0, 2, 4, 15, "\ Drama and mild smut."); BOOK("spy novel", 28, 55,c_ltblue, PAPER, MNULL, - 4, 1, -2, 0, sk_null, 0, 0, 3, 5, 18, "\ + 4, 1, -2, 0, NULL, 0, 0, 3, 5, 18, "\ A tale of intrigue and espionage amongst Nazis, no, Commies, no, Iraqis!"); // NAME RAR PRC COLOR MAT1 MAT2 BOOK("scifi novel", 20, 55,c_ltblue, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 3, 1, -3, 0, sk_null, 0, 0, 3, 6, 20, "\ + 3, 1, -3, 0, NULL, 0, 0, 3, 6, 20, "\ Aliens, ray guns, and space ships."); BOOK("drama novel", 40, 55,c_ltblue, PAPER, MNULL, - 4, 1, -2, 0, sk_null, 0, 0, 4, 7, 25, "\ + 4, 1, -2, 0, NULL, 0, 0, 4, 7, 25, "\ A real book for real adults."); BOOK("101 Wrestling Moves", 30, 180,c_green, PAPER, MNULL, - 2, 1, -4, 0, sk_unarmed, 3, 0, 0, 3, 15, "\ + 2, 1, -4, 0, Skill::skill("unarmed"), 3, 0, 0, 3, 15, "\ It seems to be a wrestling manual, poorly photocopied and released on spiral-\n\ bound paper. Still, there are lots of useful tips for unarmed combat."); BOOK("Spetsnaz Knife Techniques",12,200,c_green, PAPER, MNULL, - 1, 1, -5, 0, sk_cutting, 4, 1, 0, 4, 18, "\ + 1, 1, -5, 0, Skill::skill("cutting"), 4, 1, 0, 4, 18, "\ A classic Soviet text on the art of attacking with a blade."); // NAME RAR PRC COLOR MAT1 MAT2 BOOK("Under the Hood", 35, 190,c_green, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 3, 1, -3, 0, sk_mechanics, 3, 0, 0, 5, 18, "\ + 3, 1, -3, 0, Skill::skill("mechanics"), 3, 0, 0, 5, 18, "\ An advanced mechanics manual, covering all sorts of topics."); BOOK("Pitching a Tent",20,200,c_green, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 3, 1, -3, 0, sk_survival, 3, 0, 0, 4, 18,"\ + 3, 1, -3, 0, Skill::skill("survival"), 3, 0, 0, 4, 18,"\ A guide detailing the basics of woodsmanship and outdoor survival."); BOOK("Self-Esteem for Dummies", 50, 160,c_green, PAPER, MNULL, - 3, 1, -3, 0, sk_speech, 3, 0, 0, 5, 20, "\ + 3, 1, -3, 0, Skill::skill("speech"), 3, 0, 0, 5, 20, "\ Full of useful tips for showing confidence in your speech."); BOOK("How to Succeed in Business",40,180,c_green, PAPER, MNULL, - 3, 1, -3, 0, sk_barter, 3, 0, -1, 6, 25, "\ + 3, 1, -3, 0, Skill::skill("barter"), 3, 0, -1, 6, 25, "\ Useful if you want to get a good deal when purchasing goods."); BOOK("The Big Book of First Aid",40,200,c_green, PAPER, MNULL, - 5, 2, -2, 0, sk_firstaid, 3, 0, 0, 7, 20, "\ + 5, 2, -2, 0, Skill::skill("firstaid"), 3, 0, 0, 7, 20, "\ It's big and heavy, but full of great information about first aid."); BOOK("How to Browse the Web", 20, 170,c_green, PAPER, MNULL, - 3, 1, -3, 0, sk_computer, 2, 0, 0, 5, 15, "\ + 3, 1, -3, 0, Skill::skill("computer"), 2, 0, 0, 5, 15, "\ Very beginner-level information about computers."); // NAME RAR PRC COLOR MAT1 MAT2 BOOK("Cooking on a Budget", 35, 160,c_green, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 4, 1, -2, 0, sk_cooking, 3, 0, 0, 4, 10, "\ + 4, 1, -2, 0, Skill::skill("cooking"), 3, 0, 0, 4, 10, "\ A nice cook book that goes beyond recipes and into the chemistry of food."); BOOK("What's a Transistor?", 20, 200,c_green, PAPER, MNULL, - 3, 1, -3, 0, sk_electronics, 3, 0, 0, 7, 20, "\ + 3, 1, -3, 0, Skill::skill("electronics"), 3, 0, 0, 7, 20, "\ A basic manual of electronics and circuit design."); BOOK("Sew What? Clothing!", 15, 190,c_green, PAPER, MNULL, - 3, 1, -3, 0, sk_tailor, 3, 0, 0, 4, 18, "\ + 3, 1, -3, 0, Skill::skill("tailor"), 3, 0, 0, 4, 18, "\ A colorful book about tailoring."); BOOK("How to Trap Anything", 12, 240,c_green, PAPER, MNULL, - 2, 1, -3, 0, sk_traps, 4, 0, 0, 4, 20, "\ + 2, 1, -3, 0, Skill::skill("traps"), 4, 0, 0, 4, 20, "\ A worn manual that describes how to set and disarm a wide variety of traps."); // NAME RAR PRC COLOR MAT1 MAT2 BOOK("Building for Beginners", 10, 220,c_green, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 2, 1, -3, 0, sk_carpentry, 3, 0, 0, 5, 16, "\ + 2, 1, -3, 0, Skill::skill("carpentry"), 3, 0, 0, 5, 16, "\ A large, paperback book detailing several beginner's projects in\n\ construction."); BOOK("Computer Science 301", 8, 500,c_blue, PAPER, MNULL, - 7, 4, 5, 1, sk_computer, 5, 2, -2, 11, 35, "\ + 7, 4, 5, 1, Skill::skill("computer"), 5, 2, -2, 11, 35, "\ A college textbook on computer science."); BOOK("Advanced Electronics", 6, 520,c_blue, PAPER, MNULL, - 7, 5, 5, 1, sk_electronics, 5, 2, -1, 11, 35, "\ + 7, 5, 5, 1, Skill::skill("electronics"), 5, 2, -1, 11, 35, "\ A college textbook on circuit design."); BOOK("Advanced Economics", 12, 480,c_blue, PAPER, MNULL, - 7, 4, 5, 1, sk_barter, 5, 3, -1, 9, 30, "\ + 7, 4, 5, 1, Skill::skill("barter"), 5, 3, -1, 9, 30, "\ A college textbook on economics."); BOOK("Mechanical Mastery",12,495,c_blue,PAPER,MNULL, - 6, 3, 4, 1, sk_mechanics, 6, 3, -1, 6, 30,"\ + 6, 3, 4, 1, Skill::skill("mechanics"), 6, 3, -1, 6, 30,"\ An advanced guide on mechanics and welding, covering topics like\n\ \"Grinding off rust\" and \"Making cursive E\'s\"."); // NAME RAR PRC COLOR MAT1 MAT2 BOOK("Chemistry Textbook", 11, 495,c_blue, PAPER, MNULL, // VOL WGT DAM HIT TYPE LEV REQ FUN INT TIME - 8, 6, 5, 1, sk_cooking, 6, 3, -1, 12, 35, "\ + 8, 6, 5, 1, Skill::skill("cooking"), 6, 3, -1, 12, 35, "\ A college textbook on chemistry."); BOOK("Engineering 301", 6, 550,c_blue, PAPER, MNULL, - 6, 3, 4, 1, sk_carpentry, 6, 3, -1, 8, 30, "\ + 6, 3, 4, 1, Skill::skill("carpentry"), 6, 3, -1, 8, 30, "\ A textbook on civil engineering and construction."); BOOK("SICP", 3, 780,c_blue, PAPER, MNULL, - 6, 5, 6, 0, sk_computer, 8, 4, -1, 13, 50, "\ + 6, 5, 6, 0, Skill::skill("computer"), 8, 4, -1, 13, 50, "\ A classic text, \"The Structure and Interpretation of Computer Programs.\"\n\ Written with examples in LISP, but applicable to any language."); BOOK("Robots for Fun & Profit", 1, 920,c_blue, PAPER, MNULL, - 8, 8, 8, 1, sk_electronics, 10, 5, -1, 14, 55, "\ + 8, 8, 8, 1, Skill::skill("electronics"), 10, 5, -1, 14, 55, "\ A rare book on the design of robots, with lots of helpful step-by-step guides." ); @@ -4032,7 +4032,7 @@ AMMO("Fusion blast", 0,0, AT_FUSION,c_dkgray, MNULL, // NAME RARE COLOR MAT1 MAT2 GUN("fusion blaster", 0,0,c_magenta, STEEL, PLASTIC, // SKILL AMMO VOL WGT MDG HIT DMG ACC REC DUR BST CLIP REL - sk_rifle, AT_FUSION, 12, 0, 0, 0, 0, 4, 0, 10, 0, 1, 500, + Skill::skill("rifle"), AT_FUSION, 12, 0, 0, 0, 0, 4, 0, 10, 0, 1, 500, "",0); diff --git a/iuse.cpp b/iuse.cpp index 1a5c1863716c0..412ac5605aa5f 100644 --- a/iuse.cpp +++ b/iuse.cpp @@ -57,7 +57,7 @@ void iuse::royal_jelly(game *g, player *p, item *it, bool t) void iuse::bandage(game *g, player *p, item *it, bool t) { - int bonus = p->sklevel[sk_firstaid]; + int bonus = p->skillLevel(Skill::skill("firstaid")).level(); hp_part healed; if (p->is_npc()) { // NPCs heal whichever has sustained the most damage @@ -171,7 +171,7 @@ void iuse::bandage(game *g, player *p, item *it, bool t) refresh(); } - p->practice(sk_firstaid, 8); + p->practice(Skill::skill("firstaid"), 8); int dam = 0; if (healed == hp_head) dam = 1 + bonus * .8; @@ -184,7 +184,7 @@ void iuse::bandage(game *g, player *p, item *it, bool t) void iuse::firstaid(game *g, player *p, item *it, bool t) { - int bonus = p->sklevel[sk_firstaid]; + int bonus = p->skillLevel(Skill::skill("firstaid")).level(); hp_part healed; if (p->is_npc()) { // NPCs heal whichever has sustained the most damage @@ -298,7 +298,7 @@ void iuse::firstaid(game *g, player *p, item *it, bool t) refresh(); } - p->practice(sk_firstaid, 8); + p->practice(Skill::skill("firstaid"), 8); int dam = 0; if (healed == hp_head) dam = 10 + bonus * .8; @@ -698,8 +698,8 @@ void iuse::sew(game *g, player *p, item *it, bool t) return; } else if (fix->damage == 0) { p->moves -= 500; - p->practice(sk_tailor, 10); - int rn = dice(4, 2 + p->sklevel[sk_tailor]); + p->practice(Skill::skill("tailor"), 10); + int rn = dice(4, 2 + p->skillLevel(Skill::skill("tailor")).level()); if (p->dex_cur < 8 && one_in(p->dex_cur)) rn -= rng(2, 6); if (p->dex_cur >= 16 || (p->dex_cur > 8 && one_in(16 - p->dex_cur))) @@ -716,8 +716,8 @@ void iuse::sew(game *g, player *p, item *it, bool t) g->add_msg_if_player(p,"You practice your sewing."); } else { p->moves -= 500; - p->practice(sk_tailor, 8); - int rn = dice(4, 2 + p->sklevel[sk_tailor]); + p->practice(Skill::skill("tailor"), 8); + int rn = dice(4, 2 + p->skillLevel(Skill::skill("tailor")).level()); rn -= rng(fix->damage, fix->damage * 2); if (p->dex_cur < 8 && one_in(p->dex_cur)) rn -= rng(2, 6); @@ -805,9 +805,9 @@ void iuse::scissors(game *g, player *p, item *it, bool t) if (cut->made_of(COTTON)) { p->moves -= 25 * cut->volume(); int count = cut->volume(); - if (p->sklevel[sk_tailor] == 0) + if (p->skillLevel(Skill::skill("tailor")) == 0) count = rng(0, count); - else if (p->sklevel[sk_tailor] == 1 && count >= 2) + else if (p->skillLevel(Skill::skill("tailor")) == 1 && count >= 2) count -= rng(0, 2); if (dice(3, 3) > p->dex_cur) count -= rng(1, 3); @@ -841,9 +841,9 @@ void iuse::scissors(game *g, player *p, item *it, bool t) if (cut->made_of(LEATHER)) { p->moves -= 25 * cut->volume(); int count = cut->volume(); - if (p->sklevel[sk_tailor] == 0) + if (p->skillLevel(Skill::skill("tailor")) == 0) count = rng(0, count); - else if (p->sklevel[sk_tailor] == 1 && count >= 2) + else if (p->skillLevel(Skill::skill("tailor")) == 1 && count >= 2) count -= rng(0, 2); if (dice(3, 3) > p->dex_cur) count -= rng(1, 3); @@ -1274,7 +1274,7 @@ void iuse::dig(game *g, player *p, item *it, bool t) g->add_msg_if_player(p,"You dig a pit."); g->m.ter (p->posx + dirx, p->posy + diry) = t_pit; g->m.add_trap(p->posx + dirx, p->posy + diry, tr_pit); - p->practice(sk_traps, 1); + p->practice(Skill::skill("traps"), 1); } else g->add_msg_if_player(p,"You can't dig through %s!", g->m.tername(p->posx + dirx, p->posy + diry).c_str()); @@ -1489,7 +1489,7 @@ That trap needs a 3x3 space to be clear, centered two tiles from you."); } g->add_msg_if_player(p,message.str().c_str()); - p->practice(sk_traps, practice); + p->practice(Skill::skill("traps"), practice); g->m.add_trap(posx, posy, type); p->moves -= 100 + practice * 25; if (type == tr_engine) { @@ -1970,8 +1970,8 @@ void iuse::manhack(game *g, player *p, item *it, bool t) p->moves -= 60; it->invlet = 0; // Remove the manhack from the player's inv monster manhack(g->mtypes[mon_manhack], valid[index].x, valid[index].y); - if (rng(0, p->int_cur / 2) + p->sklevel[sk_electronics] / 2 + - p->sklevel[sk_computer] < rng(0, 4)) + if (rng(0, p->int_cur / 2) + p->skillLevel(Skill::skill("electronics")).level() / 2 + + p->skillLevel(Skill::skill("computer")).level() < rng(0, 4)) g->add_msg_if_player(p,"You misprogram the manhack; it's hostile!"); else manhack.friendly = -1; @@ -1997,8 +1997,8 @@ void iuse::turret(game *g, player *p, item *it, bool t) } it->invlet = 0; // Remove the turret from the player's inv monster turret(g->mtypes[mon_turret], dirx, diry); - if (rng(0, p->int_cur / 2) + p->sklevel[sk_electronics] / 2 + - p->sklevel[sk_computer] < rng(0, 6)) + if (rng(0, p->int_cur / 2) + p->skillLevel(Skill::skill("electronics")).level() / 2 + + p->skillLevel(Skill::skill("computer")).level() < rng(0, 6)) g->add_msg_if_player(p,"You misprogram the turret; it's hostile!"); else turret.friendly = -1; @@ -2048,7 +2048,7 @@ void iuse::tazer(game *g, player *p, item *it, bool t) return; } - int numdice = 3 + (p->dex_cur / 2.5) + p->sklevel[sk_melee] * 2; + int numdice = 3 + (p->dex_cur / 2.5) + p->skillLevel(Skill::skill("melee")).level() * 2; p->moves -= 100; if (mondex != -1) { @@ -2289,9 +2289,9 @@ void iuse::vacutainer(game *g, player *p, item *it, bool t) if (cut->made_of(COTTON)) { p->moves -= 25 * cut->volume(); int count = cut->volume(); - if (p->sklevel[sk_tailor] == 0) + if (p->skillLevel(Skill::skill("tailor")) == 0) count = rng(0, count); - else if (p->sklevel[sk_tailor] == 1 && count >= 2) + else if (p->skillLevel(Skill::skill("tailor")) == 1 && count >= 2) count -= rng(0, 2); if (dice(3, 3) > p->dex_cur) count -= rng(1, 3); @@ -2325,9 +2325,9 @@ if (cut->made_of(COTTON)) { if (cut->made_of(LEATHER)) { p->moves -= 25 * cut->volume(); int count = cut->volume(); - if (p->sklevel[sk_tailor] == 0) + if (p->skillLevel(Skill::skill("tailor")) == 0) count = rng(0, count); - else if (p->sklevel[sk_tailor] == 1 && count >= 2) + else if (p->skillLevel(Skill::skill("tailor")) == 1 && count >= 2) count -= rng(0, 2); if (dice(3, 3) > p->dex_cur) count -= rng(1, 3); @@ -2412,7 +2412,7 @@ void iuse::lumber(game *g, player *p, item *it, bool t) item scrap(g->itypes[itm_splinter], int(g->turn), g->nextinv); p->i_rem(ch); bool drop = false; - int planks = (rng(1, 3) + (p->sklevel[sk_carpentry] * 2)); + int planks = (rng(1, 3) + (p->skillLevel(Skill::skill("carpentry")).level() * 2)); int scraps = 12 - planks; if (planks >= 12) planks = 12; @@ -2577,7 +2577,7 @@ void iuse::bullet_puller(game *g, player *p, item *it, bool t) g->add_msg("You do not have that item!"); return; } - if (p->sklevel[sk_gun] < 2) { + if (p->skillLevel(Skill::skill("gun")) < 2) { g->add_msg("You need to be at least level 2 in the firearms skill before you\ can disassemble ammunition."); return;} diff --git a/map.cpp b/map.cpp index da4cd667ad220..d9ee0bf5bb229 100644 --- a/map.cpp +++ b/map.cpp @@ -296,7 +296,7 @@ bool map::displace_vehicle (game *g, int &x, int &y, const int dx, const int dy, g->u.posx, g->u.posy); continue; } - int trec = rec - psgs[i]->sklevel[sk_driving]; + int trec = rec -psgs[i]->skillLevel(Skill::skill("driving")).level(); if (trec < 0) trec = 0; // add recoil psg->driving_recoil = rec; @@ -410,7 +410,7 @@ void map::vehmove(game *g) if (veh->skidding && one_in(4)) // might turn uncontrollably while skidding veh->move.init (veh->move.dir() + (one_in(2) ? -15 * rng(1, 3) : 15 * rng(1, 3))); - else if (pl_ctrl && rng(0, 4) > g->u.sklevel[sk_driving] && one_in(20)) { + else if (pl_ctrl && rng(0, 4) > g->u.skillLevel(Skill::skill("driving")).level() && one_in(20)) { g->add_msg("You fumble with the %s's controls.", veh->name.c_str()); veh->turn (one_in(2) ? -15 : 15); } @@ -486,8 +486,9 @@ void map::vehmove(game *g) (vel2/100 - sb_bonus < 10 ? 10 : vel2/100 - sb_bonus)); } else if (veh->part_with_feature (ppl[ps], vpf_controls) >= 0) { + const int lose_ctrl_roll = rng (0, imp); - if (lose_ctrl_roll > psg->dex_cur * 2 + psg->sklevel[sk_driving] * 3) { + if (lose_ctrl_roll > psg->dex_cur * 2 + psg->skillLevel(Skill::skill("driving")).level() * 3) { if (psgname.length()) g->add_msg ("%s lose%s control of the %s.", psgname.c_str(), (psg == &g->u ? "" : "s"), veh->name.c_str()); @@ -2022,12 +2023,18 @@ void map::add_trap(const int x, const int y, const trap_id t) void map::disarm_trap(game *g, const int x, const int y) { + Skill *trapsSkill = Skill::skill("traps"); + uint32_t skillLevel = g->u.skillLevel(trapsSkill).level(); + if (tr_at(x, y) == tr_null) { debugmsg("Tried to disarm a trap where there was none (%d %d)", x, y); return; } + + const uint32_t tSkillLevel = g->u.skillLevel(Skill::skill("traps")).level(); const int diff = g->traps[tr_at(x, y)]->difficulty; - int roll = rng(g->u.sklevel[sk_traps], 4 * g->u.sklevel[sk_traps]); + int roll = rng(tSkillLevel, 4 * tSkillLevel); + while ((rng(5, 20) < g->u.per_cur || rng(1, 20) < g->u.dex_cur) && roll < 50) roll++; if (roll >= diff) { @@ -2038,12 +2045,12 @@ void map::disarm_trap(game *g, const int x, const int y) add_item(x, y, g->itypes[comp[i]], 0); } tr_at(x, y) = tr_null; - if(diff > 1.25*g->u.sklevel[sk_traps]) // failure might have set off trap - g->u.practice(sk_traps, 1.5*(diff - g->u.sklevel[sk_traps])); + if(diff > 1.25 * skillLevel) // failure might have set off trap + g->u.practice(trapsSkill, 1.5*(diff - skillLevel)); } else if (roll >= diff * .8) { g->add_msg("You fail to disarm the trap."); - if(diff > 1.25*g->u.sklevel[sk_traps]) - g->u.practice(sk_traps, 1.5*(diff - g->u.sklevel[sk_traps])); + if(diff > 1.25 * skillLevel) + g->u.practice(trapsSkill, 1.5*(diff - skillLevel)); } else { g->add_msg("You fail to disarm the trap, and you set it off!"); @@ -2053,7 +2060,7 @@ void map::disarm_trap(game *g, const int x, const int y) if(diff - roll <= 6) // Give xp for failing, but not if we failed terribly (in which // case the trap may not be disarmable). - g->u.practice(sk_traps, 2*diff); + g->u.practice(trapsSkill, 2*diff); } } diff --git a/melee.cpp b/melee.cpp index ccca18c6b06fb..bf5e81450c299 100644 --- a/melee.cpp +++ b/melee.cpp @@ -53,7 +53,7 @@ int player::base_to_hit(bool real_life, int stat) { if (stat == -999) stat = (real_life ? dex_cur : dex_max); - return 1 + int(stat / 2) + sklevel[sk_melee]; + return 1 + int(stat / 2) + skillLevel(Skill::skill("melee")).level(); } int player::hit_roll() @@ -80,28 +80,28 @@ int player::hit_roll() // Are we unarmed? if (unarmed_attack()) { - best_bonus = sklevel[sk_unarmed]; - if (sklevel[sk_unarmed] > 4) - best_bonus += sklevel[sk_unarmed] - 4; // Extra bonus for high levels + best_bonus = skillLevel(Skill::skill("unarmed")).level(); + if (skillLevel(Skill::skill("unarmed")).level() > 4) + best_bonus += skillLevel(Skill::skill("unarmed")).level() - 4; // Extra bonus for high levels } // Using a bashing weapon? if (weapon.is_bashing_weapon()) { - int bash_bonus = int(sklevel[sk_bashing] / 3); + int bash_bonus = int(skillLevel(Skill::skill("bashing")).level() / 3); if (bash_bonus > best_bonus) best_bonus = bash_bonus; } // Using a cutting weapon? if (weapon.is_cutting_weapon()) { - int cut_bonus = int(sklevel[sk_cutting] / 2); + int cut_bonus = int(skillLevel(Skill::skill("cutting")).level() / 2); if (cut_bonus > best_bonus) best_bonus = cut_bonus; } // Using a spear? if (weapon.has_flag(IF_SPEAR) || weapon.has_flag(IF_STAB)) { - int stab_bonus = int(sklevel[sk_stabbing] / 2); + int stab_bonus = int(skillLevel(Skill::skill("stabbing")).level() / 2); if (stab_bonus > best_bonus) best_bonus = stab_bonus; } @@ -341,8 +341,8 @@ void player::hit_player(game *g, player &p, bool allow_grab) if (allow_grab && technique == TEC_GRAB) { // Move our weapon to a temp slot, if it's not unarmed if (p.weapon.has_technique(TEC_BREAK, &p) && - dice(p.dex_cur + p.sklevel[sk_melee], 12) > - dice(dex_cur + sklevel[sk_melee], 10)) { + dice(p.dex_cur + p.skillLevel(Skill::skill("melee")).level(), 12) > + dice(dex_cur + skillLevel(Skill::skill("melee")).level(), 10)) { if (is_u) g->add_msg("%s break%s the grab!", target.c_str(), (p.is_npc() ? "s" : "")); } else if (!unarmed_attack()) { @@ -381,7 +381,7 @@ bool player::scored_crit(int target_dodge) // Weapon to-hit roll int chance = 25; if (unarmed_attack()) { // Unarmed attack: 1/2 of unarmed skill is to-hit - for (int i = 1; i <= int(sklevel[sk_unarmed] * .5); i++) + for (int i = 1; i <= int(skillLevel(Skill::skill("unarmed")).level() * .5); i++) chance += (50 / (2 + i)); } if (weapon.type->m_to_hit > 0) { @@ -427,17 +427,17 @@ bool player::scored_crit(int target_dodge) // Skill level roll int best_skill = 0; - if (weapon.is_bashing_weapon() && sklevel[sk_bashing] > best_skill) - best_skill = sklevel[sk_bashing]; - if (weapon.is_cutting_weapon() && sklevel[sk_cutting] > best_skill) - best_skill = sklevel[sk_cutting]; + if (weapon.is_bashing_weapon() && skillLevel(Skill::skill("bashing")).level() > best_skill) + best_skill = skillLevel(Skill::skill("bashing")).level(); + if (weapon.is_cutting_weapon() && skillLevel(Skill::skill("cutting")).level() > best_skill) + best_skill = skillLevel(Skill::skill("cutting")).level(); if ((weapon.has_flag(IF_SPEAR) || weapon.has_flag(IF_STAB)) && - sklevel[sk_stabbing] > best_skill) - best_skill = sklevel[sk_stabbing]; - if (unarmed_attack() && sklevel[sk_unarmed] > best_skill) - best_skill = sklevel[sk_unarmed]; + skillLevel(Skill::skill("stabbing")).level() > best_skill) + best_skill = skillLevel(Skill::skill("stabbing")).level(); + if (unarmed_attack() && skillLevel(Skill::skill("unarmed")).level() > best_skill) + best_skill = skillLevel(Skill::skill("unarmed")).level(); - best_skill += int(sklevel[sk_melee] / 2.5); + best_skill += int(skillLevel(Skill::skill("melee")).level() / 2.5); chance = 25; if (best_skill > 3) { @@ -465,7 +465,7 @@ int player::dodge(game *g) if (activity.type != ACT_NULL) return 0; int ret = 4 + (dex_cur / 2); - ret += sklevel[sk_dodge]; + ret += skillLevel(Skill::skill("dodge")).level(); ret += disease_intensity(DI_DODGE_BOOST); ret -= (encumb(bp_legs) / 2) + encumb(bp_torso); ret += int(current_speed(g) / 150); @@ -482,15 +482,15 @@ int player::dodge(game *g) else if (str_max <= 5) ret++; // Bonus if we're small if (dodges_left <= 0) { // We already dodged this turn - if (rng(1, sklevel[sk_dodge] + dex_cur + 15) <= sklevel[sk_dodge] + dex_cur) + if (rng(1, skillLevel(Skill::skill("dodge")).level() + dex_cur + 15) <= skillLevel(Skill::skill("dodge")).level() + dex_cur) ret = rng(0, ret); else ret = 0; } dodges_left--; // If we're over our cap, average it with our cap - if (ret > int(dex_cur / 2) + sklevel[sk_dodge] * 2) - ret = ( ret + int(dex_cur / 2) + sklevel[sk_dodge] * 2 ) / 2; + if (ret > int(dex_cur / 2) + skillLevel(Skill::skill("dodge")).level() * 2) + ret = ( ret + int(dex_cur / 2) + skillLevel(Skill::skill("dodge")).level() * 2 ) / 2; return ret; } @@ -518,9 +518,9 @@ int player::roll_bash_damage(monster *z, bool crit) { int ret = 0; int stat = str_cur; // Which stat determines damage? - int skill = sklevel[sk_bashing]; // Which skill determines damage? + int skill = skillLevel(Skill::skill("bashing")).level(); // Which skill determines damage? if (unarmed_attack()) - skill = sklevel[sk_unarmed]; + skill = skillLevel(Skill::skill("unarmed")).level(); switch (weapon.typeId()) { // Some martial arts change which stat case itm_style_crane: @@ -554,7 +554,7 @@ int player::roll_bash_damage(monster *z, bool crit) bash_cap = 5 + stat + skill; if (unarmed_attack()) - bash_dam = rng(0, int(stat / 2) + sklevel[sk_unarmed]); + bash_dam = rng(0, int(stat / 2) + skillLevel(Skill::skill("unarmed")).level()); if (crit) { bash_dam *= 1.5; @@ -594,7 +594,7 @@ int player::roll_cut_damage(monster *z, bool crit) { if (weapon.has_flag(IF_SPEAR)) return 0; // Stabs, doesn't cut! - int z_armor_cut = (z == NULL ? 0 : z->armor_cut() - sklevel[sk_cutting] / 2); + int z_armor_cut = (z == NULL ? 0 : z->armor_cut() - skillLevel(Skill::skill("cutting")).level() / 2); if (crit) z_armor_cut /= 2; @@ -607,7 +607,7 @@ int player::roll_cut_damage(monster *z, bool crit) if (has_trait(PF_CLAWS)) ret += 6; if (has_trait(PF_TALONS)) - ret += 6 + (sklevel[sk_unarmed] > 8 ? 8 : sklevel[sk_unarmed]); + ret += 6 + (skillLevel(Skill::skill("unarmed")).level() > 8 ? 8 : skillLevel(Skill::skill("unarmed")).level()); if (has_trait(PF_SLIME_HANDS) && (z == NULL || !z->has_flag(MF_ACIDPROOF))) ret += rng(4, 6); } @@ -616,13 +616,13 @@ int player::roll_cut_damage(monster *z, bool crit) return 0; // No negative damage! // 80%, 88%, 96%, 104%, 112%, 116%, 120%, 124%, 128%, 132% - if (sklevel[sk_cutting] <= 5) - ret *= double( 0.8 + 0.08 * sklevel[sk_cutting] ); + if (skillLevel(Skill::skill("cutting")).level() <= 5) + ret *= double( 0.8 + 0.08 * skillLevel(Skill::skill("cutting")).level() ); else - ret *= double( 0.92 + 0.04 * sklevel[sk_cutting] ); + ret *= double( 0.92 + 0.04 * skillLevel(Skill::skill("cutting")).level() ); if (crit) - ret *= double( 1.0 + double(sklevel[sk_cutting] / 12) ); + ret *= double( 1.0 + double(skillLevel(Skill::skill("cutting")).level() / 12) ); return ret; } @@ -630,7 +630,7 @@ int player::roll_cut_damage(monster *z, bool crit) int player::roll_stab_damage(monster *z, bool crit) { int ret = 0; - int z_armor = (z == NULL ? 0 : z->armor_cut() - 3 * sklevel[sk_stabbing]); + int z_armor = (z == NULL ? 0 : z->armor_cut() - 3 * skillLevel(Skill::skill("stabbing")).level()); if (crit) z_armor /= 3; @@ -663,7 +663,7 @@ int player::roll_stab_damage(monster *z, bool crit) return 0; // No negative stabbing! if (crit) { - int multiplier = double( 1.0 + double(sklevel[sk_stabbing] / 5) ); + int multiplier = double( 1.0 + double(skillLevel(Skill::skill("stabbing")).level() / 5) ); if (multiplier > 2.5) multiplier = 2.5; ret *= multiplier; @@ -679,10 +679,10 @@ int player::roll_stuck_penalty(monster *z, bool stabbing) cutarm = (z == NULL ? 6 : z->armor_cut()); if (stabbing) ret = weapon.damage_cut() * 3 + basharm * 3 + cutarm * 3 - - dice(sklevel[sk_stabbing], 10); + dice(skillLevel(Skill::skill("stabbing")).level(), 10); else ret = weapon.damage_cut() * 4 + basharm * 5 + cutarm * 4 - - dice(sklevel[sk_cutting], 10); + dice(skillLevel(Skill::skill("cutting")).level(), 10); if (ret >= weapon.damage_cut() * 10) return weapon.damage_cut() * 10; @@ -720,7 +720,7 @@ technique_id player::pick_technique(game *g, monster *z, player *p, possible.push_back(TEC_PRECISE); if (weapon.has_technique(TEC_BRUTAL, this) && !downed && - str_cur + sklevel[sk_melee] >= 4 + base_str_req) + str_cur + skillLevel(Skill::skill("melee")).level() >= 4 + base_str_req) possible.push_back(TEC_BRUTAL); } @@ -729,8 +729,8 @@ technique_id player::pick_technique(game *g, monster *z, player *p, if (weapon.has_technique(TEC_DISARM, this) && !z && p->weapon.typeId() != 0 && !p->weapon.has_flag(IF_UNARMED_WEAPON) && - dice( dex_cur + sklevel[sk_unarmed], 8) > - dice(p->dex_cur + p->sklevel[sk_melee], 10)) + dice( dex_cur + skillLevel(Skill::skill("unarmed")).level(), 8) > + dice(p->dex_cur + p->skillLevel(Skill::skill("melee")).level(), 10)) possible.push_back(TEC_DISARM); if (weapon.has_technique(TEC_GRAB, this) && allowgrab) @@ -740,7 +740,7 @@ technique_id player::pick_technique(game *g, monster *z, player *p, possible.push_back(TEC_RAPID); if (weapon.has_technique(TEC_THROW, this) && !downed && - str_cur + sklevel[sk_melee] >= 4 + base_str_req * 4 + rng(-4, 4)) + str_cur + skillLevel(Skill::skill("melee")).level() >= 4 + base_str_req * 4 + rng(-4, 4)) possible.push_back(TEC_THROW); if (weapon.has_technique(TEC_WIDE, this)) { // Count monsters @@ -894,7 +894,7 @@ technique_id player::pick_defensive_technique(game *g, monster *z, player *p) if (z != NULL) foe_melee_skill = z->type->melee_skill; else if (p != NULL) - foe_melee_skill = p->dex_cur + p->sklevel[sk_melee]; + foe_melee_skill = p->dex_cur + p->skillLevel(Skill::skill("melee")).level(); int foe_dodge = 0; if (z != NULL) @@ -915,26 +915,26 @@ technique_id player::pick_defensive_technique(game *g, monster *z, player *p) blocks_left--; if (weapon.has_technique(TEC_WBLOCK_3) && - dice(dex_cur + sklevel[sk_melee], 12) > dice(foe_melee_skill, 10)) + dice(dex_cur + skillLevel(Skill::skill("melee")).level(), 12) > dice(foe_melee_skill, 10)) return TEC_WBLOCK_3; if (weapon.has_technique(TEC_WBLOCK_2) && - dice(dex_cur + sklevel[sk_melee], 6) > dice(foe_melee_skill, 10)) + dice(dex_cur + skillLevel(Skill::skill("melee")).level(), 6) > dice(foe_melee_skill, 10)) return TEC_WBLOCK_2; if (weapon.has_technique(TEC_WBLOCK_1) && - dice(dex_cur + sklevel[sk_melee], 3) > dice(foe_melee_skill, 10)) + dice(dex_cur + skillLevel(Skill::skill("melee")).level(), 3) > dice(foe_melee_skill, 10)) return TEC_WBLOCK_1; if (weapon.has_technique(TEC_DEF_DISARM, this) && z == NULL && p->weapon.typeId() != 0 && !p->weapon.has_flag(IF_UNARMED_WEAPON) && - dice( dex_cur + sklevel[sk_unarmed], 8) > - dice(p->dex_cur + p->sklevel[sk_melee], 10)) + dice( dex_cur + skillLevel(Skill::skill("unarmed")).level(), 8) > + dice(p->dex_cur + p->skillLevel(Skill::skill("melee")).level(), 10)) return TEC_DEF_DISARM; if (weapon.has_technique(TEC_DEF_THROW, this) && - str_cur + sklevel[sk_melee] >= foe_size + rng(-4, 4) && + str_cur + skillLevel(Skill::skill("melee")).level() >= foe_size + rng(-4, 4) && hit_roll() > rng(1, 5) + foe_dodge && !one_in(3)) return TEC_DEF_THROW; @@ -944,13 +944,13 @@ technique_id player::pick_defensive_technique(game *g, monster *z, player *p) if (weapon.has_technique(TEC_BLOCK_LEGS, this) && (hp_cur[hp_leg_l] >= 20 || hp_cur[hp_leg_r] >= 20) && - dice(dex_cur + sklevel[sk_unarmed] + sklevel[sk_melee], 13) > + dice(dex_cur + skillLevel(Skill::skill("unarmed")).level() + skillLevel(Skill::skill("melee")).level(), 13) > dice(8 + foe_melee_skill, 10)) return TEC_BLOCK_LEGS; if (weapon.has_technique(TEC_BLOCK, this) && (hp_cur[hp_arm_l] >= 20 || hp_cur[hp_arm_r] >= 20) && - dice(dex_cur + sklevel[sk_unarmed] + sklevel[sk_melee], 16) > + dice(dex_cur + skillLevel(Skill::skill("unarmed")).level() + skillLevel(Skill::skill("melee")).level(), 16) > dice(6 + foe_melee_skill, 10)) return TEC_BLOCK; @@ -1119,7 +1119,7 @@ void player::melee_special_effects(game *g, monster *z, player *p, bool crit, // Bashing crit if (crit && !unarmed_attack()) { - int turns_stunned = int(bash_dam / 20) + rng(0, int(sklevel[sk_bashing] / 2)); + int turns_stunned = int(bash_dam / 20) + rng(0, int(skillLevel(Skill::skill("bashing")).level() / 2)); if (turns_stunned > 6) turns_stunned = 6; if (turns_stunned > 0) { @@ -1245,7 +1245,7 @@ void player::melee_special_effects(game *g, monster *z, player *p, bool crit, } else { if (mon && (cut_dam >= z->hp || stab_dam >= z->hp)) { cutting_penalty /= 2; - cutting_penalty -= rng(sklevel[sk_cutting], sklevel[sk_cutting] * 2 + 2); + cutting_penalty -= rng(skillLevel(Skill::skill("cutting")).level(), skillLevel(Skill::skill("cutting")).level() * 2 + 2); } if (cutting_penalty > 0) moves -= cutting_penalty; @@ -1357,7 +1357,7 @@ std::vector player::mutation_attacks(monster *z, player *p) std::stringstream text; if (has_trait(PF_FANGS) && !wearing_something_on(bp_mouth) && - one_in(20 - dex_cur - sklevel[sk_unarmed])) { + one_in(20 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " sink" << (is_u ? " " : "s ") << your << " fangs into " << target << "!"; @@ -1366,7 +1366,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_MANDIBLES) && one_in(22 - dex_cur - sklevel[sk_unarmed])) { + if (has_trait(PF_MANDIBLES) && one_in(22 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " slice" << (is_u ? " " : "s ") << target << " with " << your << " mandibles!"; @@ -1375,7 +1375,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_BEAK) && one_in(15 - dex_cur - sklevel[sk_unarmed])) { + if (has_trait(PF_BEAK) && one_in(15 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " peck" << (is_u ? " " : "s ") << target << "!"; tmp.text = text.str(); @@ -1383,7 +1383,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_HOOVES) && one_in(25 - dex_cur - 2 * sklevel[sk_unarmed])) { + if (has_trait(PF_HOOVES) && one_in(25 - dex_cur - 2 * skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " kick" << (is_u ? " " : "s ") << target << " with " << your << " hooves!"; @@ -1394,7 +1394,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_HORNS) && one_in(20 - dex_cur - sklevel[sk_unarmed])) { + if (has_trait(PF_HORNS) && one_in(20 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " headbutt" << (is_u ? " " : "s ") << target << " with " << your << " horns!"; @@ -1404,7 +1404,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_HORNS_CURLED) && one_in(20 - dex_cur - sklevel[sk_unarmed])) { + if (has_trait(PF_HORNS_CURLED) && one_in(20 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " headbutt" << (is_u ? " " : "s ") << target << " with " << your << " curled horns!"; @@ -1413,7 +1413,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_HORNS_POINTED) && one_in(22 - dex_cur - sklevel[sk_unarmed])){ + if (has_trait(PF_HORNS_POINTED) && one_in(22 - dex_cur - skillLevel(Skill::skill("unarmed")).level())){ special_attack tmp; text << You << " stab" << (is_u ? " " : "s ") << target << " with " << your << " pointed horns!"; @@ -1422,7 +1422,7 @@ std::vector player::mutation_attacks(monster *z, player *p) ret.push_back(tmp); } - if (has_trait(PF_ANTLERS) && one_in(20 - dex_cur - sklevel[sk_unarmed])) { + if (has_trait(PF_ANTLERS) && one_in(20 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text << You << " butt" << (is_u ? " " : "s ") << target << " with " << your << " antlers!"; @@ -1460,7 +1460,7 @@ std::vector player::mutation_attacks(monster *z, player *p) num_attacks--; for (int i = 0; i < num_attacks; i++) { - if (one_in(18 - dex_cur - sklevel[sk_unarmed])) { + if (one_in(18 - dex_cur - skillLevel(Skill::skill("unarmed")).level())) { special_attack tmp; text.str(""); text << You << " slap" << (is_u ? " " : "s ") << target << " with " << @@ -1560,25 +1560,25 @@ void melee_practice(player &u, bool hit, bool unarmed, bool bashing, bool cutting, bool stabbing) { if (!hit) { - u.practice(sk_melee, rng(2, 5)); + u.practice(Skill::skill("melee"), rng(2, 5)); if (unarmed) - u.practice(sk_unarmed, 2); + u.practice(Skill::skill("unarmed"), 2); if (bashing) - u.practice(sk_bashing, 2); + u.practice(Skill::skill("bashing"), 2); if (cutting) - u.practice(sk_cutting, 2); + u.practice(Skill::skill("cutting"), 2); if (stabbing) - u.practice(sk_stabbing, 2); + u.practice(Skill::skill("stabbing"), 2); } else { - u.practice(sk_melee, rng(5, 10)); + u.practice(Skill::skill("melee"), rng(5, 10)); if (unarmed) - u.practice(sk_unarmed, rng(5, 10)); + u.practice(Skill::skill("unarmed"), rng(5, 10)); if (bashing) - u.practice(sk_bashing, rng(5, 10)); + u.practice(Skill::skill("bashing"), rng(5, 10)); if (cutting) - u.practice(sk_cutting, rng(5, 10)); + u.practice(Skill::skill("cutting"), rng(5, 10)); if (stabbing) - u.practice(sk_stabbing, rng(5, 10)); + u.practice(Skill::skill("stabbing"), rng(5, 10)); } } diff --git a/mission.cpp b/mission.cpp index 5df6118cbcf9e..d61b80e3a8289 100644 --- a/mission.cpp +++ b/mission.cpp @@ -35,7 +35,7 @@ std::string mission::save_info() ret << type->id; ret << description << " <> " << (failed ? 1 : 0) << " " << value << " " << reward.type << " " << reward.value << " " << reward.item_id << - " " << reward.skill_id << " " << uid << " " << target.x << " " << + " " << (reward.skill?reward.skill->id():0) << " " << uid << " " << target.x << " " << target.y << " " << item_id << " " << count << " " << deadline << " " << npc_id << " " << good_fac_id << " " << bad_fac_id << " " << step << " " << follow_up; @@ -61,7 +61,7 @@ void mission::load_info(game *g, std::ifstream &data) follow_up = mission_id(tmpfollow); reward.type = npc_favor_type(reward_id); reward.item_id = itype_id( rew_item ); - reward.skill_id = skill( rew_skill ); + reward.skill = Skill::skill( rew_skill ); item_id = itype_id(itemid); } diff --git a/monattack.cpp b/monattack.cpp index cfd1513e6890a..d592b5ef02c04 100644 --- a/monattack.cpp +++ b/monattack.cpp @@ -717,7 +717,7 @@ void mattack::dermatik(game *g, monster *z) // Can we swat the bug away? int dodge_roll = z->dodge_roll(); - int swat_skill = (g->u.sklevel[sk_melee] + g->u.sklevel[sk_unarmed] * 2) / 3; + int swat_skill = (g->u.skillLevel(Skill::skill("melee")).level() + g->u.skillLevel(Skill::skill("unarmed")).level() * 2) / 3; int player_swat = dice(swat_skill, 10); if (player_swat > dodge_roll) { g->add_msg("The %s lands on you, but you swat it off.", z->name().c_str()); @@ -1144,8 +1144,10 @@ void mattack::smg(game *g, monster *z) g->add_msg("The %s fires its smg!", z->name().c_str()); player tmp; tmp.name = "The " + z->name(); - tmp.sklevel[sk_smg] = 1; - tmp.sklevel[sk_gun] = 0; + + tmp.skillLevel(Skill::skill("smg")).level(1); + tmp.skillLevel(Skill::skill("gun")).level(0); + tmp.recoil = 0; tmp.posx = z->posx; tmp.posy = z->posy; @@ -1181,8 +1183,10 @@ void mattack::smg(game *g, monster *z) // Set up a temporary player to fire this gun player tmp; tmp.name = "The " + z->name(); - tmp.sklevel[sk_smg] = 1; - tmp.sklevel[sk_gun] = 0; + + tmp.skillLevel(Skill::skill("smg")).level(1); + tmp.skillLevel(Skill::skill("gun")).level(0); + tmp.recoil = 0; tmp.posx = z->posx; tmp.posy = z->posy; diff --git a/monmove.cpp b/monmove.cpp index d3dbb7e96bd5f..2b88c665c2e3e 100644 --- a/monmove.cpp +++ b/monmove.cpp @@ -533,7 +533,7 @@ void monster::hit_player(game *g, player &p, bool can_grab) if (!is_npc) g->add_msg("The %s grabs you!", name().c_str()); if (p.weapon.has_technique(TEC_BREAK, &p) && - dice(p.dex_cur + p.sklevel[sk_melee], 12) > dice(type->melee_dice, 10)){ + dice(p.dex_cur + p.skillLevel(Skill::skill("melee")).level(), 12) > dice(type->melee_dice, 10)){ if (!is_npc) g->add_msg("You break the grab!"); } else diff --git a/monster.cpp b/monster.cpp index 490c85240d609..bb089699dc782 100644 --- a/monster.cpp +++ b/monster.cpp @@ -476,15 +476,16 @@ int monster::trigger_sum(game *g, std::vector *triggers) return ret; } -int monster::hit(game *g, player &p, body_part &bp_hit) -{ +int monster::hit(game *g, player &p, body_part &bp_hit) { + Skill *dodgeSkill = Skill::skill("dodge"); + int numdice = type->melee_skill; if (dice(numdice, 10) <= dice(p.dodge(g), 10) && !one_in(20)) { - if (numdice > p.sklevel[sk_dodge]) - p.practice(sk_dodge, 10); + if (p.skillLevel(dodgeSkill) < numdice) + p.practice(dodgeSkill, 10); return 0; // We missed! } - p.practice(sk_dodge, 5); + p.practice(dodgeSkill, 5); int ret = 0; int highest_hit; switch (type->size) { diff --git a/newcharacter.cpp b/newcharacter.cpp index a877ba076fc37..c6f15b6d77276 100644 --- a/newcharacter.cpp +++ b/newcharacter.cpp @@ -119,9 +119,13 @@ bool player::create(game *g, character_type type, std::string tempname) case 8: case 9: rn = random_skill(); - if (points >= sklevel[rn] + 1) { - points -= sklevel[rn] + 1; - sklevel[rn] += 2; + + Skill *aSkill = Skill::skill(rn); + uint32_t level = skillLevel(aSkill).level(); + + if (level < points) { + points -= level + 1; + skillLevel(aSkill).level(level + 2); } break; } @@ -376,7 +380,7 @@ int set_stats(WINDOW* w, player *u, int &points) mvwprintz(w, 8, 2, COL_STAT_ACT, "Intelligence: %d ", u->int_max); mvwprintz(w, 9, 2, c_ltgray, "Perception: %d ", u->per_max); mvwprintz(w, 6, 33, COL_STAT_ACT, "Skill comprehension: %d%%%% ", - u->comprehension_percent(sk_null, false)); + u->skillLevel("melee").comprehension(u->int_max)); mvwprintz(w, 7, 33, COL_STAT_ACT, "Read times: %d%%%% ", u->read_speed(false)); mvwprintz(w, 8, 33, COL_STAT_ACT, " Intelligence is also used when crafting, "); @@ -706,6 +710,7 @@ int set_skills(WINDOW* w, player *u, int &points) mvwprintz(w,1,40, h_ltgray, " SKILLS "); int cur_sk = 1; + Skill *currentSkill = Skill::skill(cur_sk); do { mvwprintz(w, 3, 2, c_ltgray, "Points left: %d ", points); @@ -716,56 +721,60 @@ int set_skills(WINDOW* w, player *u, int &points) "); mvwprintz(w, 24, 0, c_ltgray, "\ "); - if (points >= u->sklevel[cur_sk] + 1) + if (points >= u->skillLevel(currentSkill).level() + 1) mvwprintz(w, 3, 30, COL_SKILL_USED, "Upgrading %s costs %d points ", - skill_name(cur_sk).c_str(), u->sklevel[cur_sk] + 1); + skill_name(cur_sk).c_str(), u->skillLevel(currentSkill).level() + 1); else mvwprintz(w, 3, 30, c_ltred, "Upgrading %s costs %d points ", - skill_name(cur_sk).c_str(), u->sklevel[cur_sk] + 1); - mvwprintz(w, 22, 0, COL_SKILL_USED, skill_description(cur_sk).c_str()); + skill_name(cur_sk).c_str(), u->skillLevel(currentSkill).level() + 1); + mvwprintz(w, 22, 0, COL_SKILL_USED, currentSkill->description().c_str()); if (cur_sk <= 7) { for (int i = 1; i < 17; i++) { + Skill *thisSkill = Skill::skill(i); + mvwprintz(w, 4 + i, 0, c_ltgray, "\ "); // Clear the line - if (u->sklevel[i] == 0) { + if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 4 + i, 0, (i == cur_sk ? h_ltgray : c_ltgray), - skill_name(i).c_str()); + thisSkill->name().c_str()); } else { mvwprintz(w, 4 + i, 0, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), "%s ", skill_name(i).c_str()); - for (int j = 0; j < u->sklevel[i]; j++) + for (int j = 0; j < u->skillLevel(thisSkill).level(); j++) wprintz(w, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), "*"); } } - } else if (cur_sk >= num_skill_types - 9) { + } else if (cur_sk >= Skill::skills.size() - 9) { for (int i = num_skill_types - 16; i < num_skill_types; i++) { + Skill *thisSkill = Skill::skill(i); mvwprintz(w, 21 + i - num_skill_types, 0, c_ltgray, "\ "); // Clear the line - if (u->sklevel[i] == 0) { + if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 21 + i - num_skill_types, 0, - (i == cur_sk ? h_ltgray : c_ltgray), skill_name(i).c_str()); + (i == cur_sk ? h_ltgray : c_ltgray), thisSkill->name().c_str()); } else { mvwprintz(w, 21 + i - num_skill_types, 0, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), "%s ", - skill_name(i).c_str()); - for (int j = 0; j < u->sklevel[i]; j++) + thisSkill->name().c_str()); + for (int j = 0; j < u->skillLevel(thisSkill).level(); j++) wprintz(w, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), "*"); } } } else { for (int i = cur_sk - 7; i < cur_sk + 9; i++) { + Skill *thisSkill = Skill::skill(i); mvwprintz(w, 12 + i - cur_sk, 0, c_ltgray, "\ "); // Clear the line - if (u->sklevel[i] == 0) { + if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 12 + i - cur_sk, 0, (i == cur_sk ? h_ltgray : c_ltgray), - skill_name(i).c_str()); + thisSkill->name().c_str()); } else { mvwprintz(w, 12 + i - cur_sk, 0, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), - "%s ", skill_name(i).c_str()); - for (int j = 0; j < u->sklevel[i]; j++) + "%s ", thisSkill->name().c_str()); + for (int j = 0; j < u->skillLevel(thisSkill).level(); j++) wprintz(w, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), "*"); } } @@ -774,23 +783,25 @@ int set_skills(WINDOW* w, player *u, int &points) wrefresh(w); switch (input()) { case 'j': - if (cur_sk < num_skill_types - 1) - cur_sk++; + if (cur_sk < Skill::skills.size() - 1) + cur_sk++; + currentSkill = Skill::skill(cur_sk); break; case 'k': if (cur_sk > 1) cur_sk--; + currentSkill = Skill::skill(cur_sk); break; case 'h': - if (u->sklevel[cur_sk] > 0) { - points += u->sklevel[cur_sk] - 1; - u->sklevel[cur_sk] -= 2; + if (u->skillLevel(currentSkill).level()) { + u->skillLevel(currentSkill).level(u->skillLevel(currentSkill).level() - 2); + points += u->skillLevel(currentSkill).level() + 1; } break; case 'l': - if (points >= u->sklevel[cur_sk] + 1) { - points -= u->sklevel[cur_sk] + 1; - u->sklevel[cur_sk] += 2; + if (points >= u->skillLevel(currentSkill).level() + 1) { + points -= u->skillLevel(currentSkill).level() + 1; + u->skillLevel(currentSkill).level(u->skillLevel(currentSkill).level() + 2); } break; case '<': @@ -937,7 +948,7 @@ int player::random_bad_trait() int random_skill() { - return rng(1, num_skill_types - 1); + return rng(1, Skill::skills.size() - 1); } int calc_HP(int strength, bool tough) diff --git a/npc.cpp b/npc.cpp index 69d98e191e1be..95682ad3de110 100644 --- a/npc.cpp +++ b/npc.cpp @@ -1342,7 +1342,7 @@ std::vector npc::skills_offered_to(player *p) if (p == NULL) return ret; for (int i = 0; i < num_skill_types; i++) { - if (sklevel[i] > p->sklevel[i]) + if (p->skillLevel(Skill::skill(i)) < sklevel[i]) ret.push_back( skill(i) ); } return ret; @@ -1561,7 +1561,7 @@ int npc::value(item &it) it_book* book = dynamic_cast(it.type); if (book->intel <= int_cur) { ret += book->fun; - if (sklevel[book->type] < book->level && sklevel[book->type] >= book->req) + if (skillLevel(book->type) < book->level && skillLevel(book->type) >= book->req) ret += book->level * 3; } } diff --git a/npc.h b/npc.h index 42b2da8de599d..4e7de8488ef2b 100644 --- a/npc.h +++ b/npc.h @@ -127,13 +127,13 @@ struct npc_favor npc_favor_type type; int value; itype_id item_id; - skill skill_id; + Skill *skill; npc_favor() { type = FAVOR_NULL; value = 0; item_id = itm_null; - skill_id = sk_null; + skill = NULL; }; }; @@ -222,7 +222,7 @@ struct npc_opinion " " << favors.size(); for (int i = 0; i < favors.size(); i++) ret << " " << int(favors[i].type) << " " << favors[i].value << " " << - favors[i].item_id << " " << favors[i].skill_id; + favors[i].item_id << " " << favors[i].skill->id(); return ret.str(); } @@ -236,7 +236,7 @@ struct npc_opinion info >> tmptype >> tmpfavor.value >> tmpitem >> tmpskill; tmpfavor.type = npc_favor_type(tmptype); tmpfavor.item_id = itype_id(tmpitem); - tmpfavor.skill_id = skill(tmpskill); + tmpfavor.skill = Skill::skill(tmpskill); favors.push_back(tmpfavor); } } diff --git a/npcmove.cpp b/npcmove.cpp index a488356064d35..8d05a7aa81059 100644 --- a/npcmove.cpp +++ b/npcmove.cpp @@ -691,14 +691,14 @@ int npc::confident_range(int index) // Here we're using median values for deviation, for a around-50% estimate. // See game::fire (ranged.cpp) for where these computations come from - if (sklevel[firing->skill_used] < 5) - deviation += 3.5 * (5 - sklevel[firing->skill_used]); + if (skillLevel(firing->skill_used) < 5) + deviation += 3.5 * (5 - skillLevel(firing->skill_used).level()); else - deviation -= 2.5 * (sklevel[firing->skill_used] - 5); + deviation -= 2.5 * (skillLevel(firing->skill_used).level() - 5); if (sklevel[sk_gun] < 3) - deviation += 1.5 * (3 - sklevel[sk_gun]); + deviation += 1.5 * (3 - skillLevel(Skill::skill("gun")).level()); else - deviation -= .5 * (sklevel[sk_gun] - 3); + deviation -= .5 * (skillLevel(Skill::skill("gun")).level() - 3); if (per_cur < 8) deviation += 2 * (9 - per_cur); diff --git a/npctalk.cpp b/npctalk.cpp index efc966c90c76d..592938b3983d9 100644 --- a/npctalk.cpp +++ b/npctalk.cpp @@ -1440,9 +1440,9 @@ void talk_function::start_training(game *g, npc *p) style = itype_id(0 - p->chatbin.tempvalue); time = 30000; } else { - sk_used = skill(p->chatbin.tempvalue); - cost = -200 * (1 + g->u.sklevel[sk_used]); - time = 10000 + 5000 * g->u.sklevel[sk_used]; + sk_used = skill(p->chatbin.tempvalue); + cost = -200 * (1 + g->u.skillLevel(Skill::skill(sk_used)).level()); + time = 10000 + 5000 * g->u.skillLevel(Skill::skill(sk_used)).level(); } // Pay for it @@ -1638,7 +1638,7 @@ talk_topic dialogue::opt(talk_topic topic, game *g) if (chosen.trial == TALK_TRIAL_NONE || rng(0, 99) < trial_chance(chosen, alpha, beta)) { if (chosen.trial != TALK_TRIAL_NONE) - alpha->practice(sk_speech, (100 - trial_chance(chosen, alpha, beta)) / 10); + alpha->practice(Skill::skill("speech"), (100 - trial_chance(chosen, alpha, beta)) / 10); (effect.*chosen.effect_success)(g, beta); beta->op_of_u += chosen.opinion_success; if (beta->turned_hostile()) { @@ -1647,7 +1647,7 @@ talk_topic dialogue::opt(talk_topic topic, game *g) } return chosen.success; } else { - alpha->practice(sk_speech, (100 - trial_chance(chosen, alpha, beta)) / 7); + alpha->practice(Skill::skill("speech"), (100 - trial_chance(chosen, alpha, beta)) / 7); (effect.*chosen.effect_failure)(g, beta); beta->op_of_u += chosen.opinion_failure; if (beta->turned_hostile()) { @@ -1894,7 +1894,7 @@ Tab key to switch lists, letters to pick items, Enter to finalize, Esc to quit\n } else newinv.push_back(tmp); } - g->u.practice(sk_barter, practice / 2); + g->u.practice(Skill::skill("barter"), practice / 2); p->inv = newinv; g->u.cash += cash; p->cash -= cash; diff --git a/player.cpp b/player.cpp index baadcdcca91e0..c858dfe6b4596 100644 --- a/player.cpp +++ b/player.cpp @@ -76,6 +76,10 @@ player::player() mutation_category_level[0] = 5; // Weigh us towards no category for a bit for (int i = 1; i < NUM_MUTATION_CATEGORIES; i++) mutation_category_level[i] = 0; + + for (EACH_SKILL) { + skillLevel(*aSkill).level(0); + } } player::player(const player &rhs) @@ -164,6 +168,8 @@ player& player::operator= (const player & rhs) sklearn[i] = rhs.sklearn[i]; } + _skills = rhs._skills; + inv_sorted = rhs.inv_sorted; inv.clear(); @@ -451,7 +457,7 @@ int player::run_cost(int base_cost) int player::swim_speed() { - int ret = 440 + 2 * weight_carried() - 50 * sklevel[sk_swimming]; + int ret = 440 + 2 * weight_carried() - 50 * skillLevel(Skill::skill("swimming")).level(); if (has_trait(PF_WEBBED)) ret -= 60 + str_cur * 5; if (has_trait(PF_TAIL_FIN)) @@ -460,11 +466,11 @@ int player::swim_speed() ret -= 100; if (has_trait(PF_LEG_TENTACLES)) ret -= 60; - ret += (50 - sklevel[sk_swimming] * 2) * abs(encumb(bp_legs)); - ret += (80 - sklevel[sk_swimming] * 3) * abs(encumb(bp_torso)); - if (sklevel[sk_swimming] < 10) { + ret += (50 - skillLevel(Skill::skill("swimming")).level() * 2) * abs(encumb(bp_legs)); + ret += (80 - skillLevel(Skill::skill("swimming")).level() * 3) * abs(encumb(bp_torso)); + if (skillLevel(Skill::skill("swimming")) < 10) { for (int i = 0; i < worn.size(); i++) - ret += (worn[i].volume() * (10 - sklevel[sk_swimming])) / 2; + ret += (worn[i].volume() * (10 - skillLevel(Skill::skill("swimming")).level())) / 2; } ret -= str_cur * 6 + dex_cur * 4; // If (ret > 500), we can not swim; so do not apply the underwater bonus. @@ -520,8 +526,10 @@ void player::load_info(game *g, std::string data) for (int i = 0; i < num_hp_parts; i++) dump >> hp_cur[i] >> hp_max[i]; - for (int i = 0; i < num_skill_types; i++) - dump >> sklevel[i] >> skexercise[i] >> sklearn[i]; + + for (EVERY_SKILL) { + dump >> skillLevel(*aSkill); + } int numstyles, typetmp; dump >> numstyles; @@ -614,8 +622,11 @@ std::string player::save_info() dump << mutation_category_level[i] << " "; for (int i = 0; i < num_hp_parts; i++) dump << hp_cur[i] << " " << hp_max[i] << " "; - for (int i = 0; i < num_skill_types; i++) - dump << int(sklevel[i]) << " " << skexercise[i] << " " << sklearn[i] << " "; + + for (EVERY_SKILL) { + SkillLevel level = skillLevel(*aSkill); + dump << level; + } dump << styles.size() << " "; for (int i = 0; i < styles.size(); i++) @@ -934,18 +945,23 @@ Strength - 4; Dexterity - 4; Intelligence - 4; Dexterity - 4"); line = 2; std::vector skillslist; mvwprintz(w_skills, 0, 11, c_ltgray, "SKILLS"); - for (int i = 1; i < num_skill_types; i++) { + for (EACH_SKILL) { + int i = (*aSkill)->id(); + + SkillLevel level = skillLevel(*aSkill); + + if (i == 0) + continue; + if (sklevel[i] >= 0) { skillslist.push_back(skill(i)); if (line < 9) { - mvwprintz(w_skills, line, 1, sklearn[i] ? c_dkgray : c_ltblue, "%s:", - skill_name(skill(i)).c_str()); - mvwprintz(w_skills, line,19, c_ltblue, "%d%s(%s%d%%%%)", sklevel[i], - (sklevel[i] < 10 ? " " : ""), - (skexercise[i] < 10 && skexercise[i] >= 0 ? " " : ""), - (skexercise[i] < 0 ? 0 : skexercise[i])); + mvwprintz(w_skills, line, 1, skillLevel(*aSkill).isTraining() ? c_dkgray : c_ltblue, "%-17s", + ((*aSkill)->name() + ":").c_str()); + mvwprintz(w_skills, line,19, c_ltblue, "%-2d(%2d%%%%)", level.level(), + (level.exercise() < 0 ? 0 : level.exercise())); line++; - } + } } } wrefresh(w_skills); @@ -1145,7 +1161,7 @@ Running costs +%d movement points", encumb(bp_mouth) * 5); Melee skill -%d; Dodge skill -%d;\n\ Swimming costs +%d movement points;\n\ Melee attacks cost +%d movement points", encumb(bp_torso), encumb(bp_torso), -encumb(bp_torso) * (80 - sklevel[sk_swimming] * 3), encumb(bp_torso) * 20); + encumb(bp_torso) * (80 - skillLevel(Skill::skill("swimming")).level() * 3), encumb(bp_torso) * 20); } else if (line == 4) { mvwprintz(w_encumb, 5, 2, h_ltgray, "Arms"); @@ -1164,7 +1180,7 @@ Dexterity -%d when throwing items", encumb(bp_hands) * 30, encumb(bp_hands)); mvwprintz(w_info, 0, 0, c_magenta, "\ Running costs %s%d movement points; Swimming costs %s%d movement points;\n\ Dodge skill %s%.1f", sign.c_str(), encumb(bp_legs) * 3, - sign.c_str(), encumb(bp_legs) *(50 - sklevel[sk_swimming]), + sign.c_str(), encumb(bp_legs) *(50 - skillLevel(Skill::skill("swimming")).level()), osign.c_str(), double(double(encumb(bp_legs)) / 2)); } else if (line == 7) { mvwprintz(w_encumb, 8, 2, h_ltgray, "Feet"); @@ -1339,43 +1355,48 @@ encumb(bp_feet) * 5); if (min < 0) min = 0; } + + Skill *selectedSkill; + for (int i = min; i < max; i++) { + Skill *aSkill = Skill::skill(skillslist[i]); + SkillLevel level = skillLevel(aSkill); + + bool isLearning = level.isTraining(); + int32_t exercise = level.exercise(); + if (i == line) { - if (skexercise[skillslist[i]] >= 100) - status = sklearn[skillslist[i]] ? h_pink : h_red; + selectedSkill = aSkill; + if (exercise >= 100) + status = isLearning ? h_pink : h_red; else - status = sklearn[skillslist[i]] ? h_ltblue : h_blue; + status = isLearning ? h_ltblue : h_blue; } else { - if (skexercise[skillslist[i]] < 0) - status = sklearn[skillslist[i]] ? c_ltred : c_red; + if (exercise < 0) + status = isLearning ? c_ltred : c_red; else - status = sklearn[skillslist[i]] ? c_ltblue : c_blue; + status = isLearning ? c_ltblue : c_blue; } mvwprintz(w_skills, 2 + i - min, 1, c_ltgray, " "); - if (skexercise[i] >= 100) { + if (exercise >= 100) { mvwprintz(w_skills, 2 + i - min, 1, status, "%s:", - skill_name(skillslist[i]).c_str()); - mvwprintz(w_skills, 2 + i - min,19, status, "%d (%s%d%%%%)", - sklevel[skillslist[i]], - (skexercise[skillslist[i]] < 10 && - skexercise[skillslist[i]] >= 0 ? " " : ""), - (skexercise[skillslist[i]] < 0 ? 0 : - skexercise[skillslist[i]])); + aSkill->name().c_str()); + mvwprintz(w_skills, 2 + i - min,19, status, "%-2d(%2d%%%%)", + level.level(), + (exercise < 0 ? 0 : exercise)); } else { - mvwprintz(w_skills, 2 + i - min, 1, status, "%s:", - skill_name(skillslist[i]).c_str()); - mvwprintz(w_skills, 2 + i - min,19, status, "%d (%s%d%%%%)", - sklevel[skillslist[i]], - (skexercise[skillslist[i]] < 10 && - skexercise[skillslist[i]] >= 0 ? " " : ""), - (skexercise[skillslist[i]] < 0 ? 0 : - skexercise[skillslist[i]])); + mvwprintz(w_skills, 2 + i - min, 1, status, "%-17s", + (aSkill->name() + ":").c_str()); + mvwprintz(w_skills, 2 + i - min,19, status, "%-2d(%2d%%%%)", + level.level(), + (exercise < 0 ? 0 : + exercise)); } } werase(w_info); if (line >= 0 && line < skillslist.size()) mvwprintz(w_info, 0, 0, c_magenta, - skill_description(skillslist[line]).c_str()); + selectedSkill->description().c_str()); wrefresh(w_skills); wrefresh(w_info); switch (input()) { @@ -1388,27 +1409,28 @@ encumb(bp_feet) * 5); line--; break; case '\t': + werase(w_skills); mvwprintz(w_skills, 0, 0, c_ltgray, " SKILLS "); for (int i = 0; i < skillslist.size() && i < 7; i++) { - if (skexercise[skillslist[i]] < 0) + Skill *thisSkill = Skill::skill(i); + SkillLevel thisLevel = skillLevel(thisSkill); + if (thisLevel.exercise() < 0) status = c_ltred; else status = c_ltblue; mvwprintz(w_skills, i + 2, 1, status, "%s:", - skill_name(skillslist[i]).c_str()); - mvwprintz(w_skills, i + 2, 19, status, "%d (%s%d%%%%)", - sklevel[skillslist[i]], - (skexercise[skillslist[i]] < 10 && - skexercise[skillslist[i]] >= 0 ? " " : ""), - (skexercise[skillslist[i]] < 0 ? 0 : - skexercise[skillslist[i]])); + thisSkill->name().c_str()); + mvwprintz(w_skills, i + 2, 19, status, "%d (%2d%%%%)", + thisLevel.level(), + (thisLevel.exercise() < 0 ? 0 : + thisLevel.exercise())); } wrefresh(w_skills); line = 0; curtab = 1; break; case ' ': - sklearn[skillslist[line]] = !sklearn[skillslist[line]]; + skillLevel(selectedSkill).toggleTraining(); break; case 'q': case 'Q': @@ -1919,7 +1941,7 @@ bool player::has_two_arms() bool player::avoid_trap(trap* tr) { - int myroll = dice(3, dex_cur + sklevel[sk_dodge] * 1.5); + int myroll = dice(3, dex_cur + skillLevel(Skill::skill("dodge")).level() * 1.5); int traproll; if (per_cur - encumb(bp_eyes) >= tr->visibility) traproll = dice(3, tr->avoidance); @@ -1936,10 +1958,10 @@ void player::pause(game *g) { moves = 0; if (recoil > 0) { - if (str_cur + 2 * sklevel[sk_gun] >= recoil) + if (str_cur + 2 * skillLevel(Skill::skill("gun")).level() >= recoil) recoil = 0; else { - recoil -= str_cur + 2 * sklevel[sk_gun]; + recoil -= str_cur + 2 * skillLevel(Skill::skill("gun")).level(); recoil = int(recoil / 2); } } @@ -1973,8 +1995,8 @@ int player::throw_range(int index) if (ret < 1) return 1; // Cap at double our strength + skill - if (ret > str_cur * 1.5 + sklevel[sk_throw]) - return str_cur * 1.5 + sklevel[sk_throw]; + if (ret > str_cur * 1.5 + skillLevel(Skill::skill("throw")).level()) + return str_cur * 1.5 + skillLevel(Skill::skill("throw")).level(); return ret; } @@ -2073,7 +2095,7 @@ int player::read_speed(bool real_life) int player::talk_skill() { - int ret = int_cur + per_cur + sklevel[sk_speech] * 3; + int ret = int_cur + per_cur + skillLevel(Skill::skill("speech")).level() * 3; if (has_trait(PF_DEFORMED)) ret -= 4; else if (has_trait(PF_DEFORMED2)) @@ -4288,7 +4310,7 @@ void player::use(game *g, char let) } else if (used->is_gunmod()) { - if (sklevel[sk_gun] == 0) { + if (skillLevel(Skill::skill("gun")) == 0) { g->add_msg("You need to be at least level 1 in the firearms skill before you\ can modify guns."); if (replace_item) @@ -4310,31 +4332,31 @@ void player::use(game *g, char let) return; } it_gun* guntype = dynamic_cast(gun->type); - if (guntype->skill_used == sk_archery || guntype->skill_used == sk_launcher) { + if (guntype->skill_used == Skill::skill("archery") || guntype->skill_used == Skill::skill("launcher")) { g->add_msg("You cannot mod your %s.", gun->tname(g).c_str()); if (replace_item) inv.add_item(copy); return; } - if (guntype->skill_used == sk_pistol && !mod->used_on_pistol) { + if (guntype->skill_used == Skill::skill("pistol") && !mod->used_on_pistol) { g->add_msg("That %s cannot be attached to a handgun.", used->tname(g).c_str()); if (replace_item) inv.add_item(copy); return; - } else if (guntype->skill_used == sk_shotgun && !mod->used_on_shotgun) { + } else if (guntype->skill_used == Skill::skill("shotgun") && !mod->used_on_shotgun) { g->add_msg("That %s cannot be attached to a shotgun.", used->tname(g).c_str()); if (replace_item) inv.add_item(copy); return; - } else if (guntype->skill_used == sk_smg && !mod->used_on_smg) { + } else if (guntype->skill_used == Skill::skill("smg") && !mod->used_on_smg) { g->add_msg("That %s cannot be attached to a submachine gun.", used->tname(g).c_str()); if (replace_item) inv.add_item(copy); return; - } else if (guntype->skill_used == sk_rifle && !mod->used_on_rifle) { + } else if (guntype->skill_used == Skill::skill("rifle") && !mod->used_on_rifle) { g->add_msg("That %s cannot be attached to a rifle.", used->tname(g).c_str()); if (replace_item) @@ -4510,9 +4532,9 @@ int time; //Declare this here so that we can change the time depending on whats g->add_msg("You're illiterate!"); return; } - else if (tmp->req > sklevel[tmp->type]) { + else if (skillLevel(tmp->type) < tmp->req) { g->add_msg("The %s-related jargon flies over your head!", - skill_name(tmp->type).c_str()); + tmp->type->name().c_str()); return; } else if (tmp->intel > int_cur) { g->add_msg("This book is too complex for you to easily understand. It will take longer to read."); @@ -4521,9 +4543,9 @@ int time; //Declare this here so that we can change the time depending on whats moves = 0; return; } - else if (tmp->level <= sklevel[tmp->type] && tmp->fun <= 0 && + else if (skillLevel(tmp->type) >= tmp->level && tmp->fun <= 0 && !query_yn("Your %s skill won't be improved. Read anyway?", - skill_name(tmp->type).c_str())) + tmp->type->name().c_str())) return; // Base read_speed() is 1000 move points (1 minute per tmp->time) @@ -4847,34 +4869,43 @@ bool player::wearing_something_on(body_part bp) return false; } -void player::practice(skill s, int amount) -{ - skill savant = sk_null; - int savant_level = 0, savant_exercise = 0; - if (skexercise[s] < 0) - amount += (amount >= -1 * skexercise[s] ? -1 * skexercise[s] : amount); - if (has_trait(PF_SAVANT)) { -// Find our best skill - for (int i = 1; i < num_skill_types; i++) { - if (sklevel[i] >= savant_level) { - savant = skill(i); - savant_level = sklevel[i]; - savant_exercise = skexercise[i]; - } else if (sklevel[i] == savant_level && skexercise[i] > savant_exercise) { - savant = skill(i); - savant_exercise = skexercise[i]; - } +void player::practice (Skill *s, int amount) { + SkillLevel& level = skillLevel(s); + + if (level.exercise() < 0) { + if (amount >= -level.exercise()) { + amount -= level.exercise(); + } else { + amount += amount; + } } - } - while (sklearn[s] && amount > 0 && xp_pool >= (1 + sklevel[s])) { - amount -= sklevel[s] + 1; - if ((savant == sk_null || savant == s || !one_in(2)) && - rng(0, 100) < comprehension_percent(s)) { - xp_pool -= (1 + sklevel[s]); - skexercise[s]++; + + bool isSavant = has_trait(PF_SAVANT); + + Skill *savantSkill = NULL; + SkillLevel savantSkillLevel = SkillLevel(); + + if (isSavant) { + for (EACH_SKILL) { + if (skillLevel(*aSkill) > savantSkillLevel) { + savantSkill = *aSkill; + savantSkillLevel = skillLevel(*aSkill); + } + } + } + + uint32_t newLevel; + + while (level.isTraining() && amount > 0 && xp_pool >= (1 + level.level())) { + amount -= level.level() + 1; + if ((!isSavant || s == savantSkill || one_in(2)) && rng(0, 100) < level.comprehension(int_cur, has_trait(PF_FASTLEARNER))) { + xp_pool -= (1 + level.level()); + + skillLevel(s).train(newLevel); + } } - } } + void player::assign_activity(activity_type type, int moves, int index) { if (backlog.type == type && backlog.index == index && @@ -5057,3 +5088,11 @@ bool activity_is_suspendable(activity_type type) return false; return true; } + +SkillLevel& player::skillLevel(std::string ident) { + return _skills[Skill::skill(ident)]; +} + +SkillLevel& player::skillLevel(Skill *_skill) { + return _skills[_skill]; +} diff --git a/player.h b/player.h index 51489a9dace48..535d39c5e1849 100644 --- a/player.h +++ b/player.h @@ -13,6 +13,7 @@ #include "mutation.h" #include #include +#include class monster; class game; @@ -30,6 +31,8 @@ struct special_attack }; class player { + std::map _skills; + public: player(); player(const player &rhs); @@ -201,7 +204,7 @@ class player { int resist(body_part bp); // Infection &c resistance bool wearing_something_on(body_part bp); // True if wearing something on bp - void practice(skill s, int amount); // Practice a skill + void practice(Skill *s, int amount); void assign_activity(activity_type type, int moves, int index = -1); void cancel_activity(); @@ -293,7 +296,10 @@ class player { int skexercise[num_skill_types]; int sktrain[num_skill_types]; bool sklearn[num_skill_types]; - + + SkillLevel& skillLevel(Skill* _skill); + SkillLevel& skillLevel(std::string ident); + bool inv_sorted; //std::vector inv; inventory inv; diff --git a/ranged.cpp b/ranged.cpp index 71bc698b291ce..54357a9bae9d2 100644 --- a/ranged.cpp +++ b/ranged.cpp @@ -129,7 +129,7 @@ void game::fire(player &p, int tarx, int tary, std::vector &trajectory, else trange = int(trange * .8); } - if (firing->skill_used == sk_rifle && trange > LONG_RANGE) + if (firing->skill_used == Skill::skill("rifle") && trange > LONG_RANGE) trange = LONG_RANGE + .6 * (trange - LONG_RANGE); std::string message = ""; @@ -141,7 +141,7 @@ void game::fire(player &p, int tarx, int tary, std::vector &trajectory, (mon_at(tarx, tary) == -1 || z[mon_at(tarx, tary)].hp <= 0)) { std::vector new_targets; int mondex; - for (int radius = 1; radius <= 2 + p.sklevel[sk_gun] && new_targets.empty(); + for (int radius = 1; radius <= 2 + p.skillLevel(Skill::skill("gun")).level() && new_targets.empty(); radius++) { for (int diff = 0 - radius; diff <= radius; diff++) { mondex = mon_at(tarx + diff, tary - radius); @@ -172,7 +172,7 @@ void game::fire(player &p, int tarx, int tary, std::vector &trajectory, else trajectory = line_to(p.posx, p.posy, tarx, tary, 0); } else if ((!p.has_trait(PF_TRIGGERHAPPY) || one_in(3)) && - (p.sklevel[sk_gun] >= 7 || one_in(7 - p.sklevel[sk_gun]))) + (p.skillLevel(Skill::skill("gun")) >= 7 || one_in(7 - p.skillLevel(Skill::skill("gun")).level()))) return; // No targets, so return } @@ -363,13 +363,15 @@ void game::throw_item(player &p, int tarx, int tary, item &thrown, int trange = 1.5 * rl_dist(p.posx, p.posy, tarx, tary); // Throwing attempts below "Basic Competency" level are extra-bad - if (p.sklevel[sk_throw] < 3) - deviation += rng(0, 8 - p.sklevel[sk_throw]); + uint32_t skillLevel = p.skillLevel(Skill::skill("throw")).level(); - if (p.sklevel[sk_throw] < 8) - deviation += rng(0, 8 - p.sklevel[sk_throw]); + if (skillLevel < 3) + deviation += rng(0, 8 - skillLevel); + + if (skillLevel < 8) + deviation += rng(0, 8 - skillLevel); else - deviation -= p.sklevel[sk_throw] - 6; + deviation -= skillLevel - 6; deviation += p.throw_dex_mod(); @@ -427,7 +429,7 @@ void game::throw_item(player &p, int tarx, int tary, item &thrown, // OR it's not the monster we were aiming at and we were lucky enough to hit it if (mon_at(tx, ty) != -1 && (!missed || one_in(7 - int(z[mon_at(tx, ty)].type->size)))) { - if (rng(0, 100) < 20 + p.sklevel[sk_throw] * 12 && + if (rng(0, 100) < 20 + skillLevel * 12 && thrown.type->melee_cut > 0) { if (!p.is_npc()) { message += " You cut the "; @@ -454,11 +456,11 @@ void game::throw_item(player &p, int tarx, int tary, item &thrown, if (goodhit < .1 && !z[mon_at(tx, ty)].has_flag(MF_NOHEAD)) { message = "Headshot!"; dam = rng(dam, dam * 3); - p.practice(sk_throw, 5); + p.practice(Skill::skill("throw"), 5); } else if (goodhit < .2) { message = "Critical!"; dam = rng(dam, dam * 2); - p.practice(sk_throw, 2); + p.practice(Skill::skill("throw"), 2); } else if (goodhit < .4) dam = rng(int(dam / 2), int(dam * 1.5)); else if (goodhit < .5) { @@ -709,54 +711,39 @@ void game::hit_monster_with_flags(monster &z, unsigned int effects) int time_to_fire(player &p, it_gun* firing) { int time = 0; - switch (firing->skill_used) { - - case sk_pistol: - if (p.sklevel[sk_pistol] > 6) - time = 10; - else - time = (80 - 10 * p.sklevel[sk_pistol]); - break; - - case sk_shotgun: - if (p.sklevel[sk_shotgun] > 3) - time = 70; - else - time = (150 - 25 * p.sklevel[sk_shotgun]); - break; - - case sk_smg: - if (p.sklevel[sk_smg] > 5) - time = 20; - else - time = (80 - 10 * p.sklevel[sk_smg]); - break; - - case sk_rifle: - if (p.sklevel[sk_rifle] > 8) - time = 30; - else - time = (150 - 15 * p.sklevel[sk_rifle]); - break; - - case sk_archery: - if (p.sklevel[sk_archery] > 8) - time = 20; - else - time = (220 - 25 * p.sklevel[sk_archery]); - break; - - case sk_launcher: - if (p.sklevel[sk_launcher] > 8) - time = 30; - else - time = (200 - 20 * p.sklevel[sk_launcher]); - break; - - default: - debugmsg("Why is shooting %s using %s skill?", (firing->name).c_str(), - skill_name(firing->skill_used).c_str()); - time = 0; + if (firing->skill_used == Skill::skill("pistol")) { + if (p.skillLevel(Skill::skill("pistol")) > 6) + time = 10; + else + time = (80 - 10 * p.skillLevel(Skill::skill("pistol")).level()); + } else if (firing->skill_used == Skill::skill("shotgun")) { + if (p.skillLevel(Skill::skill("shotgun")) > 3) + time = 70; + else + time = (150 - 25 * p.skillLevel(Skill::skill("shotgun")).level()); + } else if (firing->skill_used == Skill::skill("smg")) { + if (p.skillLevel(Skill::skill("smg")) > 5) + time = 20; + else + time = (80 - 10 * p.skillLevel(Skill::skill("smg")).level()); + } else if (firing->skill_used == Skill::skill("rifle")) { + if (p.skillLevel(Skill::skill("rifle")) > 8) + time = 30; + else + time = (150 - 15 * p.skillLevel(Skill::skill("rifle")).level()); + } else if (firing->skill_used == Skill::skill("archery")) { + if (p.skillLevel(Skill::skill("archery")) > 8) + time = 20; + else + time = (220 - 25 * p.skillLevel(Skill::skill("archery")).level()); + } else if (firing->skill_used == Skill::skill("launcher")) { + if (p.skillLevel(Skill::skill("launcher")) > 8) + time = 30; + else + time = (200 - 20 * p.skillLevel(Skill::skill("launcher")).level()); + } else { + debugmsg("Why is shooting %s using %s skill?", (firing->name).c_str(), firing->skill_used->name().c_str()); + time = 0; } return time; @@ -813,7 +800,7 @@ int calculate_range(player &p, int tarx, int tary) trange = int(trange * .8); } - if (firing->skill_used == sk_rifle && trange > LONG_RANGE) + if (firing->skill_used == Skill::skill("rifle") && trange > LONG_RANGE) trange = LONG_RANGE + .6 * (trange - LONG_RANGE); return trange; @@ -826,15 +813,15 @@ double calculate_missed_by(player &p, int trange, item* weapon) // Calculate deviation from intended target (assuming we shoot for the head) double deviation = 0.; // Measured in quarter-degrees // Up to 1.5 degrees for each skill point < 4; up to 1.25 for each point > 4 - if (p.sklevel[firing->skill_used] < 4) - deviation += rng(0, 6 * (4 - p.sklevel[firing->skill_used])); - else if (p.sklevel[firing->skill_used] > 4) - deviation -= rng(0, 5 * (p.sklevel[firing->skill_used] - 4)); + if (p.skillLevel(firing->skill_used) < 4) + deviation += rng(0, 6 * (4 - p.skillLevel(firing->skill_used).level())); + else if (p.skillLevel(firing->skill_used) > 4) + deviation -= rng(0, 5 * (p.skillLevel(firing->skill_used).level() - 4)); - if (p.sklevel[sk_gun] < 3) - deviation += rng(0, 3 * (3 - p.sklevel[sk_gun])); + if (p.skillLevel(Skill::skill("gun")) < 3) + deviation += rng(0, 3 * (3 - p.skillLevel(Skill::skill("gun")).level())); else - deviation -= rng(0, 2 * (p.sklevel[sk_gun] - 3)); + deviation -= rng(0, 2 * (p.skillLevel(Skill::skill("gun")).level() - 3)); deviation += p.ranged_dex_mod(); deviation += p.ranged_per_mod(); @@ -861,7 +848,7 @@ int recoil_add(player &p) // item::recoil() doesn't suport gunmods, so call it on player gun. int ret = p.weapon.recoil(); ret -= rng(p.str_cur / 2, p.str_cur); - ret -= rng(0, p.sklevel[firing->skill_used] / 2); + ret -= rng(0, p.skillLevel(firing->skill_used).level() / 2); if (ret > 0) return ret; return 0; diff --git a/skill.cpp b/skill.cpp index 9382fe38e6776..2a7454f4922ce 100644 --- a/skill.cpp +++ b/skill.cpp @@ -1,249 +1,199 @@ +#include +#include +#include + #include "skill.h" +#include "rng.h" -std::string skill_name(int sk) -{ - switch (sk) { - case sk_null: - return "nothing"; - case sk_dodge: - return "dodge"; - case sk_melee: - return "melee"; - case sk_unarmed: - return "unarmed combat"; - case sk_bashing: - return "bashing weapons"; - case sk_cutting: - return "cutting weapons"; - case sk_stabbing: - return "piercing weapons"; - case sk_throw: - return "throwing"; - case sk_gun: - return "firearms"; - case sk_pistol: - return "handguns"; - case sk_shotgun: - return "shotguns"; - case sk_smg: - return "submachine guns"; - case sk_rifle: - return "rifles"; - case sk_archery: - return "archery"; - case sk_launcher: - return "grenade launcher"; - case sk_computer: - return "computers"; - case sk_mechanics: - return "mechanics"; - case sk_electronics: - return "electronics"; - case sk_cooking: - return "cooking"; - case sk_carpentry: - return "construction"; - case sk_survival: - return "survival"; - case sk_traps: - return "traps"; - case sk_tailor: - return "tailoring"; - case sk_firstaid: - return "first aid"; - case sk_speech: - return "speech"; - case sk_barter: - return "barter"; - case sk_swimming: - return "swimming"; - case sk_driving: - return "driving"; - case num_skill_types: - return "out of bounds"; - } - return "the skill with no name"; +#include "picojson.h" + +Skill::Skill() { + _ident = std::string("null"); + + _name = std::string("nothing"); + _description = std::string("The zen-most skill there is."); } -std::string skill_description(int sk) -{ - switch (sk) { - case sk_null: - return "No skill at all."; - case sk_dodge: - return "\ -Your skill at dodging, whether it be from an attack, a trap, or a natural\n\ -occurrence. It is also used when attempting to fall gracefully, or in other\n\ -acrobatic feats."; - case sk_melee: - return "\ -Your skill at hand-to-hand combat, both with and without a weapon. At low\n\ -levels this merely increases your chance to hit, but at higher levels it also\n\ -increases the damage done significantly."; - case sk_unarmed: - return "\ -Your skill at combat without a weapon. While at low levels, unarmed combat is\n\ -a good way to die quickly, those skilled in it can eventually use throws and\n\ -crushing blows to quickly dispatch enemies."; - case sk_bashing: - return "\ -Your skill at combat with weapons that club or bash your enemies. This\n\ -includes everything from rocks to baseball bats, and even the butt of rifles.\n\ -This increases damage, and at higher levels will improve your chance to hit."; - case sk_cutting: - return "\ -Your skill at combat with weapons that cut or slice your enemies. At first\n\ -this will simply slightly increase accuracy and damage; later on it will\n\ -help you bypass armor and thick hides."; - case sk_stabbing: - return "\ -Your skill at combat that involves piercing weapons. This includes spears,\n\ -which only have a stabbing attack, and things like knives, which can cut or\n\ -pierce. This increases your accuracy and chance of a deadly critical."; - case sk_throw: - return "\ -Your skill at throwing items and getting them to go where you want. Increases\n\ -both accuracy and, at higher levels, range."; - case sk_gun: - return "\ -Your general skill at firearms. This increases your accuracy with any gun,\n\ -but not as much as the skill associated with the gun in question."; - case sk_pistol: - return "\ -Your skill with handguns. These have poor accuracy, but generally are fired\n\ -and reloaded faster than other guns, and are good in close quarters."; - case sk_shotgun: - return "\ -Your skill with shotguns. Shot is easy to hit with, and does massive damage,\n\ -but has short range. Shotguns may also be loaded with slugs, which go further\n\ -and do as much damage, but are not very accurate."; - case sk_smg: - return "\ -Your skill with submachine guns and machine pistols. Halfway between a pistol\n\ -and an assault rifle, these weapons fire and reload quickly, and may fire in\n\ -bursts, but they are not very accurate."; - case sk_rifle: - return "\ -Your skill with rifles, both assault rifles and semi-auto hunting rifles.\n\ -These have terrific range and accuracy, but are very slow to fire and reload,\n\ -and are not very good in close quarters."; - case sk_archery: - return "\ -Your skill with all kinds of bows, from crossbows to handmade long bows.\n\ -These are quiet, but require some amount of strength to use, and are not\n\ -terribly accurate. They can only be deadly in skilled hands."; - case sk_launcher: - return "\ -Your skill with grenade launchers, whether standalone or as a rifle mod.\n\ -These launchers fire a variety of 40mm grenades with different uses,\n\ -but they and their rounds are hard to find."; - case sk_computer: - return "\ -Your skill with computers, both in terms of legitimate use, and hacking. This\n\ -will help you use complex systems, and bypass their security."; - case sk_mechanics: - return "\ -Your skill with repairs to mechanical systems, and the crafting of many items\n\ -that use complex parts, but are not electronics."; - case sk_electronics: - return "\ -Your skill with repairs to electrical systems, and the crafting of many items\n\ -that use electrical parts."; - case sk_cooking: - return "\ -Your skill in combining food ingredients to make other, tastier food items.\n\ -This may also be used in mixing chemicals and other more esoteric tasks."; - case sk_carpentry: - return "\ -Your general knowledge in construction. This is used primarily when building\n\ -terrain, via the * screen."; - case sk_survival: - return "\ -Your skill in wilderness survival. This helps you butcher meat from a corpse\n\ -and craft various basic survival items. High levels may allow you to remove\n\ -poison from tainted meat. Also used for skinning corpses to acquire pelts."; - case sk_traps: - return "\ -Your skill at setting and disarming traps safely and effectively. Note that\n\ -this does not help you detect traps, or avoid their effects if you activate\n\ -them."; - case sk_tailor: - return "\ -Your skill at repairing clothing, and at higher levels, creating clothing\n\ -from basic materials. Generally a sewing kit is needed. Also applies to\n\ -other methods of clothing repair and textile crafting."; - case sk_firstaid: - return "\ -Your skill at emergency medical treatment, such as that from first aid kits\n\ -and bandages. High levels of this skill may help heal more HP. Some drugs\n\ -may be more effective as well."; - case sk_speech: - return "\ -Your skill at talking to people, convincing them of things, lying, and many\n\ -others. Works best in conjunction with a high intelligence."; - case sk_barter: - return "\ -Your skill at getting a good deal when trading with others. Very high levels\n\ -might even see you getting freebies."; - case sk_swimming: - return "\ -Your skill at swimming. This affects speed, your ability to swim while\n\ -wearing clothes or carrying weights, and in-water combat."; - case sk_driving: - return "\ -Your skill at driving. This affects how well you can control a vehicle,\n\ -as well as the penalty of shooting while driving."; - case num_skill_types: - return "out of bounds"; - default: - return "What is this skill I don't even know! BUG!"; - } +Skill::Skill(size_t id, std::string ident, std::string name, std::string description) { + _id = id; + _ident = ident; + + _name = name; + _description = description; } -std::string skill_long_name(skill sk, int level) -{ - switch (sk) { - case sk_null: - return "Nothing"; - case sk_dodge: - if (level == 0) - return "Easily-Hit"; - if (level == 1) - return "huh"; - case sk_melee: - case sk_unarmed: - case sk_bashing: - case sk_cutting: - case sk_stabbing: - case sk_throw: - case sk_gun: - case sk_pistol: - case sk_shotgun: - case sk_smg: - case sk_rifle: - case sk_archery: - case sk_launcher: - case sk_mechanics: - case sk_electronics: - case sk_cooking: - case sk_tailor: - case sk_carpentry: - case sk_firstaid: - case sk_speech: - case sk_barter: - case sk_computer: - case sk_survival: - case sk_traps: - case sk_swimming: - case sk_driving: - return "huh"; - } - return "huh"; +std::vector Skill::skills(Skill::loadSkills()); + +std::vector Skill::loadSkills() { + std::vector allSkills; + + picojson::value skillsRaw; + + std::ifstream skillsFile; + + skillsFile.open("data/raw/skills.json"); + + skillsFile >> skillsRaw; + + if (skillsRaw.is()) { + const picojson::array& skills = skillsRaw.get(); + for (picojson::array::const_iterator aSkill = skills.begin(); aSkill != skills.end(); ++aSkill) { + const picojson::array& fields = aSkill->get(); + picojson::array::const_iterator aField = fields.begin(); + + std::string ident, name, description; + + ident = aField++->get(); + name = aField++->get(); + description = aField++->get(); + + Skill *newSkill = new Skill(allSkills.size(), ident, name, description); + allSkills.push_back(newSkill); + } + } else { + std::cout << skillsRaw << std::endl; + exit(1); + } + + return allSkills; +} + +size_t Skill::skill_id(std::string ident) { + for (EACH_SKILL) { + if ((*aSkill)->_ident == ident) { + return (*aSkill)->_id; + } + } +} + +Skill* Skill::skill(std::string ident) { + size_t skillID = Skill::skill_id(ident); + + return Skill::skill(skillID); +} + +Skill* Skill::skill(size_t id) { + return Skill::skills[id]; +} + +size_t Skill::skill_count() { + return Skill::skills.size(); +} + + +SkillLevel::SkillLevel(uint32_t level, int32_t exercise, bool isTraining) { + _level = level; + _exercise = exercise; + _isTraining = isTraining; +} + +SkillLevel::SkillLevel(uint32_t minLevel, uint32_t maxLevel, int32_t minExercise, int32_t maxExercise, bool isTraining) { + _level = rng(minLevel, maxLevel); + _exercise = rng(minExercise, maxExercise); + _isTraining = isTraining; +} + +uint32_t SkillLevel::comprehension(uint32_t intellect, bool fastLearner) { + if (intellect == 0) + return 0; + + uint32_t base_comprehension; + + if (intellect <= 8) { + base_comprehension = intellect * 10; + } else { + base_comprehension = 80 + (intellect - 8) * 8; + } + + if (fastLearner) { + base_comprehension = base_comprehension / 2 * 3; + } + + uint32_t skill_penalty; + + if (_level <= intellect / 2) { + skill_penalty = 0; + } else if (_level <= intellect) { + skill_penalty = _level; + } else { + skill_penalty = _level * 2; + } + + if (skill_penalty >= base_comprehension) { + return 1; + } else { + return base_comprehension - skill_penalty; + } +} + +int32_t SkillLevel::train(uint32_t &level) { + ++_exercise; + + if (_exercise == 100) { + _exercise = 0; + ++_level; + } + + level = _level; + + return _exercise; +} + +int32_t SkillLevel::rust(uint32_t &level) { + --_exercise; + + if (_exercise == 100) { + _exercise = 0; + --_level; + } + + level = _level; + + return _exercise; +} + +int32_t SkillLevel::readBook(uint32_t minimumGain, uint32_t maximumGain, uint32_t maximumLevel) { + uint32_t gain = rng(minimumGain, maximumGain); + + uint32_t level; + + for (uint32_t i = 0; i < gain; ++i) { + train(level); + + if (level >= maximumLevel) + break; + } + + return _exercise; } -double price_adjustment(int barter_skill) -{ +std::istream& operator>>(std::istream& is, SkillLevel& obj) { + uint32_t level; int32_t exercise; bool isTraining; + + is >> level >> exercise >> isTraining; + + obj = SkillLevel(level, exercise, isTraining); + + return is; +} + +std::ostream& operator<<(std::ostream& os, const SkillLevel& obj) { + os << obj.level() << " " << obj.exercise() << " " << obj.isTraining() << " "; + + return os; +} + + +std::string skill_name(int sk) { + return Skill::skill(sk)->name(); +} + +std::string skill_description(int sk) { + return Skill::skill(sk)->description(); +} + +double price_adjustment(int barter_skill) { switch (barter_skill) { case 0: return 1.5; case 1: return 1.4; diff --git a/skill.h b/skill.h index bb84f1f8bf04a..8ffd9fe9e472d 100644 --- a/skill.h +++ b/skill.h @@ -2,6 +2,9 @@ #define _SKILL_H_ #include +#include +#include + enum skill { sk_null = 0, @@ -21,8 +24,89 @@ enum skill { num_skill_types // MUST be last! }; +#define EVERY_SKILL std::vector::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill +#define EACH_SKILL std::vector::iterator aSkill = Skill::skills.begin()++; aSkill != Skill::skills.end(); ++aSkill + +class Skill { + size_t _id; + std::string _ident; + + std::string _name; + std::string _description; + + static size_t skill_id(std::string ident); + + public: + static std::vector skills; + static std::vector loadSkills(); + static Skill* skill(std::string ident); + static Skill* skill(size_t id); + + static size_t skill_count(); + + Skill(); + Skill(size_t id, std::string ident, std::string name, std::string description); + + //DEBUG + size_t id() { return _id; } + + std::string ident() { return _ident; } + std::string name() { return _name; } + std::string description() { return _description; } + + bool operator==(const Skill& b) const { return this->_ident == b._ident; } + bool operator< (const Skill& b) const { return this->_ident < b._ident; } // Only here for the benefit of std::map + + bool operator!=(const Skill& b) const { return !(*this == b); } +}; + +class SkillLevel { + uint32_t _level; + int32_t _exercise; + bool _isTraining; + + public: + SkillLevel(uint32_t level = 0, int32_t exercise = 0, bool isTraining = true); + SkillLevel(uint32_t minLevel, uint32_t maxLevel, int32_t minExercise, int32_t maxExercise, bool isTraining = true); + + bool isTraining() const { return _isTraining; } + bool toggleTraining() { _isTraining = !_isTraining; return _isTraining; } + + uint32_t level() const { return _level; } + uint32_t level(uint32_t level) { _level = level; return level; } + + int32_t exercise() const { return _exercise; } + + uint32_t comprehension(uint32_t intellect, bool fastLearner = false); + + int32_t train(uint32_t &level); + int32_t rust(uint32_t &level); + + int32_t readBook(uint32_t minimumGain, uint32_t maximumGain, uint32_t maximumLevel = 0xFFFFFFFF); + + bool operator==(const SkillLevel& b) const { return this->_level == b._level && this->_exercise == b._exercise; } + bool operator< (const SkillLevel& b) const { return this->_level < b._level || (this->_level == b._level && this->_exercise < b._exercise); } + bool operator> (const SkillLevel& b) const { return this->_level > b._level || (this->_level == b._level && this->_exercise > b._exercise); } + + bool operator==(const uint32_t& b) const { return this->_level == b; } + bool operator< (const uint32_t& b) const { return this->_level < b; } + bool operator> (const uint32_t& b) const { return this->_level > b; } + + bool operator!=(const SkillLevel& b) const { return !(*this == b); } + bool operator<=(const SkillLevel& b) const { return !(*this > b); } + bool operator>=(const SkillLevel& b) const { return !(*this < b); } + + bool operator!=(const uint32_t& b) const { return !(*this == b); } + bool operator<=(const uint32_t& b) const { return !(*this > b); } + bool operator>=(const uint32_t& b) const { return !(*this < b); } +}; + +std::istream& operator>>(std::istream& is, SkillLevel& obj); +std::ostream& operator<<(std::ostream& os, const SkillLevel& obj); + std::string skill_name(int); std::string skill_description(int); -std::string skill_long_name(skill sk, int level); + double price_adjustment(int); + #endif diff --git a/trapfunc.cpp b/trapfunc.cpp index fa8aa062c4581..8575b1426b97c 100644 --- a/trapfunc.cpp +++ b/trapfunc.cpp @@ -477,12 +477,12 @@ void trapfunc::sinkhole(game *g, int x, int y) g->add_msg("You step into a sinkhole, and start to sink down!"); if (g->u.has_amount(itm_rope_30, 1) && query_yn("Throw your rope to try to catch soemthing?")) { - int throwroll = rng(g->u.sklevel[sk_throw], - g->u.sklevel[sk_throw] + g->u.str_cur + g->u.dex_cur); + int throwroll = rng(g->u.skillLevel(Skill::skill("throw")).level(), + g->u.skillLevel(Skill::skill("throw")).level() + g->u.str_cur + g->u.dex_cur); if (throwroll >= 12) { g->add_msg("The rope catches something!"); - if (rng(g->u.sklevel[sk_unarmed], - g->u.sklevel[sk_unarmed] + g->u.str_cur) > 6) { + if (rng(g->u.skillLevel(Skill::skill("unarmed")).level(), + g->u.skillLevel(Skill::skill("unarmed")).level() + g->u.str_cur) > 6) { // Determine safe places for the character to get pulled to std::vector safe; for (int i = g->u.posx - 1; i <= g->u.posx + 1; i++) { diff --git a/tutorial.cpp b/tutorial.cpp index 40d88e0480199..57885a855f67b 100644 --- a/tutorial.cpp +++ b/tutorial.cpp @@ -31,8 +31,8 @@ bool tutorial_game::init(game *g) g->cur_om.make_tutorial(); g->u.toggle_trait(PF_QUICK); g->u.inv.push_back(item(g->itypes[itm_lighter], 0, 'e')); - g->u.sklevel[sk_gun] = 5; - g->u.sklevel[sk_melee] = 5; + g->u.skillLevel(Skill::skill("gun")).level(5); + g->u.skillLevel(Skill::skill("melee")).level(5); // Init the starting map at g location. for (int i = 0; i <= MAPSIZE; i += 2) { for (int j = 0; j <= MAPSIZE; j += 2) { diff --git a/veh_interact.cpp b/veh_interact.cpp index 46880f8a3de77..f3c65e256673e 100644 --- a/veh_interact.cpp +++ b/veh_interact.cpp @@ -151,7 +151,7 @@ int veh_interact::cant_do (char mode) return cpart < 0? 1 : (parts_here.size() < 2 && !veh->can_unmount(cpart)? 2 : (!has_wrench || !has_hacksaw? 3 : - (g->u.sklevel[sk_mechanics] < 2 ? 4 : 0))); + (g->u.skillLevel(Skill::skill("mechanics")) < 2 ? 4 : 0))); default: return -1; } @@ -197,7 +197,7 @@ void veh_interact::do_install(int reason) display_list (pos); itype_id itm = vpart_list[sel_part].item; bool has_comps = crafting_inv.has_amount(itm, 1); - bool has_skill = g->u.sklevel[sk_mechanics] >= vpart_list[sel_part].difficulty; + bool has_skill = g->u.skillLevel(Skill::skill("mechanics")) >= vpart_list[sel_part].difficulty; werase (w_msg); int slen = g->itypes[itm]->name.length(); mvwprintz(w_msg, 0, 1, c_ltgray, "Needs %s and level %d skill in mechanics.", @@ -205,7 +205,7 @@ void veh_interact::do_install(int reason) mvwprintz(w_msg, 0, 7, has_comps? c_ltgreen : c_red, g->itypes[itm]->name.c_str()); mvwprintz(w_msg, 0, 18+slen, has_skill? c_ltgreen : c_red, "%d", vpart_list[sel_part].difficulty); bool eng = vpart_list[sel_part].flags & mfb (vpf_engine); - bool has_skill2 = !eng || (g->u.sklevel[sk_mechanics] >= dif_eng); + bool has_skill2 = !eng || (g->u.skillLevel(Skill::skill("mechanics")) >= dif_eng); if (engines && eng) // already has engine { mvwprintz(w_msg, 1, 1, c_ltgray, @@ -277,7 +277,7 @@ void veh_interact::do_repair(int reason) werase (w_msg); bool has_comps = true; int dif = veh->part_info(sel_part).difficulty + (veh->parts[sel_part].hp <= 0? 0 : 2); - bool has_skill = dif <= g->u.sklevel[sk_mechanics]; + bool has_skill = g->u.skillLevel(Skill::skill("mechanics")).level() >= dif; mvwprintz(w_msg, 0, 1, c_ltgray, "You need level %d skill in mechanics.", dif); mvwprintz(w_msg, 0, 16, has_skill? c_ltgreen : c_red, "%d", dif); if (veh->parts[sel_part].hp <= 0) @@ -620,7 +620,7 @@ void veh_interact::display_list (int pos) int y = i - page * page_size; itype_id itm = vpart_list[can_mount[i]].item; bool has_comps = crafting_inv.has_amount(itm, 1); - bool has_skill = g->u.sklevel[sk_mechanics] >= vpart_list[can_mount[i]].difficulty; + bool has_skill = g->u.skillLevel(Skill::skill("mechanics")) >= vpart_list[can_mount[i]].difficulty; nc_color col = has_comps && has_skill? c_white : c_dkgray; mvwprintz(w_list, y, 3, pos == i? hilite (col) : col, vpart_list[can_mount[i]].name); mvwputch (w_list, y, 1, @@ -663,9 +663,9 @@ void complete_vehicle (game *g) tools.push_back(component(itm_welder, welder_charges)); tools.push_back(component(itm_toolset, welder_charges/5)); consume_tools(g, tools); - g->add_msg ("You install a %s into the %s.", + g->add_msg ("You install a %s into the %s.", vpart_list[part].name, veh->name.c_str()); - g->u.practice (sk_mechanics, vpart_list[part].difficulty * 5 + 20); + g->u.practice (Skill::skill("mechanics"), vpart_list[part].difficulty * 5 + 20); break; case 'r': if (veh->parts[part].hp <= 0) @@ -682,14 +682,14 @@ void complete_vehicle (game *g) tools.push_back(component(itm_toolset, welder_charges/5)); consume_tools(g, tools); veh->parts[part].hp = veh->part_info(part).durability; - g->add_msg ("You repair the %s's %s.", + g->add_msg ("You repair the %s's %s.", veh->name.c_str(), veh->part_info(part).name); - g->u.practice (sk_mechanics, (vpart_list[part].difficulty + dd) * 5 + 20); + g->u.practice (Skill::skill("mechanics"), (vpart_list[part].difficulty + dd) * 5 + 20); break; case 'f': if (!g->pl_refill_vehicle(*veh, part, true)) debugmsg ("complete_vehicle refill broken"); - g->pl_refill_vehicle(*veh, part); + g->pl_refill_vehicle(*veh, part); break; case 'o': for (int i = 0; i < veh->parts[part].items.size(); i++) @@ -711,10 +711,9 @@ void complete_vehicle (game *g) } if (!broken) g->m.add_item (g->u.posx, g->u.posy, g->itypes[itm], g->turn); - g->u.practice (sk_mechanics, 2 * 5 + 20); + g->u.practice (Skill::skill("mechanics"), 2 * 5 + 20); break; default:; - } } diff --git a/vehicle.cpp b/vehicle.cpp index e88a3b872955e..461a3d8f86d8c 100644 --- a/vehicle.cpp +++ b/vehicle.cpp @@ -1824,8 +1824,8 @@ bool vehicle::fire_turret_internal (int p, it_gun &gun, it_ammo &ammo, int charg g->add_msg("The %s fires its %s!", name.c_str(), part_info(p).name); player tmp; tmp.name = std::string("The ") + part_info(p).name; - tmp.sklevel[gun.skill_used] = 1; - tmp.sklevel[sk_gun] = 0; + tmp.skillLevel(gun.skill_used).level(1); + tmp.skillLevel(Skill::skill("gun")).level(0); tmp.recoil = abs(velocity) / 100 / 4; tmp.posx = x; tmp.posy = y;