From c3b1916e038b5063eed1edc9873aec170ea823ff Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sat, 12 Jan 2013 18:01:42 +0100 Subject: [PATCH 01/25] Loadable skills: Step one: Basic framework: The subtitle --- data/SKILLS | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++ skill.cpp | 73 +++++++++++++++++++++++++ skill.h | 24 ++++++++ 3 files changed, 251 insertions(+) create mode 100644 data/SKILLS diff --git a/data/SKILLS b/data/SKILLS new file mode 100644 index 0000000000000..a4b9242969012 --- /dev/null +++ b/data/SKILLS @@ -0,0 +1,154 @@ +null +null +The skill of true Zen. + +dodge +dodge +Your skill at dodging, whether it be from an attack, a trap, or a natural +occurrence. It is also used when attempting to fall gracefully, or in other +acrobatic feats. + +melee +melee +Your skill at hand-to-hand combat, both with and without a weapon. At low +levels this merely increases your chance to hit, but at higher levels it also +increases the damage done significantly. + +unarmed +unarmed combat +Your skill at combat without a weapon. While at low levels, unarmed combat is +a good way to die quickly, those skilled in it can eventually use throws and +crushing blows to quickly dispatch enemies. + +bashing +bashing weapons +Your skill at combat with weapons that club or bash your enemies. This +includes everything from rocks to baseball bats, and even the butt of rifles. +This 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 +this will simply slightly increase accuracy and damage; later on it will +help you bypass armor and thick hides. + +stabbing +piercing weapons +Your skill at combat that involves piercing weapons. This includes spears, +which only have a stabbing attack, and things like knives, which can cut or +pierce. 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 +both accuracy and, at higher levels, range. + +gun +firearms +Your general skill at firearms. This increases your accuracy with any gun, +but 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 +and 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, +but has short range. Shotguns may also be loaded with slugs, which go further +and do as much damage, but are not very accurate. + +smg +submachine guns +Your skill with submachine guns and machine pistols. Halfway between a pistol +and an assault rifle, these weapons fire and reload quickly, and may fire in +bursts, but they are not very accurate. + +rifle +rifles +Your skill with rifles, both assault rifles and semi-auto hunting rifles. +These have terrific range and accuracy, but are very slow to fire and reload, +and are not very good in close quarters. + +archery +archery +Your skill with all kinds of bows, from crossbows to handmade long bows. +These are quiet, but require some amount of strength to use, and are not +terribly accurate. They can only be deadly in skilled hands. + +launcher +grenade launcher +Your skill with grenade launchers, whether standalone or as a rifle mod. +These launchers fire a variety of 40mm grenades with different uses, +but they and their rounds are hard to find. + +computer +computers +Your skill with computers, both in terms of legitimate use, and hacking. This +will help you use complex systems, and bypass their security. + +mechanics +mechanics +Your skill with repairs to mechanical systems, and the crafting of many items +that use complex parts, but are not electronics. + +electronics +electronics +Your skill with repairs to electrical systems, and the crafting of many items +that use electrical parts. + +cooking +cooking +Your skill in combining food ingredients to make other, tastier food items. +This 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 +terrain, via the * screen. + +survival +survival +Your skill in wilderness survival. This helps you butcher meat from a corpse +and craft various basic survival items. High levels may allow you to remove +poison 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 +this does not help you detect traps, or avoid their effects if you activate +them. + +tailor +tailoring +Your skill at repairing clothing, and at higher levels, creating clothing +from basic materials. Generally a sewing kit is needed. Also applies to +other methods of clothing repair and textile crafting. + +firstaid +first aid +Your skill at emergency medical treatment, such as that from first aid kits +and bandages. High levels of this skill may help heal more HP. Some drugs +may be more effective as well. + +speech +speech +Your skill at talking to people, convincing them of things, lying, and many +others. Works best in conjunction with a high intelligence. + +barter +barter +Your skill at getting a good deal when trading with others. Very high levels +might even see you getting freebies. + +swimming +swimming +Your skill at swimming. This affects speed, your ability to swim while +wearing clothes or carrying weights, and in-water combat. + +driving +driving +Your skill at driving. This affects how well you can control a vehicle, +as well as the penalty of shooting while driving. + diff --git a/skill.cpp b/skill.cpp index 9382fe38e6776..247720ed1c4b4 100644 --- a/skill.cpp +++ b/skill.cpp @@ -1,5 +1,78 @@ +#include +#include +#include + #include "skill.h" +Skill::Skill() { + _ident = std::string("null"); + + _name = std::string("nothing"); + _description = std::string("The zen-most skill there is."); +} + +Skill::Skill(size_t id, std::string ident, std::string name, std::string description) { + _id = id; + _ident = ident; + + _name = name; + _description = description; +} + +std::vector Skill::skills(Skill::loadSkills()); + +std::vector Skill::loadSkills() { + std::vector allSkills; + + std::ifstream skills_file; + + skills_file.open("data/SKILLS"); + + while (!skills_file.eof()) { + std::string ident, name; + std::ostringstream description; + + getline(skills_file, ident); + getline(skills_file, name); + + std::string tmp; + + while (1) { + getline(skills_file, tmp); + + if (tmp == "") { + description << '\b'; + + Skill aSkill(allSkills.size(), ident, name, description.str()); + allSkills.push_back(aSkill); + break; + } else { + description << tmp << '\n'; + } + } + } + + return allSkills; +} + +size_t Skill::skill_id(std::string ident) { + for (std::vector::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill) { + 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]; +} + std::string skill_name(int sk) { switch (sk) { diff --git a/skill.h b/skill.h index bb84f1f8bf04a..7adeff8c14a16 100644 --- a/skill.h +++ b/skill.h @@ -2,6 +2,7 @@ #define _SKILL_H_ #include +#include enum skill { sk_null = 0, @@ -21,8 +22,31 @@ enum skill { num_skill_types // MUST be last! }; +class Skill { + size_t _id; + std::string _ident; + + std::string _name; + std::string _description; + + static Skill skill(size_t id); + static size_t skill_id(std::string ident); + + public: + static std::vector skills; + static std::vector loadSkills(); + static Skill skill(std::string ident); + + Skill(); + Skill(size_t id, std::string ident, std::string name, std::string description); + + std::string name() { return _name; }; + std::string description() { return _description; }; +}; + std::string skill_name(int); std::string skill_description(int); std::string skill_long_name(skill sk, int level); double price_adjustment(int); + #endif From 929df3cf80de992312203c648e67a60b79c46a94 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sat, 12 Jan 2013 18:14:37 +0100 Subject: [PATCH 02/25] Loadable skills: Part Two: The kills. --- skill.cpp | 245 ++---------------------------------------------------- skill.h | 4 +- 2 files changed, 7 insertions(+), 242 deletions(-) diff --git a/skill.cpp b/skill.cpp index 247720ed1c4b4..99b6685b759c3 100644 --- a/skill.cpp +++ b/skill.cpp @@ -73,250 +73,15 @@ Skill Skill::skill(size_t id) { return Skill::skills[id]; } -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"; -} - -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!"; - } +std::string skill_name(int sk) { + return Skill::skill(sk).name(); } -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::string skill_description(int sk) { + return Skill::skill(sk).description(); } - -double price_adjustment(int barter_skill) -{ +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 7adeff8c14a16..c5183b6886062 100644 --- a/skill.h +++ b/skill.h @@ -29,13 +29,13 @@ class Skill { std::string _name; std::string _description; - static Skill skill(size_t id); 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); Skill(); Skill(size_t id, std::string ident, std::string name, std::string description); @@ -46,7 +46,7 @@ class Skill { std::string skill_name(int); std::string skill_description(int); -std::string skill_long_name(skill sk, int level); + double price_adjustment(int); #endif From a6f7e307eaa5d702aea2404e6b9edd84e3188b61 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sat, 12 Jan 2013 18:40:02 +0100 Subject: [PATCH 03/25] Loadable skills: Part three: skill_count() --- skill.cpp | 4 ++++ skill.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/skill.cpp b/skill.cpp index 99b6685b759c3..238032e8bab68 100644 --- a/skill.cpp +++ b/skill.cpp @@ -73,6 +73,10 @@ Skill Skill::skill(size_t id) { return Skill::skills[id]; } +size_t Skill::skill_count() { + return Skill::skills.size(); +} + std::string skill_name(int sk) { return Skill::skill(sk).name(); } diff --git a/skill.h b/skill.h index c5183b6886062..2f5dd73d371d4 100644 --- a/skill.h +++ b/skill.h @@ -37,6 +37,8 @@ class Skill { 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); From f6e605a8edb85257272913c8bef9bcd57a5c8760 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 12:27:51 +0100 Subject: [PATCH 04/25] Defines, operators, accessors. --- skill.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++- skill.h | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/skill.cpp b/skill.cpp index 238032e8bab68..4aa3088f206d1 100644 --- a/skill.cpp +++ b/skill.cpp @@ -3,6 +3,7 @@ #include #include "skill.h" +#include "rng.h" Skill::Skill() { _ident = std::string("null"); @@ -56,7 +57,7 @@ std::vector Skill::loadSkills() { } size_t Skill::skill_id(std::string ident) { - for (std::vector::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill) { + for (EACH_SKILL) { if (aSkill->_ident == ident) { return aSkill->_id; } @@ -77,6 +78,47 @@ 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; +} + +int32_t SkillLevel::train(uint32_t amount, uint32_t &level) { + _exercise += amount; + + if (_exercise >= 100) { + _exercise -= 100; + _exercise /= 2; + ++_level; + } + + level = _level; + + return _exercise; +} + +int32_t SkillLevel::rust(uint32_t &level) { + --_exercise; + + if (_exercise == 100) { + _exercise = 0; + --_level; + } + + level = _level; + + return _exercise; +} + + std::string skill_name(int sk) { return Skill::skill(sk).name(); } diff --git a/skill.h b/skill.h index 2f5dd73d371d4..f18cdc69abe7d 100644 --- a/skill.h +++ b/skill.h @@ -22,6 +22,8 @@ enum skill { num_skill_types // MUST be last! }; +#define EACH_SKILL std::vector::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill + class Skill { size_t _id; std::string _ident; @@ -42,8 +44,46 @@ class Skill { Skill(); Skill(size_t id, std::string ident, std::string name, std::string description); - std::string name() { return _name; }; - std::string description() { return _description; }; + 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 +}; + +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() { return _isTraining; } + bool toggleTraining() { _isTraining = !_isTraining; return _isTraining; } + + uint32_t level() { return _level; } + uint32_t level(uint32_t level) { _level = level; return level; } + + int32_t train(uint32_t amount, uint32_t &level); + int32_t rust(uint32_t &level); + + bool operator==(const SkillLevel& b) const { return this->_level == b._level; } + bool operator< (const SkillLevel& b) const { return this->_level < b._level; } + bool operator> (const SkillLevel& b) const { return this->_level > b._level; } + + 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::string skill_name(int); From 211064deb5aa4460042c008d9cbc42c684026c02 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 12:28:19 +0100 Subject: [PATCH 05/25] New Skill array. --- player.cpp | 6 ++++++ player.h | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/player.cpp b/player.cpp index 56881c255470c..82a4f3b29d840 100644 --- a/player.cpp +++ b/player.cpp @@ -162,6 +162,8 @@ player& player::operator= (const player & rhs) sklearn[i] = rhs.sklearn[i]; } + _skills = rhs._skills; + inv_sorted = rhs.inv_sorted; inv.clear(); @@ -5082,3 +5084,7 @@ std::string random_last_name() fin.close(); return lastname; } + +SkillLevel& player::skillLevel(std::string ident) { + return _skills[Skill::skill(ident)]; +} diff --git a/player.h b/player.h index 56de61b449ad1..e29319f45cd1f 100644 --- a/player.h +++ b/player.h @@ -13,6 +13,7 @@ #include "mutation.h" #include #include +#include class monster; class game; @@ -36,6 +37,8 @@ std::string random_first_name(bool male); std::string random_last_name(); class player { + std::map _skills; + public: player(); player(const player &rhs); @@ -298,7 +301,9 @@ class player { int skexercise[num_skill_types]; int sktrain[num_skill_types]; bool sklearn[num_skill_types]; - + + SkillLevel& skillLevel(std::string ident); + bool inv_sorted; //std::vector inv; inventory inv; From 400e63611d9f3101df48a100044fb077c926564f Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 13:07:48 +0100 Subject: [PATCH 06/25] SkillLevel::comprehension() --- skill.cpp | 42 +++++++++++++++++++++++++++++++++++++----- skill.h | 4 +++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/skill.cpp b/skill.cpp index 4aa3088f206d1..c1f95e4449e2e 100644 --- a/skill.cpp +++ b/skill.cpp @@ -91,12 +91,44 @@ SkillLevel::SkillLevel(uint32_t minLevel, uint32_t maxLevel, int32_t minExercise _isTraining = isTraining; } -int32_t SkillLevel::train(uint32_t amount, uint32_t &level) { - _exercise += amount; +uint32_t SkillLevel::comprehension(uint32_t intellect, bool fastLearner) { + if (intellect == 0) + return 0; - if (_exercise >= 100) { - _exercise -= 100; - _exercise /= 2; + uint32_t base_comprehension; + + if (intellect <= 8) { + base_comprehension = intellect * 5; + } else { + base_comprehension = 40 + (intellect - 8) * 3; + } + + 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; } diff --git a/skill.h b/skill.h index f18cdc69abe7d..14257674767a6 100644 --- a/skill.h +++ b/skill.h @@ -66,7 +66,9 @@ class SkillLevel { uint32_t level() { return _level; } uint32_t level(uint32_t level) { _level = level; return level; } - int32_t train(uint32_t amount, uint32_t &level); + uint32_t comprehension(uint32_t intellect, bool fastLearner = false); + + int32_t train(uint32_t &level); int32_t rust(uint32_t &level); bool operator==(const SkillLevel& b) const { return this->_level == b._level; } From 230fc8e7dbdd76cf0df40c2a1ddf989364bde180 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 13:17:13 +0100 Subject: [PATCH 07/25] Expanded comparators for SkillLevel --- skill.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skill.h b/skill.h index 14257674767a6..56c6a707a56e7 100644 --- a/skill.h +++ b/skill.h @@ -71,9 +71,9 @@ class SkillLevel { int32_t train(uint32_t &level); int32_t rust(uint32_t &level); - bool operator==(const SkillLevel& b) const { return this->_level == b._level; } - bool operator< (const SkillLevel& b) const { return this->_level < b._level; } - bool operator> (const SkillLevel& b) const { return this->_level > b._level; } + 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; } From 3f9b5f23d6360b8ad4c67fbc1354398f69ca38d2 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 15:46:20 +0100 Subject: [PATCH 08/25] Significantly upped skill comprehension to better match old values. --- skill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skill.cpp b/skill.cpp index c1f95e4449e2e..6bb1b4b33897d 100644 --- a/skill.cpp +++ b/skill.cpp @@ -98,9 +98,9 @@ uint32_t SkillLevel::comprehension(uint32_t intellect, bool fastLearner) { uint32_t base_comprehension; if (intellect <= 8) { - base_comprehension = intellect * 5; + base_comprehension = intellect * 10; } else { - base_comprehension = 40 + (intellect - 8) * 3; + base_comprehension = 80 + (intellect - 8) * 8; } if (fastLearner) { From 8f6f3a6177aedb07578ccd0663d7f44c0020d7cf Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 15:46:42 +0100 Subject: [PATCH 09/25] Fixed an appearance of a ghost skill. --- data/SKILLS | 1 - 1 file changed, 1 deletion(-) diff --git a/data/SKILLS b/data/SKILLS index a4b9242969012..4a0004182efef 100644 --- a/data/SKILLS +++ b/data/SKILLS @@ -151,4 +151,3 @@ driving driving Your skill at driving. This affects how well you can control a vehicle, as well as the penalty of shooting while driving. - From 06ae5e8afc3b3f6195c749a2c39d871de56176cf Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 15:48:26 +0100 Subject: [PATCH 10/25] exposed excercise through an accessor --- skill.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/skill.h b/skill.h index 56c6a707a56e7..9c6841712d125 100644 --- a/skill.h +++ b/skill.h @@ -66,6 +66,8 @@ class SkillLevel { uint32_t level() { return _level; } uint32_t level(uint32_t level) { _level = level; return level; } + int32_t exercise() { return _exercise; } + uint32_t comprehension(uint32_t intellect, bool fastLearner = false); int32_t train(uint32_t &level); From 34651948bc45a09a8cf9fb593b02a369b3a7afc6 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 16:18:16 +0100 Subject: [PATCH 11/25] display using new method, save and load --- newcharacter.cpp | 69 +++++++++++++++++++-------------- player.cpp | 99 ++++++++++++++++++++++++++++++------------------ player.h | 1 + skill.cpp | 16 ++++++++ skill.h | 18 +++++++-- 5 files changed, 133 insertions(+), 70 deletions(-) diff --git a/newcharacter.cpp b/newcharacter.cpp index e8264e25df43c..06ad2fe8aecef 100644 --- a/newcharacter.cpp +++ b/newcharacter.cpp @@ -118,9 +118,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; } @@ -375,7 +379,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, "); @@ -705,6 +709,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); @@ -715,56 +720,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), "*"); } } @@ -773,23 +782,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 '<': @@ -936,7 +947,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/player.cpp b/player.cpp index 82a4f3b29d840..2499c2df54656 100644 --- a/player.cpp +++ b/player.cpp @@ -74,6 +74,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) @@ -518,6 +522,11 @@ 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 (EVERY_SKILL) { + dump >> skillLevel(*aSkill); + } + for (int i = 0; i < num_skill_types; i++) dump >> sklevel[i] >> skexercise[i] >> sklearn[i]; @@ -612,8 +621,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++) @@ -932,18 +944,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); @@ -1337,43 +1354,48 @@ encumb(bp_feet) * 5); if (min < 0) min = 0; } + + Skill selectedSkill; + for (int i = min; i < max; i++) { + Skill aSkill = Skill::skill(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()) { @@ -1386,6 +1408,7 @@ 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) @@ -1394,10 +1417,8 @@ encumb(bp_feet) * 5); 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%%%%)", + mvwprintz(w_skills, i + 2, 19, status, "%d (%2d%%%%)", sklevel[skillslist[i]], - (skexercise[skillslist[i]] < 10 && - skexercise[skillslist[i]] >= 0 ? " " : ""), (skexercise[skillslist[i]] < 0 ? 0 : skexercise[skillslist[i]])); } @@ -1406,7 +1427,7 @@ encumb(bp_feet) * 5); curtab = 1; break; case ' ': - sklearn[skillslist[line]] = !sklearn[skillslist[line]]; + skillLevel(selectedSkill).toggleTraining(); break; case 'q': case 'Q': @@ -5088,3 +5109,7 @@ std::string random_last_name() SkillLevel& player::skillLevel(std::string ident) { return _skills[Skill::skill(ident)]; } + +SkillLevel& player::skillLevel(const Skill& _skill) { + return _skills[_skill]; +} diff --git a/player.h b/player.h index e29319f45cd1f..29b4d7f1ce8f2 100644 --- a/player.h +++ b/player.h @@ -302,6 +302,7 @@ class player { int sktrain[num_skill_types]; bool sklearn[num_skill_types]; + SkillLevel& skillLevel(const Skill& _skill); SkillLevel& skillLevel(std::string ident); bool inv_sorted; diff --git a/skill.cpp b/skill.cpp index 6bb1b4b33897d..376ad7cb5c8bc 100644 --- a/skill.cpp +++ b/skill.cpp @@ -150,6 +150,22 @@ int32_t SkillLevel::rust(uint32_t &level) { return _exercise; } +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(); diff --git a/skill.h b/skill.h index 9c6841712d125..f1fe49107b456 100644 --- a/skill.h +++ b/skill.h @@ -3,6 +3,8 @@ #include #include +#include + enum skill { sk_null = 0, @@ -22,7 +24,8 @@ enum skill { num_skill_types // MUST be last! }; -#define EACH_SKILL std::vector::iterator aSkill = Skill::skills.begin(); aSkill != Skill::skills.end(); ++aSkill +#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; @@ -44,6 +47,10 @@ class Skill { 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; } @@ -60,13 +67,13 @@ class SkillLevel { 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() { return _isTraining; } + bool isTraining() const { return _isTraining; } bool toggleTraining() { _isTraining = !_isTraining; return _isTraining; } - uint32_t level() { return _level; } + uint32_t level() const { return _level; } uint32_t level(uint32_t level) { _level = level; return level; } - int32_t exercise() { return _exercise; } + int32_t exercise() const { return _exercise; } uint32_t comprehension(uint32_t intellect, bool fastLearner = false); @@ -90,6 +97,9 @@ class SkillLevel { 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); From 1a26777911890e493798c32a184e65bc4a1bf972 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 16:35:19 +0100 Subject: [PATCH 12/25] final display fixes --- player.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/player.cpp b/player.cpp index 2499c2df54656..44bfdc050aaf3 100644 --- a/player.cpp +++ b/player.cpp @@ -1411,16 +1411,18 @@ encumb(bp_feet) * 5); 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()); + thisSkill.name().c_str()); mvwprintz(w_skills, i + 2, 19, status, "%d (%2d%%%%)", - sklevel[skillslist[i]], - (skexercise[skillslist[i]] < 0 ? 0 : - skexercise[skillslist[i]])); + thisLevel.level(), + (thisLevel.exercise() < 0 ? 0 : + thisLevel.exercise())); } wrefresh(w_skills); line = 0; From 85443e661bdb6618356da29b262a2790615287e8 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 18:50:36 +0100 Subject: [PATCH 13/25] conversion: bionics, books, guns, melee --- bionics.cpp | 19 ++--- computer.cpp | 2 +- construction.cpp | 4 +- game.cpp | 21 ++--- item.cpp | 28 +++---- itype.h | 8 +- itypedef.cpp | 206 +++++++++++++++++++++++------------------------ map.cpp | 13 +-- melee.cpp | 20 ++--- npc.cpp | 2 +- npcmove.cpp | 10 +-- npctalk.cpp | 6 +- player.cpp | 76 +++++++++++------ player.h | 1 + ranged.cpp | 123 +++++++++++++--------------- skill.cpp | 16 ++++ skill.h | 4 + vehicle.cpp | 4 +- 18 files changed, 303 insertions(+), 260 deletions(-) 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..6a861203cd1b2 100644 --- a/computer.cpp +++ b/computer.cpp @@ -162,7 +162,7 @@ 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); + p->practice(Skill::skill("computer"), 5 + Security * 2); int player_roll = p->sklevel[sk_computer]; if (p->int_cur < 8 && one_in(2)) player_roll -= rng(0, 8 - p->int_cur); diff --git a/construction.cpp b/construction.cpp index bbb97b4b32ac7..1b0cc31c61162 100644 --- a/construction.cpp +++ b/construction.cpp @@ -547,9 +547,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/game.cpp b/game.cpp index f42b0e54e0ae5..f1f8bb652ee78 100644 --- a/game.cpp +++ b/game.cpp @@ -816,19 +816,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; @@ -5941,18 +5942,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); } diff --git a/item.cpp b/item.cpp index e4825ccf30aa6..5d2674165f4ef 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 == Skill::skill("null")) 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 (Skill::skill("null") != 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; @@ -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) @@ -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; diff --git a/itype.h b/itype.h index db45b75373772..960c5d14c0491 100644 --- a/itype.h +++ b/itype.h @@ -538,7 +538,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; @@ -556,7 +556,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, @@ -665,7 +665,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 @@ -680,7 +680,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 2b6d360dba3b3..8ecdba10223ea 100644 --- a/itypedef.cpp +++ b/itypedef.cpp @@ -2326,19 +2326,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.", @@ -2347,21 +2347,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); @@ -2369,25 +2369,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); @@ -2395,19 +2395,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.", @@ -2416,25 +2416,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)); @@ -2442,28 +2442,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); @@ -2471,26 +2471,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\ @@ -2500,27 +2500,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)); @@ -2528,21 +2528,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.", @@ -2551,14 +2551,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)); @@ -2566,14 +2566,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." @@ -2581,7 +2581,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." , @@ -2590,20 +2590,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.", @@ -2612,21 +2612,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)); @@ -2634,28 +2634,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)); @@ -2663,14 +2663,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.", @@ -2679,13 +2679,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.", @@ -2694,20 +2694,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.", @@ -2716,21 +2716,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.", @@ -2738,7 +2738,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.", @@ -2747,21 +2747,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.", @@ -2770,19 +2770,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); @@ -2790,21 +2790,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.", @@ -2813,20 +2813,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.", @@ -3068,146 +3068,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, Skill::skill("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, Skill::skill("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, Skill::skill("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, Skill::skill("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, Skill::skill("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, Skill::skill("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." ); @@ -4000,7 +4000,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/map.cpp b/map.cpp index 396dbec8cd8dc..8a1414c770d38 100644 --- a/map.cpp +++ b/map.cpp @@ -2014,6 +2014,9 @@ void map::add_trap(int x, int y, trap_id t) void map::disarm_trap(game *g, int x, 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; @@ -2030,12 +2033,12 @@ void map::disarm_trap(game *g, int x, 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!"); @@ -2045,7 +2048,7 @@ void map::disarm_trap(game *g, int x, 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..5f956cb79e61b 100644 --- a/melee.cpp +++ b/melee.cpp @@ -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/npc.cpp b/npc.cpp index 69d98e191e1be..6244e125711a5 100644 --- a/npc.cpp +++ b/npc.cpp @@ -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/npcmove.cpp b/npcmove.cpp index f3770cf91d24f..c15448854e350 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..b1aab5dd3ce5c 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 diff --git a/player.cpp b/player.cpp index 44bfdc050aaf3..6c4be548b7d60 100644 --- a/player.cpp +++ b/player.cpp @@ -453,7 +453,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)) @@ -462,11 +462,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. @@ -1160,7 +1160,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"); @@ -1179,7 +1179,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"); @@ -1940,7 +1940,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); @@ -1957,10 +1957,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); } } @@ -1994,8 +1994,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; } @@ -2094,7 +2094,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)) @@ -4305,7 +4305,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) @@ -4327,31 +4327,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) @@ -4527,9 +4527,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."); @@ -4538,9 +4538,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) @@ -4865,7 +4865,7 @@ bool player::wearing_something_on(body_part bp) void player::practice(skill s, int amount) { - skill savant = sk_null; + skill savant = sk_null; int savant_level = 0, savant_exercise = 0; if (skexercise[s] < 0) amount += (amount >= -1 * skexercise[s] ? -1 * skexercise[s] : amount); @@ -4891,6 +4891,34 @@ void player::practice(skill s, int amount) } } } + +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; + } + } + + if (has_trait(PF_SAVANT)) { + // … + } + + uint32_t newLevel; + + while (level.isTraining() && amount > 0 && xp_pool >= (1 + level.level())) { + amount -= level.level() + 1; + if (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 && diff --git a/player.h b/player.h index 29b4d7f1ce8f2..9dca78ff18f22 100644 --- a/player.h +++ b/player.h @@ -210,6 +210,7 @@ class player { 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(); diff --git a/ranged.cpp b/ranged.cpp index ac2896fb72ae8..dcdc244b835d9 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 376ad7cb5c8bc..1e297d432b4a5 100644 --- a/skill.cpp +++ b/skill.cpp @@ -150,6 +150,22 @@ int32_t SkillLevel::rust(uint32_t &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; +} + + std::istream& operator>>(std::istream& is, SkillLevel& obj) { uint32_t level; int32_t exercise; bool isTraining; diff --git a/skill.h b/skill.h index f1fe49107b456..2d87319950fbc 100644 --- a/skill.h +++ b/skill.h @@ -56,6 +56,8 @@ class Skill { 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 { @@ -80,6 +82,8 @@ class SkillLevel { 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); } diff --git a/vehicle.cpp b/vehicle.cpp index c65fb4acfa436..ab7ef698cc964 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; From 14a1919f2e6363cf54ee784e8b9e5fade1f8c078 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 19:05:31 +0100 Subject: [PATCH 14/25] traps updated --- trapfunc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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++) { From a7fcaf61f94ef65fd33ea6961cd6638f817d0aa3 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 19:51:48 +0100 Subject: [PATCH 15/25] odds and ends --- computer.cpp | 2 +- construction.cpp | 4 ++-- defense.cpp | 9 +++++---- game.cpp | 41 +++++++++++++++++++++++++---------------- monattack.cpp | 14 +++++++++----- monmove.cpp | 2 +- monster.cpp | 11 ++++++----- tutorial.cpp | 4 ++-- veh_interact.cpp | 23 +++++++++++------------ 9 files changed, 62 insertions(+), 48 deletions(-) diff --git a/computer.cpp b/computer.cpp index 6a861203cd1b2..aa822488d64b8 100644 --- a/computer.cpp +++ b/computer.cpp @@ -163,7 +163,7 @@ bool computer::hack_attempt(player *p, int Security) Security = security; // Set to main system security if no value passed p->practice(Skill::skill("computer"), 5 + Security * 2); - int player_roll = p->sklevel[sk_computer]; + 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 9a9e6cf7b4312..cdaa9013148c0 100644 --- a/construction.cpp +++ b/construction.cpp @@ -276,7 +276,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 @@ void game::construction_menu() bool game::player_can_build(player &p, inventory inv, constructable* con, int level, bool cont) { - if (p.sklevel[sk_carpentry] < con->difficulty) + if (p.skillLevel(Skill::skill("carpentry")) < con->difficulty) return false; if (level < 0) diff --git a/defense.cpp b/defense.cpp index 189ad6bc24533..b15d3971b9e28 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 8e731e637c52e..3707b6a2b8279 100644 --- a/game.cpp +++ b/game.cpp @@ -4085,8 +4085,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()); @@ -4389,9 +4389,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++; @@ -5833,7 +5835,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); } @@ -6016,6 +6018,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; @@ -6023,10 +6029,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 @@ -6039,7 +6045,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 @@ -6372,8 +6378,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.)"); @@ -6401,7 +6408,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); @@ -6410,7 +6417,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) @@ -6555,10 +6562,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); } } @@ -6738,7 +6747,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/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 43f35fa5d2923..72895fb3c2574 100644 --- a/monster.cpp +++ b/monster.cpp @@ -474,15 +474,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/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:; - } } From 93ffc17f3913ebb7b33698f2077e211c5b669317 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 20:30:20 +0100 Subject: [PATCH 16/25] items, melee --- item.cpp | 2 +- iuse.cpp | 50 +++++++++++------------ melee.cpp | 120 +++++++++++++++++++++++++++--------------------------- 3 files changed, 86 insertions(+), 86 deletions(-) diff --git a/item.cpp b/item.cpp index bca4fa68755f2..ebdde288589af 100644 --- a/item.cpp +++ b/item.cpp @@ -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 == NULL || p->skillLevel(Skill::skill("unarmed")) >= style->moves[i].level)) return true; } } diff --git a/iuse.cpp b/iuse.cpp index dcb1308cf7e63..41b976ae31894 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); @@ -1248,7 +1248,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()); @@ -1463,7 +1463,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) { @@ -1943,8 +1943,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; @@ -1970,8 +1970,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; @@ -2021,7 +2021,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) { @@ -2262,9 +2262,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); @@ -2298,9 +2298,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); @@ -2385,7 +2385,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; @@ -2550,7 +2550,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/melee.cpp b/melee.cpp index 5f956cb79e61b..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 " << From 7796b1120413a543d8a409a38e3a77def071c730 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 20:36:03 +0100 Subject: [PATCH 17/25] driving, disarming traps --- map.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/map.cpp b/map.cpp index c98aa56d7f9c5..5b92b5f6047d3 100644 --- a/map.cpp +++ b/map.cpp @@ -296,7 +296,7 @@ bool map::displace_vehicle (game *g, int &x, int &y, int dx, int dy, bool test=f 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); } @@ -487,7 +487,7 @@ void map::vehmove(game *g) vel2/100 - sb_bonus)); } else if (veh->part_with_feature (ppl[ps], vpf_controls) >= 0) { 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()); @@ -2023,8 +2023,10 @@ void map::disarm_trap(game *g, int x, int y) debugmsg("Tried to disarm a trap where there was none (%d %d)", x, y); return; } + uint32_t tSkillLevel = g->u.skillLevel(Skill::skill("traps")).level(); + 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) { From d7b2a59973deb9ff4caf589e8d5eecd45aad8991 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 20:43:00 +0100 Subject: [PATCH 18/25] savant handling --- player.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/player.cpp b/player.cpp index eebb521279d6e..3cd4184352550 100644 --- a/player.cpp +++ b/player.cpp @@ -4903,15 +4903,25 @@ void player::practice (Skill s, int amount) { } } - if (has_trait(PF_SAVANT)) { - // … + bool isSavant = has_trait(PF_SAVANT); + + Skill savantSkill = Skill(); + 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 (rng(0, 100) < level.comprehension(int_cur, has_trait(PF_FASTLEARNER))) { + 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); From 14e7d28f5121efc2d9e0e3ec129f104d6042ca33 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 20:58:52 +0100 Subject: [PATCH 19/25] crafting --- crafting.cpp | 366 +++++++++++++++++++++++++-------------------------- crafting.h | 42 +++--- 2 files changed, 208 insertions(+), 200 deletions(-) diff --git a/crafting.cpp b/crafting.cpp index 300cb4e2079a7..238a2ec327f0f 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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("null"), 0, 5000, true); COMP(itm_duct_tape, 100, NULL); COMP(itm_lawnmower_blade, 1, NULL); COMP(itm_stick, 1, itm_mop, 1, NULL); - RECIPE(itm_spear_wood, CC_WEAPON, sk_null, sk_null, 0, 800, false); + RECIPE(itm_spear_wood, CC_WEAPON, Skill::skill("null"), Skill::skill("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"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("null"), 0, 500, false); COMP(itm_rag, 1, NULL); COMP(itm_bottle_glass, 1, itm_flask_glass, 1, NULL); COMP(itm_whiskey, 7, itm_vodka, 7, itm_rum, 7, itm_tequila, 7, itm_gasoline, 200, NULL); - RECIPE(itm_pipebomb, CC_WEAPON, sk_mechanics, sk_null, 1, 750, false); + RECIPE(itm_pipebomb, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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_FOOD, sk_cooking, sk_null, 0, 5000, false); + RECIPE(itm_water_clean, CC_FOOD, Skill::skill("cooking"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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_FOOD, sk_cooking, sk_null, 0, 4000, false); + RECIPE(itm_tea, CC_FOOD, Skill::skill("cooking"), Skill::skill("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_FOOD, sk_cooking, sk_null, 0, 4000, false); + RECIPE(itm_coffee, CC_FOOD, Skill::skill("cooking"), Skill::skill("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_FOOD, sk_cooking, sk_null, 1, 5000, false); + RECIPE(itm_oj, CC_FOOD, Skill::skill("cooking"), Skill::skill("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_FOOD, sk_cooking, sk_null, 2, 7000, false); + RECIPE(itm_apple_cider, CC_FOOD, Skill::skill("cooking"), Skill::skill("null"), 2, 7000, false); TOOL(itm_rock, -1, itm_toolset, -1, NULL); COMP(itm_apple, 3, NULL); - RECIPE(itm_long_island, CC_FOOD, sk_cooking, sk_null, 1, 7000, false); + RECIPE(itm_long_island, CC_FOOD, Skill::skill("cooking"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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_FOOD, sk_cooking, sk_null, 5, 20000, false); + RECIPE(itm_meth, CC_FOOD, Skill::skill("cooking"), Skill::skill("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_FOOD, sk_cooking, sk_null, 5, 5000, false); + RECIPE(itm_royal_jelly, CC_FOOD, Skill::skill("cooking"), Skill::skill("null"), 5, 5000, false); COMP(itm_honeycomb, 1, NULL); COMP(itm_bleach, 2, itm_purifier, 1, NULL); - RECIPE(itm_heroin, CC_FOOD, sk_cooking, sk_null, 6, 2000, false); + RECIPE(itm_heroin, CC_FOOD, Skill::skill("cooking"), Skill::skill("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_FOOD, sk_cooking, sk_firstaid, 8, 10000, false); + RECIPE(itm_mutagen, CC_FOOD, 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_FOOD, sk_cooking, sk_firstaid, 9, 10000, false); + RECIPE(itm_purifier, CC_FOOD, 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, Skill::skill("null"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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, Skill::skill("null"), Skill::skill("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"), Skill::skill("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, Skill::skill("null"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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"), Skill::skill("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 == Skill::skill("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 == Skill::skill("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 == Skill::skill("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)); @@ -1411,10 +1411,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 == Skill::skill("null") || + u.skillLevel(recipes[i]->sk_primary) >= recipes[i]->difficulty) && + (recipes[i]->sk_secondary == Skill::skill("null") || + u.skillLevel(recipes[i]->sk_secondary) > 0)) { if (recipes[i]->difficulty >= 0) current.push_back(recipes[i]); @@ -1475,11 +1475,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 == Skill::skill("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; @@ -1489,9 +1489,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 != Skill::skill("null")) u.practice(making->sk_primary, making->difficulty * 5 + 20); - if (making->sk_secondary != sk_null) + if (making->sk_secondary != Skill::skill("null")) u.practice(making->sk_secondary, 5); // Messed up badly; waste some components. @@ -1884,11 +1884,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 == Skill::skill("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; @@ -1896,9 +1896,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 != Skill::skill("null")) u.practice(dis->sk_primary, (dis->difficulty) * 2); - if (dis->sk_secondary != sk_null) + if (dis->sk_secondary != Skill::skill("null")) u.practice(dis->sk_secondary, 2); for (int j = 0; j < 5; j++) diff --git a/crafting.h b/crafting.h index 4db266edcd61f..6cc9bef35b8da 100644 --- a/crafting.h +++ b/crafting.h @@ -29,23 +29,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 = Skill::skill("null"); + sk_secondary = Skill::skill("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) {} From d9d9105b2f1ebfa9ad64190b14334c908518d127 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 21:51:22 +0100 Subject: [PATCH 20/25] cleanup --- game.cpp | 71 ++++++++++++++++++++--------------------------------- game.h | 2 +- npc.cpp | 2 +- npctalk.cpp | 6 ++--- player.cpp | 32 ------------------------ player.h | 1 - 6 files changed, 31 insertions(+), 83 deletions(-) diff --git a/game.cpp b/game.cpp index 3707b6a2b8279..4431842568e1d 100644 --- a/game.cpp +++ b/game.cpp @@ -708,53 +708,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() @@ -2131,8 +2116,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: @@ -2164,12 +2149,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()); diff --git a/game.h b/game.h index 286cf21091e2b..af2c5a337821e 100644 --- a/game.h +++ b/game.h @@ -338,7 +338,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/npc.cpp b/npc.cpp index 6244e125711a5..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; diff --git a/npctalk.cpp b/npctalk.cpp index b1aab5dd3ce5c..592938b3983d9 100644 --- a/npctalk.cpp +++ b/npctalk.cpp @@ -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 3cd4184352550..80f7f3c773c52 100644 --- a/player.cpp +++ b/player.cpp @@ -527,9 +527,6 @@ void player::load_info(game *g, std::string data) dump >> skillLevel(*aSkill); } - for (int i = 0; i < num_skill_types; i++) - dump >> sklevel[i] >> skexercise[i] >> sklearn[i]; - int numstyles, typetmp; dump >> numstyles; for (int i = 0; i < numstyles; i++) { @@ -4863,35 +4860,6 @@ 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]; - } - } - } - 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]++; - } - } -} - void player::practice (Skill s, int amount) { SkillLevel& level = skillLevel(s); diff --git a/player.h b/player.h index 9dca78ff18f22..bcc7ba247dd97 100644 --- a/player.h +++ b/player.h @@ -209,7 +209,6 @@ 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); From 34831c98e13d76711e2a697650e2c363f1fbba26 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 21:54:56 +0100 Subject: [PATCH 21/25] moved skills file into place. --- data/{SKILLS => raw/skills.json} | 0 skill.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename data/{SKILLS => raw/skills.json} (100%) diff --git a/data/SKILLS b/data/raw/skills.json similarity index 100% rename from data/SKILLS rename to data/raw/skills.json diff --git a/skill.cpp b/skill.cpp index 1e297d432b4a5..3e9a6dbce1046 100644 --- a/skill.cpp +++ b/skill.cpp @@ -27,7 +27,7 @@ std::vector Skill::loadSkills() { std::ifstream skills_file; - skills_file.open("data/SKILLS"); + skills_file.open("data/raw/SKILLS"); while (!skills_file.eof()) { std::string ident, name; From 7a51e2628576394a9784ce82e2fa077ab355d36e Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Sun, 13 Jan 2013 22:33:29 +0100 Subject: [PATCH 22/25] Converted file format to JSON. Adds picojson by Kazuho Oku. github.com/kazuho/picojson This necessitates mention in readme-files bundled with compiled releases; no change required for code releases. --- data/raw/skills.json | 295 ++++++------- picojson.h | 998 +++++++++++++++++++++++++++++++++++++++++++ skill.cpp | 38 +- 3 files changed, 1160 insertions(+), 171 deletions(-) create mode 100644 picojson.h diff --git a/data/raw/skills.json b/data/raw/skills.json index 4a0004182efef..05f25e3c42d8d 100644 --- a/data/raw/skills.json +++ b/data/raw/skills.json @@ -1,153 +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 -occurrence. It is also used when attempting to fall gracefully, or in other -acrobatic feats. - -melee -melee -Your skill at hand-to-hand combat, both with and without a weapon. At low -levels this merely increases your chance to hit, but at higher levels it also -increases the damage done significantly. - -unarmed -unarmed combat -Your skill at combat without a weapon. While at low levels, unarmed combat is -a good way to die quickly, those skilled in it can eventually use throws and -crushing blows to quickly dispatch enemies. - -bashing -bashing weapons -Your skill at combat with weapons that club or bash your enemies. This -includes everything from rocks to baseball bats, and even the butt of rifles. -This 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 -this will simply slightly increase accuracy and damage; later on it will -help you bypass armor and thick hides. - -stabbing -piercing weapons -Your skill at combat that involves piercing weapons. This includes spears, -which only have a stabbing attack, and things like knives, which can cut or -pierce. 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 -both accuracy and, at higher levels, range. - -gun -firearms -Your general skill at firearms. This increases your accuracy with any gun, -but 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 -and 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, -but has short range. Shotguns may also be loaded with slugs, which go further -and do as much damage, but are not very accurate. - -smg -submachine guns -Your skill with submachine guns and machine pistols. Halfway between a pistol -and an assault rifle, these weapons fire and reload quickly, and may fire in -bursts, but they are not very accurate. - -rifle -rifles -Your skill with rifles, both assault rifles and semi-auto hunting rifles. -These have terrific range and accuracy, but are very slow to fire and reload, -and are not very good in close quarters. - -archery -archery -Your skill with all kinds of bows, from crossbows to handmade long bows. -These are quiet, but require some amount of strength to use, and are not -terribly accurate. They can only be deadly in skilled hands. - -launcher -grenade launcher -Your skill with grenade launchers, whether standalone or as a rifle mod. -These launchers fire a variety of 40mm grenades with different uses, -but they and their rounds are hard to find. - -computer -computers -Your skill with computers, both in terms of legitimate use, and hacking. This -will help you use complex systems, and bypass their security. - -mechanics -mechanics -Your skill with repairs to mechanical systems, and the crafting of many items -that use complex parts, but are not electronics. - -electronics -electronics -Your skill with repairs to electrical systems, and the crafting of many items -that use electrical parts. - -cooking -cooking -Your skill in combining food ingredients to make other, tastier food items. -This 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 -terrain, via the * screen. - -survival -survival -Your skill in wilderness survival. This helps you butcher meat from a corpse -and craft various basic survival items. High levels may allow you to remove -poison 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 -this does not help you detect traps, or avoid their effects if you activate -them. - -tailor -tailoring -Your skill at repairing clothing, and at higher levels, creating clothing -from basic materials. Generally a sewing kit is needed. Also applies to -other methods of clothing repair and textile crafting. - -firstaid -first aid -Your skill at emergency medical treatment, such as that from first aid kits -and bandages. High levels of this skill may help heal more HP. Some drugs -may be more effective as well. - -speech -speech -Your skill at talking to people, convincing them of things, lying, and many -others. Works best in conjunction with a high intelligence. - -barter -barter -Your skill at getting a good deal when trading with others. Very high levels -might even see you getting freebies. - -swimming -swimming -Your skill at swimming. This affects speed, your ability to swim while -wearing clothes or carrying weights, and in-water combat. - -driving -driving -Your skill at driving. This affects how well you can control a vehicle, -as well as the penalty of shooting while driving. +[ + [ + "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/picojson.h b/picojson.h new file mode 100644 index 0000000000000..356d2b88138b2 --- /dev/null +++ b/picojson.h @@ -0,0 +1,998 @@ +/* + * Copyright 2009-2010 Cybozu Labs, Inc. + * Copyright 2011 Kazuho Oku + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY CYBOZU LABS, INC. ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL CYBOZU LABS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are + * those of the authors and should not be interpreted as representing official + * policies, either expressed or implied, of Cybozu Labs, Inc. + * + */ +#ifndef picojson_h +#define picojson_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #define SNPRINTF _snprintf_s + #pragma warning(push) + #pragma warning(disable : 4244) // conversion from int to char +#else + #define SNPRINTF snprintf +#endif + +namespace picojson { + + enum { + null_type, + boolean_type, + number_type, + string_type, + array_type, + object_type + }; + + struct null {}; + + class value { + public: + typedef std::vector array; + typedef std::map object; + protected: + int type_; + union { + bool boolean_; + double number_; + std::string* string_; + array* array_; + object* object_; + }; + public: + value(); + value(int type, bool); + explicit value(bool b); + explicit value(double n); + explicit value(const std::string& s); + explicit value(const array& a); + explicit value(const object& o); + explicit value(const char* s); + value(const char* s, size_t len); + ~value(); + value(const value& x); + value& operator=(const value& x); + template bool is() const; + template const T& get() const; + template T& get(); + bool evaluate_as_boolean() const; + const value& get(size_t idx) const; + const value& get(const std::string& key) const; + bool contains(size_t idx) const; + bool contains(const std::string& key) const; + std::string to_str() const; + template void serialize(Iter os) const; + std::string serialize() const; + private: + template value(const T*); // intentionally defined to block implicit conversion of pointer to bool + }; + + typedef value::array array; + typedef value::object object; + + inline value::value() : type_(null_type) {} + + inline value::value(int type, bool) : type_(type) { + switch (type) { +#define INIT(p, v) case p##type: p = v; break + INIT(boolean_, false); + INIT(number_, 0.0); + INIT(string_, new std::string()); + INIT(array_, new array()); + INIT(object_, new object()); +#undef INIT + default: break; + } + } + + inline value::value(bool b) : type_(boolean_type) { + boolean_ = b; + } + + inline value::value(double n) : type_(number_type) { + number_ = n; + } + + inline value::value(const std::string& s) : type_(string_type) { + string_ = new std::string(s); + } + + inline value::value(const array& a) : type_(array_type) { + array_ = new array(a); + } + + inline value::value(const object& o) : type_(object_type) { + object_ = new object(o); + } + + inline value::value(const char* s) : type_(string_type) { + string_ = new std::string(s); + } + + inline value::value(const char* s, size_t len) : type_(string_type) { + string_ = new std::string(s, len); + } + + inline value::~value() { + switch (type_) { +#define DEINIT(p) case p##type: delete p; break + DEINIT(string_); + DEINIT(array_); + DEINIT(object_); +#undef DEINIT + default: break; + } + } + + inline value::value(const value& x) : type_(x.type_) { + switch (type_) { +#define INIT(p, v) case p##type: p = v; break + INIT(boolean_, x.boolean_); + INIT(number_, x.number_); + INIT(string_, new std::string(*x.string_)); + INIT(array_, new array(*x.array_)); + INIT(object_, new object(*x.object_)); +#undef INIT + default: break; + } + } + + inline value& value::operator=(const value& x) { + if (this != &x) { + this->~value(); + new (this) value(x); + } + return *this; + } + +#define IS(ctype, jtype) \ + template <> inline bool value::is() const { \ + return type_ == jtype##_type; \ + } + IS(null, null) + IS(bool, boolean) + IS(int, number) + IS(double, number) + IS(std::string, string) + IS(array, array) + IS(object, object) +#undef IS + +#define GET(ctype, var) \ + template <> inline const ctype& value::get() const { \ + assert("type mismatch! call vis() before get()" \ + && is()); \ + return var; \ + } \ + template <> inline ctype& value::get() { \ + assert("type mismatch! call is() before get()" \ + && is()); \ + return var; \ + } + GET(bool, boolean_) + GET(double, number_) + GET(std::string, *string_) + GET(array, *array_) + GET(object, *object_) +#undef GET + + inline bool value::evaluate_as_boolean() const { + switch (type_) { + case null_type: + return false; + case boolean_type: + return boolean_; + case number_type: + return number_ != 0; + case string_type: + return ! string_->empty(); + default: + return true; + } + } + + inline const value& value::get(size_t idx) const { + static value s_null; + assert(is()); + return idx < array_->size() ? (*array_)[idx] : s_null; + } + + inline const value& value::get(const std::string& key) const { + static value s_null; + assert(is()); + object::const_iterator i = object_->find(key); + return i != object_->end() ? i->second : s_null; + } + + inline bool value::contains(size_t idx) const { + assert(is()); + return idx < array_->size(); + } + + inline bool value::contains(const std::string& key) const { + assert(is()); + object::const_iterator i = object_->find(key); + return i != object_->end(); + } + + inline std::string value::to_str() const { + switch (type_) { + case null_type: return "null"; + case boolean_type: return boolean_ ? "true" : "false"; + case number_type: { + char buf[256]; + double tmp; + SNPRINTF(buf, sizeof(buf), fabs(number_) < (1ULL << 53) && modf(number_, &tmp) == 0 ? "%.f" : "%.17g", number_); + return buf; + } + case string_type: return *string_; + case array_type: return "array"; + case object_type: return "object"; + default: assert(0); +#ifdef _MSC_VER + __assume(0); +#endif + } + } + + template void copy(const std::string& s, Iter oi) { + std::copy(s.begin(), s.end(), oi); + } + + template void serialize_str(const std::string& s, Iter oi) { + *oi++ = '"'; + for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { + switch (*i) { +#define MAP(val, sym) case val: copy(sym, oi); break + MAP('"', "\\\""); + MAP('\\', "\\\\"); + MAP('/', "\\/"); + MAP('\b', "\\b"); + MAP('\f', "\\f"); + MAP('\n', "\\n"); + MAP('\r', "\\r"); + MAP('\t', "\\t"); +#undef MAP + default: + if ((unsigned char)*i < 0x20 || *i == 0x7f) { + char buf[7]; + SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff); + copy(buf, buf + 6, oi); + } else { + *oi++ = *i; + } + break; + } + } + *oi++ = '"'; + } + + template void value::serialize(Iter oi) const { + switch (type_) { + case string_type: + serialize_str(*string_, oi); + break; + case array_type: { + *oi++ = '['; + for (array::const_iterator i = array_->begin(); i != array_->end(); ++i) { + if (i != array_->begin()) { + *oi++ = ','; + } + i->serialize(oi); + } + *oi++ = ']'; + break; + } + case object_type: { + *oi++ = '{'; + for (object::const_iterator i = object_->begin(); + i != object_->end(); + ++i) { + if (i != object_->begin()) { + *oi++ = ','; + } + serialize_str(i->first, oi); + *oi++ = ':'; + i->second.serialize(oi); + } + *oi++ = '}'; + break; + } + default: + copy(to_str(), oi); + break; + } + } + + inline std::string value::serialize() const { + std::string s; + serialize(std::back_inserter(s)); + return s; + } + + template class input { + protected: + Iter cur_, end_; + int last_ch_; + bool ungot_; + int line_; + public: + input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {} + int getc() { + if (ungot_) { + ungot_ = false; + return last_ch_; + } + if (cur_ == end_) { + last_ch_ = -1; + return -1; + } + if (last_ch_ == '\n') { + line_++; + } + last_ch_ = *cur_++ & 0xff; + return last_ch_; + } + void ungetc() { + if (last_ch_ != -1) { + assert(! ungot_); + ungot_ = true; + } + } + Iter cur() const { return cur_; } + int line() const { return line_; } + void skip_ws() { + while (1) { + int ch = getc(); + if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { + ungetc(); + break; + } + } + } + bool expect(int expect) { + skip_ws(); + if (getc() != expect) { + ungetc(); + return false; + } + return true; + } + bool match(const std::string& pattern) { + for (std::string::const_iterator pi(pattern.begin()); + pi != pattern.end(); + ++pi) { + if (getc() != *pi) { + ungetc(); + return false; + } + } + return true; + } + }; + + template inline int _parse_quadhex(input &in) { + int uni_ch = 0, hex; + for (int i = 0; i < 4; i++) { + if ((hex = in.getc()) == -1) { + return -1; + } + if ('0' <= hex && hex <= '9') { + hex -= '0'; + } else if ('A' <= hex && hex <= 'F') { + hex -= 'A' - 0xa; + } else if ('a' <= hex && hex <= 'f') { + hex -= 'a' - 0xa; + } else { + in.ungetc(); + return -1; + } + uni_ch = uni_ch * 16 + hex; + } + return uni_ch; + } + + template inline bool _parse_codepoint(String& out, input& in) { + int uni_ch; + if ((uni_ch = _parse_quadhex(in)) == -1) { + return false; + } + if (0xd800 <= uni_ch && uni_ch <= 0xdfff) { + if (0xdc00 <= uni_ch) { + // a second 16-bit of a surrogate pair appeared + return false; + } + // first 16-bit of surrogate pair, get the next one + if (in.getc() != '\\' || in.getc() != 'u') { + in.ungetc(); + return false; + } + int second = _parse_quadhex(in); + if (! (0xdc00 <= second && second <= 0xdfff)) { + return false; + } + uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff); + uni_ch += 0x10000; + } + if (uni_ch < 0x80) { + out.push_back(uni_ch); + } else { + if (uni_ch < 0x800) { + out.push_back(0xc0 | (uni_ch >> 6)); + } else { + if (uni_ch < 0x10000) { + out.push_back(0xe0 | (uni_ch >> 12)); + } else { + out.push_back(0xf0 | (uni_ch >> 18)); + out.push_back(0x80 | ((uni_ch >> 12) & 0x3f)); + } + out.push_back(0x80 | ((uni_ch >> 6) & 0x3f)); + } + out.push_back(0x80 | (uni_ch & 0x3f)); + } + return true; + } + + template inline bool _parse_string(String& out, input& in) { + while (1) { + int ch = in.getc(); + if (ch < ' ') { + in.ungetc(); + return false; + } else if (ch == '"') { + return true; + } else if (ch == '\\') { + if ((ch = in.getc()) == -1) { + return false; + } + switch (ch) { +#define MAP(sym, val) case sym: out.push_back(val); break + MAP('"', '\"'); + MAP('\\', '\\'); + MAP('/', '/'); + MAP('b', '\b'); + MAP('f', '\f'); + MAP('n', '\n'); + MAP('r', '\r'); + MAP('t', '\t'); +#undef MAP + case 'u': + if (! _parse_codepoint(out, in)) { + return false; + } + break; + default: + return false; + } + } else { + out.push_back(ch); + } + } + return false; + } + + template inline bool _parse_array(Context& ctx, input& in) { + if (! ctx.parse_array_start()) { + return false; + } + if (in.expect(']')) { + return true; + } + size_t idx = 0; + do { + if (! ctx.parse_array_item(in, idx)) { + return false; + } + idx++; + } while (in.expect(',')); + return in.expect(']'); + } + + template inline bool _parse_object(Context& ctx, input& in) { + if (! ctx.parse_object_start()) { + return false; + } + if (in.expect('}')) { + return true; + } + do { + std::string key; + if (! in.expect('"') + || ! _parse_string(key, in) + || ! in.expect(':')) { + return false; + } + if (! ctx.parse_object_item(in, key)) { + return false; + } + } while (in.expect(',')); + return in.expect('}'); + } + + template inline bool _parse_number(double& out, input& in) { + std::string num_str; + while (1) { + int ch = in.getc(); + if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.' + || ch == 'e' || ch == 'E') { + num_str.push_back(ch); + } else { + in.ungetc(); + break; + } + } + char* endp; + out = strtod(num_str.c_str(), &endp); + return endp == num_str.c_str() + num_str.size(); + } + + template inline bool _parse(Context& ctx, input& in) { + in.skip_ws(); + int ch = in.getc(); + switch (ch) { +#define IS(ch, text, op) case ch: \ + if (in.match(text) && op) { \ + return true; \ + } else { \ + return false; \ + } + IS('n', "ull", ctx.set_null()); + IS('f', "alse", ctx.set_bool(false)); + IS('t', "rue", ctx.set_bool(true)); +#undef IS + case '"': + return ctx.parse_string(in); + case '[': + return _parse_array(ctx, in); + case '{': + return _parse_object(ctx, in); + default: + if (('0' <= ch && ch <= '9') || ch == '-') { + in.ungetc(); + double f; + if (_parse_number(f, in)) { + ctx.set_number(f); + return true; + } else { + return false; + } + } + break; + } + in.ungetc(); + return false; + } + + class deny_parse_context { + public: + bool set_null() { return false; } + bool set_bool(bool) { return false; } + bool set_number(double) { return false; } + template bool parse_string(input&) { return false; } + bool parse_array_start() { return false; } + template bool parse_array_item(input&, size_t) { + return false; + } + bool parse_object_start() { return false; } + template bool parse_object_item(input&, const std::string&) { + return false; + } + }; + + class default_parse_context { + protected: + value* out_; + public: + default_parse_context(value* out) : out_(out) {} + bool set_null() { + *out_ = value(); + return true; + } + bool set_bool(bool b) { + *out_ = value(b); + return true; + } + bool set_number(double f) { + *out_ = value(f); + return true; + } + template bool parse_string(input& in) { + *out_ = value(string_type, false); + return _parse_string(out_->get(), in); + } + bool parse_array_start() { + *out_ = value(array_type, false); + return true; + } + template bool parse_array_item(input& in, size_t) { + array& a = out_->get(); + a.push_back(value()); + default_parse_context ctx(&a.back()); + return _parse(ctx, in); + } + bool parse_object_start() { + *out_ = value(object_type, false); + return true; + } + template bool parse_object_item(input& in, const std::string& key) { + object& o = out_->get(); + default_parse_context ctx(&o[key]); + return _parse(ctx, in); + } + private: + default_parse_context(const default_parse_context&); + default_parse_context& operator=(const default_parse_context&); + }; + + class null_parse_context { + public: + struct dummy_str { + void push_back(int) {} + }; + public: + null_parse_context() {} + bool set_null() { return true; } + bool set_bool(bool) { return true; } + bool set_number(double) { return true; } + template bool parse_string(input& in) { + dummy_str s; + return _parse_string(s, in); + } + bool parse_array_start() { return true; } + template bool parse_array_item(input& in, size_t) { + return _parse(*this, in); + } + bool parse_object_start() { return true; } + template bool parse_object_item(input& in, const std::string&) { + return _parse(*this, in); + } + private: + null_parse_context(const null_parse_context&); + null_parse_context& operator=(const null_parse_context&); + }; + + // obsolete, use the version below + template inline std::string parse(value& out, Iter& pos, const Iter& last) { + std::string err; + pos = parse(out, pos, last, &err); + return err; + } + + template inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) { + input in(first, last); + if (! _parse(ctx, in) && err != NULL) { + char buf[64]; + SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line()); + *err = buf; + while (1) { + int ch = in.getc(); + if (ch == -1 || ch == '\n') { + break; + } else if (ch >= ' ') { + err->push_back(ch); + } + } + } + return in.cur(); + } + + template inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) { + default_parse_context ctx(&out); + return _parse(ctx, first, last, err); + } + + inline std::string parse(value& out, std::istream& is) { + std::string err; + parse(out, std::istreambuf_iterator(is.rdbuf()), + std::istreambuf_iterator(), &err); + return err; + } + + template struct last_error_t { + static std::string s; + }; + template std::string last_error_t::s; + + inline void set_last_error(const std::string& s) { + last_error_t::s = s; + } + + inline const std::string& get_last_error() { + return last_error_t::s; + } + + inline bool operator==(const value& x, const value& y) { + if (x.is()) + return y.is(); +#define PICOJSON_CMP(type) \ + if (x.is()) \ + return y.is() && x.get() == y.get() + PICOJSON_CMP(bool); + PICOJSON_CMP(double); + PICOJSON_CMP(std::string); + PICOJSON_CMP(array); + PICOJSON_CMP(object); +#undef PICOJSON_CMP + assert(0); +#ifdef _MSC_VER + __assume(0); +#endif + return false; + } + + inline bool operator!=(const value& x, const value& y) { + return ! (x == y); + } +} + +inline std::istream& operator>>(std::istream& is, picojson::value& x) +{ + picojson::set_last_error(std::string()); + std::string err = picojson::parse(x, is); + if (! err.empty()) { + picojson::set_last_error(err); + is.setstate(std::ios::failbit); + } + return is; +} + +inline std::ostream& operator<<(std::ostream& os, const picojson::value& x) +{ + x.serialize(std::ostream_iterator(os)); + return os; +} +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif +#ifdef TEST_PICOJSON +#ifdef _MSC_VER + #pragma warning(disable : 4127) // conditional expression is constant +#endif + +using namespace std; + +static void plan(int num) +{ + printf("1..%d\n", num); +} + +static bool success = true; + +static void ok(bool b, const char* name = "") +{ + static int n = 1; + if (! b) + success = false; + printf("%s %d - %s\n", b ? "ok" : "ng", n++, name); +} + +template void is(const T& x, const T& y, const char* name = "") +{ + if (x == y) { + ok(true, name); + } else { + ok(false, name); + } +} + +#include +#include +#include + +int main(void) +{ + plan(75); + + // constructors +#define TEST(expr, expected) \ + is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr) + + TEST( (true), "true"); + TEST( (false), "false"); + TEST( (42.0), "42"); + TEST( (string("hello")), "\"hello\""); + TEST( ("hello"), "\"hello\""); + TEST( ("hello", 4), "\"hell\""); + + { + double a = 1; + for (int i = 0; i < 1024; i++) { + picojson::value vi(a); + std::stringstream ss; + ss << vi; + picojson::value vo; + ss >> vo; + double b = vo.get(); + if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) { + printf("ng i=%d a=%.18e b=%.18e\n", i, a, b); + } + a *= 2; + } + } + +#undef TEST + +#define TEST(in, type, cmp, serialize_test) { \ + picojson::value v; \ + const char* s = in; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + ok(err.empty(), in " no error"); \ + ok(v.is(), in " check type"); \ + is(v.get(), cmp, in " correct output"); \ + is(*s, '\0', in " read to eof"); \ + if (serialize_test) { \ + is(v.serialize(), string(in), in " serialize"); \ + } \ + } + TEST("false", bool, false, true); + TEST("true", bool, true, true); + TEST("90.5", double, 90.5, false); + TEST("1.7976931348623157e+308", double, DBL_MAX, false); + TEST("\"hello\"", string, string("hello"), true); + TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"), + true); + TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string, + string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false); + TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false); +#undef TEST + +#define TEST(type, expr) { \ + picojson::value v; \ + const char *s = expr; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + ok(err.empty(), "empty " #type " no error"); \ + ok(v.is(), "empty " #type " check type"); \ + ok(v.get().empty(), "check " #type " array size"); \ + } + TEST(array, "[]"); + TEST(object, "{}"); +#undef TEST + + { + picojson::value v; + const char *s = "[1,true,\"hello\"]"; + string err = picojson::parse(v, s, s + strlen(s)); + ok(err.empty(), "array no error"); + ok(v.is(), "array check type"); + is(v.get().size(), size_t(3), "check array size"); + ok(v.contains(0), "check contains array[0]"); + ok(v.get(0).is(), "check array[0] type"); + is(v.get(0).get(), 1.0, "check array[0] value"); + ok(v.contains(1), "check contains array[1]"); + ok(v.get(1).is(), "check array[1] type"); + ok(v.get(1).get(), "check array[1] value"); + ok(v.contains(2), "check contains array[2]"); + ok(v.get(2).is(), "check array[2] type"); + is(v.get(2).get(), string("hello"), "check array[2] value"); + ok(!v.contains(3), "check not contains array[3]"); + } + + { + picojson::value v; + const char *s = "{ \"a\": true }"; + string err = picojson::parse(v, s, s + strlen(s)); + ok(err.empty(), "object no error"); + ok(v.is(), "object check type"); + is(v.get().size(), size_t(1), "check object size"); + ok(v.contains("a"), "check contains property"); + ok(v.get("a").is(), "check bool property exists"); + is(v.get("a").get(), true, "check bool property value"); + is(v.serialize(), string("{\"a\":true}"), "serialize object"); + ok(!v.contains("z"), "check not contains property"); + } + +#define TEST(json, msg) do { \ + picojson::value v; \ + const char *s = json; \ + string err = picojson::parse(v, s, s + strlen(s)); \ + is(err, string("syntax error at line " msg), msg); \ + } while (0) + TEST("falsoa", "1 near: oa"); + TEST("{]", "1 near: ]"); + TEST("\n\bbell", "2 near: bell"); + TEST("\"abc\nd\"", "1 near: "); +#undef TEST + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }"; + err = picojson::parse(v2, s, s + strlen(s)); + ok((v1 == v2), "check == operator in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }"; + err = picojson::parse(v2, s, s + strlen(s)); + ok((v1 != v2), "check != operator for array in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }"; + err = picojson::parse(v2, s, s + strlen(s)); + ok((v1 != v2), "check != operator for object in deep comparison"); + } + + { + picojson::value v1, v2; + const char *s; + string err; + s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }"; + err = picojson::parse(v1, s, s + strlen(s)); + picojson::object& o = v1.get(); + o.erase("b"); + picojson::array& a = o["a"].get(); + picojson::array::iterator i; + i = std::remove(a.begin(), a.end(), picojson::value(std::string("three"))); + a.erase(i, a.end()); + s = "{ \"a\": [1,2], \"d\": 2 }"; + err = picojson::parse(v2, s, s + strlen(s)); + ok((v1 == v2), "check erase()"); + } + + ok(picojson::value(3.0).serialize() == "3", + "integral number should be serialized as a integer"); + + { + const char* s = "{ \"a\": [1,2], \"d\": 2 }"; + picojson::null_parse_context ctx; + string err; + picojson::_parse(ctx, s, s + strlen(s), &err); + ok(err.empty(), "null_parse_context"); + } + + return success ? 0 : 1; +} + +#endif diff --git a/skill.cpp b/skill.cpp index 3e9a6dbce1046..8ef491b6571cb 100644 --- a/skill.cpp +++ b/skill.cpp @@ -5,6 +5,8 @@ #include "skill.h" #include "rng.h" +#include "picojson.h" + Skill::Skill() { _ident = std::string("null"); @@ -25,32 +27,32 @@ std::vector Skill::skills(Skill::loadSkills()); std::vector Skill::loadSkills() { std::vector allSkills; - std::ifstream skills_file; + picojson::value skillsRaw; - skills_file.open("data/raw/SKILLS"); + std::ifstream skillsFile; - while (!skills_file.eof()) { - std::string ident, name; - std::ostringstream description; + skillsFile.open("data/raw/skills.json"); - getline(skills_file, ident); - getline(skills_file, name); + skillsFile >> skillsRaw; - std::string tmp; + 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(); - while (1) { - getline(skills_file, tmp); + std::string ident, name, description; - if (tmp == "") { - description << '\b'; + ident = aField++->get(); + name = aField++->get(); + description = aField++->get(); - Skill aSkill(allSkills.size(), ident, name, description.str()); - allSkills.push_back(aSkill); - break; - } else { - description << tmp << '\n'; - } + Skill newSkill(allSkills.size(), ident, name, description); + allSkills.push_back(newSkill); } + } else { + std::cout << skillsRaw << std::endl; + exit(1); } return allSkills; From 505d4a30870ef03881c8d6b51d43d842a189015d Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Mon, 14 Jan 2013 00:10:24 +0100 Subject: [PATCH 23/25] moved to references --- skill.cpp | 4 ++-- skill.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/skill.cpp b/skill.cpp index 8ef491b6571cb..9e8830fb29e65 100644 --- a/skill.cpp +++ b/skill.cpp @@ -66,13 +66,13 @@ size_t Skill::skill_id(std::string ident) { } } -Skill Skill::skill(std::string ident) { +Skill& Skill::skill(std::string ident) { size_t skillID = Skill::skill_id(ident); return Skill::skill(skillID); } -Skill Skill::skill(size_t id) { +Skill& Skill::skill(size_t id) { return Skill::skills[id]; } diff --git a/skill.h b/skill.h index 2d87319950fbc..ff26e5c3902e3 100644 --- a/skill.h +++ b/skill.h @@ -39,8 +39,8 @@ class Skill { public: static std::vector skills; static std::vector loadSkills(); - static Skill skill(std::string ident); - static Skill skill(size_t id); + static Skill& skill(std::string ident); + static Skill& skill(size_t id); static size_t skill_count(); From 4f784862aeaf3e79fdb62d3aa0fa58c2a20e2fad Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Mon, 14 Jan 2013 00:19:34 +0100 Subject: [PATCH 24/25] Fixed an off-by-one display error in the character screen. --- player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player.cpp b/player.cpp index 80f7f3c773c52..ced6623d1cb2c 100644 --- a/player.cpp +++ b/player.cpp @@ -1355,7 +1355,7 @@ encumb(bp_feet) * 5); Skill selectedSkill; for (int i = min; i < max; i++) { - Skill aSkill = Skill::skill(i); + Skill aSkill = Skill::skill(skillslist[i]); SkillLevel level = skillLevel(aSkill); bool isLearning = level.isTraining(); From c1e0814874b4dec0e877ed4bc6f08db28e906264 Mon Sep 17 00:00:00 2001 From: Williham Totland Date: Thu, 17 Jan 2013 14:55:49 +0100 Subject: [PATCH 25/25] Further reworked Skill to use pointers. This should remove the need for a null skill alltogether. --- crafting.cpp | 228 +++++++++++++++++++++++------------------------ crafting.h | 10 +-- defense.cpp | 2 +- game.cpp | 16 ++-- item.cpp | 34 +++---- itype.h | 8 +- itypedef.cpp | 12 +-- map.cpp | 2 +- mission.cpp | 4 +- monster.cpp | 2 +- newcharacter.cpp | 22 ++--- npc.h | 8 +- player.cpp | 28 +++--- player.h | 6 +- ranged.cpp | 2 +- skill.cpp | 20 ++--- skill.h | 12 +-- 17 files changed, 208 insertions(+), 208 deletions(-) diff --git a/crafting.cpp b/crafting.cpp index 86f1e33388aac..cd33e0546bc45 100755 --- 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, Skill::skill("null"), Skill::skill("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,28 +38,28 @@ RECIPE(itm_lawnmower, CC_NONCRAFT, Skill::skill("null"), Skill::skill("null"), 0 COMP(itm_combustion_tiny, 1, NULL); COMP(itm_pipe, 3, NULL); -RECIPE(itm_lighter, CC_NONCRAFT, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("stabbing"), Skill::skill("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); @@ -76,35 +76,35 @@ RECIPE(itm_lighter, CC_NONCRAFT, Skill::skill("null"), Skill::skill("null"), 0, COMP(itm_stick, 1, itm_broom, 1, itm_mop, 1, itm_2x4, 1, itm_bee_sting, 1, NULL); - RECIPE(itm_nailboard, CC_WEAPON, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("gun"), Skill::skill("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, Skill::skill("gun"), Skill::skill("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); @@ -169,12 +169,12 @@ RECIPE(itm_lighter, CC_NONCRAFT, Skill::skill("null"), Skill::skill("null"), 0, COMP(itm_shot_slug, 4, NULL); COMP(itm_gasoline, 200, NULL); - RECIPE(itm_acidbomb, CC_WEAPON, Skill::skill("cooking"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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,7 +183,7 @@ RECIPE(itm_lighter, CC_NONCRAFT, Skill::skill("null"), Skill::skill("null"), 0, 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, Skill::skill("mechanics"), Skill::skill("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); @@ -441,71 +441,71 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") // FOOD - RECIPE(itm_water_clean, CC_DRINK, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_tequila, 1, NULL); COMP(itm_triple_sec, 1, NULL); - RECIPE(itm_jerky, CC_FOOD, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_sugar, 2, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_pizza, CC_FOOD, Skill::skill("cooking"), Skill::skill("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,18 +558,18 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_sauce_pesto, 1, itm_sauce_red, 1, NULL); COMP(itm_water, 1, itm_water_clean, 1, NULL); - RECIPE(itm_meth, CC_CHEM, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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); @@ -590,38 +590,38 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") // ELECTRONICS - RECIPE(itm_antenna, CC_ELECTRONIC, Skill::skill("null"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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); @@ -634,7 +634,7 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") itm_bolt_steel, 1, itm_scrap, 1, NULL); COMP(itm_can_drink, 1, itm_can_food, 1, NULL); - RECIPE(itm_coilgun, CC_WEAPON, Skill::skill("electronics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_scrap, 6, NULL); COMP(itm_cable, 20, NULL); - RECIPE(itm_radio, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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); @@ -659,7 +659,7 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_scrap, 3, NULL); COMP(itm_cable, 5, NULL); - RECIPE(itm_hotplate, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") itm_knife_butter, 6, itm_muffler, 1, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_tazer, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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); @@ -692,7 +692,7 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_scrap, 4, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_EMPbomb, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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); @@ -708,7 +708,7 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_amplifier, 1, NULL); COMP(itm_cable, 2, NULL); - RECIPE(itm_geiger_off, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_scrap, 6, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_UPS_off, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_scrap, 4, NULL); COMP(itm_cable, 10, NULL); - RECIPE(itm_bionics_battery, CC_ELECTRONIC, Skill::skill("electronics"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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,59 +743,59 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") // ARMOR - RECIPE(itm_thread, CC_ARMOR, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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); @@ -803,13 +803,13 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") 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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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); @@ -822,39 +822,39 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_amplifier, 3, NULL); COMP(itm_scrap, 5, NULL); - RECIPE(itm_hat_fur, CC_ARMOR, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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,27 +863,27 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_steel_chunk, 12, NULL); COMP(itm_wire, 3, NULL); - RECIPE(itm_string_36, CC_MISC, Skill::skill("null"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("tailor"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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); @@ -902,55 +902,55 @@ RECIPE(itm_c4, CC_WEAPON, Skill::skill("mechanics"), Skill::skill("electronics") COMP(itm_poppy_bud, 2, NULL); COMP(itm_poppy_flower, 2, NULL); - RECIPE(itm_carspike, CC_MISC, Skill::skill("null"), Skill::skill("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, Skill::skill("null"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("gun"), Skill::skill("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, Skill::skill("traps"), Skill::skill("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, Skill::skill("traps"), Skill::skill("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); @@ -989,22 +989,22 @@ RECIPE(itm_boobytrap, CC_MISC, Skill::skill("mechanics"), Skill::skill("traps"), 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, Skill::skill("firstaid"), Skill::skill("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, Skill::skill("mechanics"), Skill::skill("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, Skill::skill("cooking"), Skill::skill("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, Skill::skill("electronics"), Skill::skill("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); @@ -1124,13 +1124,13 @@ 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 == Skill::skill("null") ? "N/A" : - current[line]->sk_primary.name().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 == Skill::skill("null") ? "N/A" : - current[line]->sk_secondary.name().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 == Skill::skill("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", @@ -1429,9 +1429,9 @@ 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 == Skill::skill("null") || + (recipes[i]->sk_primary == NULL || u.skillLevel(recipes[i]->sk_primary) >= recipes[i]->difficulty) && - (recipes[i]->sk_secondary == Skill::skill("null") || + (recipes[i]->sk_secondary == NULL || u.skillLevel(recipes[i]->sk_secondary) > 0)) { if (recipes[i]->difficulty >= 0) @@ -1494,7 +1494,7 @@ void game::complete_craft() // # of dice is 75% primary skill, 25% secondary (unless secondary is null) int skill_dice = u.skillLevel(making->sk_primary).level() * 3; - if (making->sk_secondary == Skill::skill("null")) + if (making->sk_secondary == NULL) skill_dice += u.skillLevel(making->sk_primary).level(); else skill_dice += u.skillLevel(making->sk_secondary).level(); @@ -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 != Skill::skill("null")) + if (making->sk_primary) u.practice(making->sk_primary, making->difficulty * 5 + 20); - if (making->sk_secondary != Skill::skill("null")) + if (making->sk_secondary) u.practice(making->sk_secondary, 5); // Messed up badly; waste some components. @@ -1903,7 +1903,7 @@ 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.skillLevel(dis->sk_primary).level() * 3; - if (dis->sk_secondary == Skill::skill("null")) + if (dis->sk_secondary == NULL) skill_dice += u.skillLevel(dis->sk_primary).level(); else skill_dice += u.skillLevel(dis->sk_secondary).level(); @@ -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 != Skill::skill("null")) + if (dis->sk_primary) u.practice(dis->sk_primary, (dis->difficulty) * 2); - if (dis->sk_secondary != Skill::skill("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 cc2f9380bc6db..8b96a9b9e52a7 100755 --- a/crafting.h +++ b/crafting.h @@ -35,8 +35,8 @@ struct recipe { int id; itype_id result; craft_cat category; - Skill sk_primary; - Skill sk_secondary; + Skill *sk_primary; + Skill *sk_secondary; int difficulty; int time; bool reversible; // can the item be disassembled? @@ -48,14 +48,14 @@ struct recipe { id = 0; result = itm_null; category = CC_NULL; - sk_primary = Skill::skill("null"); - sk_secondary = Skill::skill("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, +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/defense.cpp b/defense.cpp index b15d3971b9e28..b579ea721152d 100644 --- a/defense.cpp +++ b/defense.cpp @@ -1185,7 +1185,7 @@ void draw_caravan_items(WINDOW *w, game *g, std::vector *items, } int caravan_price(player &u, int price) { - Skill barterSkill = Skill::skill("barter"); + Skill *barterSkill = Skill::skill("barter"); if (u.skillLevel(barterSkill) > 10) return int( double(price) * .5); diff --git a/game.cpp b/game.cpp index 572b3f64233db..eccf952ae671a 100644 --- a/game.cpp +++ b/game.cpp @@ -717,7 +717,7 @@ void game::rustCheck() { u.skillLevel(*aSkill).rust(newLevel); if (newLevel < skillLevel) { - add_msg("Your skill in %s has reduced to %d!", aSkill->name().c_str(), newLevel); + add_msg("Your skill in %s has reduced to %d!", (*aSkill)->name().c_str(), newLevel); } } } @@ -794,7 +794,7 @@ void game::process_activity() } if (u.skillLevel(reading->type) < reading->level) { - add_msg("You learn a little about %s!", reading->type.name().c_str()); + 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.skillLevel(reading->type).level(); if (min_ex < 1) @@ -2138,7 +2138,7 @@ z.size(), events.size()); int(p->personality.collector) << " Altruism: " << int(p->personality.altruism) << std::endl; for (EACH_SKILL) { - data << aSkill->name() << ": " << p->skillLevel(*aSkill) << std::endl; + data << (*aSkill)->name() << ": " << p->skillLevel(*aSkill) << std::endl; } full_screen_popup(data.str().c_str()); @@ -4364,7 +4364,7 @@ void game::examine() u.power_level > 0 && query_yn("Use fingerhack on the reader?")); if (using_electrohack || using_fingerhack) { - Skill computerSkill = Skill::skill("computer"); + Skill *computerSkill = Skill::skill("computer"); u.moves -= 500; u.practice(computerSkill, 20); @@ -5927,7 +5927,7 @@ void game::plfire(bool burst) burst = true; // Train up our skill - Skill gunSkill = Skill::skill("gun"); + Skill *gunSkill = Skill::skill("gun"); it_gun* firing = dynamic_cast(u.weapon.type); int num_shots = 1; @@ -5994,7 +5994,7 @@ void game::complete_butcher(int index) int pieces, pelts; double skill_shift = 0.; - Skill survivalSkill = Skill::skill("survival"); + Skill *survivalSkill = Skill::skill("survival"); uint32_t sSkillLevel = u.skillLevel(survivalSkill).level(); switch (corpse->size) { @@ -6354,7 +6354,7 @@ void game::chat() } void game::pldrive(int x, int y) { - Skill drivingSkill = Skill::skill("driving"); + 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! " @@ -6537,7 +6537,7 @@ void game::plmove(int x, int y) // Adjust recoil down if (u.recoil > 0) { - Skill gunSkill = Skill::skill("gun"); + Skill *gunSkill = Skill::skill("gun"); if (int(u.str_cur / 2) + u.skillLevel(gunSkill).level() >= u.recoil) u.recoil = 0; diff --git a/item.cpp b/item.cpp index ebdde288589af..e1fcb4cad6177 100644 --- a/item.cpp +++ b/item.cpp @@ -364,7 +364,7 @@ std::string item::info(bool showtext) ammo_recoil = curammo->recoil; } - dump << " Skill used: " << gun->skill_used.name() << "\n Ammunition: " << + dump << " Skill used: " << gun->skill_used->name() << "\n Ammunition: " << clip_size() << " rounds of " << ammo_name(ammo_type()); dump << "\n Damage: "; @@ -455,15 +455,15 @@ std::string item::info(bool showtext) } else if (is_book()) { it_book* book = dynamic_cast(type); - if (book->type == Skill::skill("null")) + if (!book->type) dump << " Just for fun.\n"; else { - dump << " Can bring your " << book->type.name() << " 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 " << book->type.name() << " 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; @@ -545,7 +545,7 @@ nc_color item::color(player *u) } } else if (is_book()) { it_book* tmp = dynamic_cast(type); - if (Skill::skill("null") != tmp->type && tmp->intel <= u->int_cur + u->skillLevel(tmp->type).level() && + if (tmp->type && tmp->intel <= u->int_cur + u->skillLevel(tmp->type).level() && (tmp->intel == 0 || !u->has_trait(PF_ILLITERATE)) && (u->skillLevel(tmp->type) >= tmp->req) && (u->skillLevel(tmp->type) < tmp->level)) @@ -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->skillLevel(Skill::skill("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.id()])); /// TODO: FIXME + gun_value *= (.3 + (.7 * skills[gun->skill_used->id()])); /// TODO: FIXME my_value += gun_value; } @@ -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() ) @@ -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 3b63fb527ad9c..e42bfeca144d4 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 d1c461bada323..1f029831095ea 100644 --- a/itypedef.cpp +++ b/itypedef.cpp @@ -3086,7 +3086,7 @@ 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, Skill::skill("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, @@ -3094,7 +3094,7 @@ BOOK("US Weekly", 40, 40,c_pink, PAPER, MNULL, 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, Skill::skill("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, @@ -3114,21 +3114,21 @@ BOOK("Guns n Ammo", 20, 48,c_pink, PAPER, MNULL, Reviews of firearms, and various useful tips about their use."); BOOK("romance novel", 30, 55,c_ltblue, PAPER, MNULL, - 4, 1, -2, 0, Skill::skill("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, Skill::skill("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, Skill::skill("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, Skill::skill("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, diff --git a/map.cpp b/map.cpp index 96244933c511f..a3a61458e353d 100644 --- a/map.cpp +++ b/map.cpp @@ -2036,7 +2036,7 @@ void map::add_trap(int x, int y, trap_id t) void map::disarm_trap(game *g, int x, int y) { - Skill trapsSkill = Skill::skill("traps"); + Skill *trapsSkill = Skill::skill("traps"); uint32_t skillLevel = g->u.skillLevel(trapsSkill).level(); if (tr_at(x, y) == tr_null) { 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/monster.cpp b/monster.cpp index 72895fb3c2574..231f046d17f04 100644 --- a/monster.cpp +++ b/monster.cpp @@ -475,7 +475,7 @@ int monster::trigger_sum(game *g, std::vector *triggers) } int monster::hit(game *g, player &p, body_part &bp_hit) { - Skill dodgeSkill = Skill::skill("dodge"); + Skill *dodgeSkill = Skill::skill("dodge"); int numdice = type->melee_skill; if (dice(numdice, 10) <= dice(p.dodge(g), 10) && !one_in(20)) { diff --git a/newcharacter.cpp b/newcharacter.cpp index 7e1ce2428e106..c6f15b6d77276 100644 --- a/newcharacter.cpp +++ b/newcharacter.cpp @@ -120,7 +120,7 @@ bool player::create(game *g, character_type type, std::string tempname) case 9: rn = random_skill(); - Skill aSkill = Skill::skill(rn); + Skill *aSkill = Skill::skill(rn); uint32_t level = skillLevel(aSkill).level(); if (level < points) { @@ -710,7 +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); + Skill *currentSkill = Skill::skill(cur_sk); do { mvwprintz(w, 3, 2, c_ltgray, "Points left: %d ", points); @@ -727,17 +727,17 @@ int set_skills(WINDOW* w, player *u, int &points) else mvwprintz(w, 3, 30, c_ltred, "Upgrading %s costs %d points ", skill_name(cur_sk).c_str(), u->skillLevel(currentSkill).level() + 1); - mvwprintz(w, 22, 0, COL_SKILL_USED, currentSkill.description().c_str()); + 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); + Skill *thisSkill = Skill::skill(i); mvwprintz(w, 4 + i, 0, c_ltgray, "\ "); // Clear the line if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 4 + i, 0, (i == cur_sk ? h_ltgray : c_ltgray), - thisSkill.name().c_str()); + thisSkill->name().c_str()); } else { mvwprintz(w, 4 + i, 0, (i == cur_sk ? hilite(COL_SKILL_USED) : COL_SKILL_USED), @@ -748,32 +748,32 @@ int set_skills(WINDOW* w, player *u, int &points) } } 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); + Skill *thisSkill = Skill::skill(i); mvwprintz(w, 21 + i - num_skill_types, 0, c_ltgray, "\ "); // Clear the line if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 21 + i - num_skill_types, 0, - (i == cur_sk ? h_ltgray : c_ltgray), thisSkill.name().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 ", - thisSkill.name().c_str()); + 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); + Skill *thisSkill = Skill::skill(i); mvwprintz(w, 12 + i - cur_sk, 0, c_ltgray, "\ "); // Clear the line if (u->skillLevel(thisSkill) == 0) { mvwprintz(w, 12 + i - cur_sk, 0, (i == cur_sk ? h_ltgray : c_ltgray), - thisSkill.name().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 ", thisSkill.name().c_str()); + "%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), "*"); } 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/player.cpp b/player.cpp index 2d311cd3098a3..a4acacfa58080 100644 --- a/player.cpp +++ b/player.cpp @@ -941,7 +941,7 @@ Strength - 4; Dexterity - 4; Intelligence - 4; Dexterity - 4"); std::vector skillslist; mvwprintz(w_skills, 0, 11, c_ltgray, "SKILLS"); for (EACH_SKILL) { - int i = aSkill->id(); + int i = (*aSkill)->id(); SkillLevel level = skillLevel(*aSkill); @@ -952,7 +952,7 @@ Strength - 4; Dexterity - 4; Intelligence - 4; Dexterity - 4"); skillslist.push_back(skill(i)); if (line < 9) { mvwprintz(w_skills, line, 1, skillLevel(*aSkill).isTraining() ? c_dkgray : c_ltblue, "%-17s", - (aSkill->name() + ":").c_str()); + ((*aSkill)->name() + ":").c_str()); mvwprintz(w_skills, line,19, c_ltblue, "%-2d(%2d%%%%)", level.level(), (level.exercise() < 0 ? 0 : level.exercise())); line++; @@ -1351,10 +1351,10 @@ encumb(bp_feet) * 5); min = 0; } - Skill selectedSkill; + Skill *selectedSkill; for (int i = min; i < max; i++) { - Skill aSkill = Skill::skill(skillslist[i]); + Skill *aSkill = Skill::skill(skillslist[i]); SkillLevel level = skillLevel(aSkill); bool isLearning = level.isTraining(); @@ -1375,13 +1375,13 @@ encumb(bp_feet) * 5); mvwprintz(w_skills, 2 + i - min, 1, c_ltgray, " "); if (exercise >= 100) { mvwprintz(w_skills, 2 + i - min, 1, status, "%s:", - aSkill.name().c_str()); + 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, "%-17s", - (aSkill.name() + ":").c_str()); + (aSkill->name() + ":").c_str()); mvwprintz(w_skills, 2 + i - min,19, status, "%-2d(%2d%%%%)", level.level(), (exercise < 0 ? 0 : @@ -1391,7 +1391,7 @@ encumb(bp_feet) * 5); werase(w_info); if (line >= 0 && line < skillslist.size()) mvwprintz(w_info, 0, 0, c_magenta, - selectedSkill.description().c_str()); + selectedSkill->description().c_str()); wrefresh(w_skills); wrefresh(w_info); switch (input()) { @@ -1407,14 +1407,14 @@ encumb(bp_feet) * 5); werase(w_skills); mvwprintz(w_skills, 0, 0, c_ltgray, " SKILLS "); for (int i = 0; i < skillslist.size() && i < 7; i++) { - Skill thisSkill = Skill::skill(i); + 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:", - thisSkill.name().c_str()); + thisSkill->name().c_str()); mvwprintz(w_skills, i + 2, 19, status, "%d (%2d%%%%)", thisLevel.level(), (thisLevel.exercise() < 0 ? 0 : @@ -4529,7 +4529,7 @@ int time; //Declare this here so that we can change the time depending on whats } else if (skillLevel(tmp->type) < tmp->req) { g->add_msg("The %s-related jargon flies over your head!", - tmp->type.name().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."); @@ -4540,7 +4540,7 @@ int time; //Declare this here so that we can change the time depending on whats } else if (skillLevel(tmp->type) >= tmp->level && tmp->fun <= 0 && !query_yn("Your %s skill won't be improved. Read anyway?", - tmp->type.name().c_str())) + tmp->type->name().c_str())) return; // Base read_speed() is 1000 move points (1 minute per tmp->time) @@ -4863,7 +4863,7 @@ bool player::wearing_something_on(body_part bp) return false; } -void player::practice (Skill s, int amount) { +void player::practice (Skill *s, int amount) { SkillLevel& level = skillLevel(s); if (level.exercise() < 0) { @@ -4876,7 +4876,7 @@ void player::practice (Skill s, int amount) { bool isSavant = has_trait(PF_SAVANT); - Skill savantSkill = Skill(); + Skill *savantSkill = NULL; SkillLevel savantSkillLevel = SkillLevel(); if (isSavant) { @@ -5087,6 +5087,6 @@ SkillLevel& player::skillLevel(std::string ident) { return _skills[Skill::skill(ident)]; } -SkillLevel& player::skillLevel(const Skill& _skill) { +SkillLevel& player::skillLevel(Skill *_skill) { return _skills[_skill]; } diff --git a/player.h b/player.h index 1b501ecfaf328..535d39c5e1849 100644 --- a/player.h +++ b/player.h @@ -31,7 +31,7 @@ struct special_attack }; class player { - std::map _skills; + std::map _skills; public: player(); @@ -204,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); + void practice(Skill *s, int amount); void assign_activity(activity_type type, int moves, int index = -1); void cancel_activity(); @@ -297,7 +297,7 @@ class player { int sktrain[num_skill_types]; bool sklearn[num_skill_types]; - SkillLevel& skillLevel(const Skill& _skill); + SkillLevel& skillLevel(Skill* _skill); SkillLevel& skillLevel(std::string ident); bool inv_sorted; diff --git a/ranged.cpp b/ranged.cpp index 649676aa42e6d..54357a9bae9d2 100644 --- a/ranged.cpp +++ b/ranged.cpp @@ -742,7 +742,7 @@ int time_to_fire(player &p, it_gun* firing) 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()); + debugmsg("Why is shooting %s using %s skill?", (firing->name).c_str(), firing->skill_used->name().c_str()); time = 0; } diff --git a/skill.cpp b/skill.cpp index 9e8830fb29e65..2a7454f4922ce 100644 --- a/skill.cpp +++ b/skill.cpp @@ -22,10 +22,10 @@ Skill::Skill(size_t id, std::string ident, std::string name, std::string descrip _description = description; } -std::vector Skill::skills(Skill::loadSkills()); +std::vector Skill::skills(Skill::loadSkills()); -std::vector Skill::loadSkills() { - std::vector allSkills; +std::vector Skill::loadSkills() { + std::vector allSkills; picojson::value skillsRaw; @@ -47,7 +47,7 @@ std::vector Skill::loadSkills() { name = aField++->get(); description = aField++->get(); - Skill newSkill(allSkills.size(), ident, name, description); + Skill *newSkill = new Skill(allSkills.size(), ident, name, description); allSkills.push_back(newSkill); } } else { @@ -60,19 +60,19 @@ std::vector Skill::loadSkills() { size_t Skill::skill_id(std::string ident) { for (EACH_SKILL) { - if (aSkill->_ident == ident) { - return aSkill->_id; + if ((*aSkill)->_ident == ident) { + return (*aSkill)->_id; } } } -Skill& Skill::skill(std::string ident) { +Skill* Skill::skill(std::string ident) { size_t skillID = Skill::skill_id(ident); return Skill::skill(skillID); } -Skill& Skill::skill(size_t id) { +Skill* Skill::skill(size_t id) { return Skill::skills[id]; } @@ -186,11 +186,11 @@ std::ostream& operator<<(std::ostream& os, const SkillLevel& obj) { std::string skill_name(int sk) { - return Skill::skill(sk).name(); + return Skill::skill(sk)->name(); } std::string skill_description(int sk) { - return Skill::skill(sk).description(); + return Skill::skill(sk)->description(); } double price_adjustment(int barter_skill) { diff --git a/skill.h b/skill.h index ff26e5c3902e3..8ffd9fe9e472d 100644 --- a/skill.h +++ b/skill.h @@ -24,8 +24,8 @@ 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 +#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; @@ -37,10 +37,10 @@ class Skill { 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 std::vector skills; + static std::vector loadSkills(); + static Skill* skill(std::string ident); + static Skill* skill(size_t id); static size_t skill_count();