Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds a mechanical skills system. #20159

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions SQL/migrate-2023/V011__skills_education.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
--
-- Implemented in PR #?????.
-- Add education and skills.
--

ALTER TABLE `ss13_characters` ADD COLUMN `education` VARCHAR(48) DEFAULT NULL AFTER `origin`;
ALTER TABLE `ss13_characters` ADD COLUMN `skills` VARCHAR(256) DEFAULT NULL AFTER `education`;
ALTER TABLE `ss13_characters` DROP COLUMN `home_system`;
18 changes: 18 additions & 0 deletions aurorastation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@
#include "code\__DEFINES\shuttle.dm"
#include "code\__DEFINES\si.dm"
#include "code\__DEFINES\singletons.dm"
#include "code\__DEFINES\skills.dm"
#include "code\__DEFINES\smart_token_bucket.dm"
#include "code\__DEFINES\solar.dm"
#include "code\__DEFINES\sound.dm"
Expand Down Expand Up @@ -363,6 +364,7 @@
#include "code\controllers\subsystems\records.dm"
#include "code\controllers\subsystems\responseteam.dm"
#include "code\controllers\subsystems\runechat.dm"
#include "code\controllers\subsystems\skills.dm"
#include "code\controllers\subsystems\skybox.dm"
#include "code\controllers\subsystems\sound_loops.dm"
#include "code\controllers\subsystems\sounds.dm"
Expand Down Expand Up @@ -537,6 +539,13 @@
#include "code\datums\repositories\singletons.dm"
#include "code\datums\repositories\sound_channels.dm"
#include "code\datums\repositories\unique.dm"
#include "code\datums\skills\_skill_categories.dm"
#include "code\datums\skills\_skills.dm"
#include "code\datums\skills\combat\combat.dm"
#include "code\datums\skills\everyday\service.dm"
#include "code\datums\skills\occupational\engineering.dm"
#include "code\datums\skills\occupational\medical.dm"
#include "code\datums\skills\occupational\science.dm"
#include "code\datums\state_machine\state.dm"
#include "code\datums\state_machine\transition.dm"
#include "code\datums\tips\tips.dm"
Expand Down Expand Up @@ -1699,6 +1708,13 @@
#include "code\modules\background\citizenship\tajara.dm"
#include "code\modules\background\citizenship\unathi.dm"
#include "code\modules\background\citizenship\vaurca.dm"
#include "code\modules\background\education\_education.dm"
#include "code\modules\background\education\engineering.dm"
#include "code\modules\background\education\medical.dm"
#include "code\modules\background\education\misc.dm"
#include "code\modules\background\education\science.dm"
#include "code\modules\background\education\security.dm"
#include "code\modules\background\education\service.dm"
#include "code\modules\background\origins\_origins.dm"
#include "code\modules\background\origins\origins\diona\biesel.dm"
#include "code\modules\background\origins\origins\diona\coalition.dm"
Expand Down Expand Up @@ -1864,6 +1880,7 @@
#include "code\modules\client\preference_setup\occupation\occupation.dm"
#include "code\modules\client\preference_setup\origin\origin.dm"
#include "code\modules\client\preference_setup\other\01_incidents.dm"
#include "code\modules\client\preference_setup\skills\skills.dm"
#include "code\modules\client\verbs\ping.dm"
#include "code\modules\clothing\chameleon.dm"
#include "code\modules\clothing\clothing.dm"
Expand Down Expand Up @@ -2830,6 +2847,7 @@
#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
#include "code\modules\mob\living\simple_animal\hostile\toy\mech.dm"
#include "code\modules\mob\living\simple_animal\mechanical\mechanical.dm"
#include "code\modules\mob\skills\skills.dm"
#include "code\modules\modular_computers\_description.dm"
#include "code\modules\modular_computers\laptop_vendor.dm"
#include "code\modules\modular_computers\computers\modular_computer\core.dm"
Expand Down
32 changes: 32 additions & 0 deletions code/__DEFINES/skills.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// You don't know anything about this subject.
#define SKILL_LEVEL_UNFAMILIAR 1
/// You're familiar with this subject, either by reading into it or by doing some courses.
#define SKILL_LEVEL_FAMILIAR 2
/// You've been formally trained in this subject. Typically, this is the minimum level for a job.
#define SKILL_LEVEL_TRAINED 3
/// You have some training and a good amount of experience in this subject.
#define SKILL_LEVEL_PROFESSIONAL 4

/// An everyday skill is a skill that can be picked up normally. Think like mixing a drink, growing a plant, cooking, and so on.
#define SKILL_CATEGORY_EVERYDAY "Everyday"
#define SKILL_SUBCATEGORY_SERVICE "Service"
#define SKILL_SUBCATEGORY_MUNDANE "Mundane"

/// Occupational skills are the skills necessary for you to do your job to a minimum degree.
#define SKILL_CATEGORY_OCCUPATIONAL "Occupational"
#define SKILL_SUBCATEGORY_MEDICAL "Medical"
#define SKILL_SUBCATEGORY_ENGINEERING "Engineering"
#define SKILL_SUBCATEGORY_SCIENCE "Science"

///A combat skill is a skill that has a direct effect in combat. These have an increased cost.
#define SKILL_CATEGORY_COMBAT "Combat"
#define SKILL_SUBCATEGORY_RANGED "Ranged"
#define SKILL_SUBCATEGORY_MELEE "Melee"

#define BASE_SKILL_POINTS_COMBAT 4
#define BASE_SKILL_POINTS_OCCUPATIONAL 8
#define BASE_SKILL_POINTS_EVERYDAY 8

#define SKILL_MODIFIER_EASY 1
#define SKILL_MODIFIER_MEDIUM 2
#define SKILL_MODIFIER_HARD 4
34 changes: 34 additions & 0 deletions code/controllers/subsystems/skills.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
SUBSYSTEM_DEF(skills)
name = "Skills"
flags = SS_NO_FIRE

/// This is essentially the list we use to read skills in the character setup.
var/list/skill_tree = list()
/// A map of all the skill levels to their definition.
var/list/skill_level_map = list(
"Unfamiliar" = "You don't know anything about this subject.",
"Familiar" = "You're familiar with this subject, either by reading into it or by doing some courses.",
"Trained" = "You've been formally trained in this subject. Typically, this is the minimum level for a job.",
"Professional" = "You have a lot of training and a good amount of experience in this subject."
)

/datum/controller/subsystem/skills/Initialize()
// Initialize the skill category lists first.
// This creates linked lists as follows: "Science" -> empty list
for(var/singleton/skill_category/skill_category in GET_SINGLETON_SUBTYPE_LIST(/singleton/skill_category))
skill_tree[skill_category] = list()

// Now, initialize all the skills.
// What actually goes on here: we want a tree that we can traverse programmatically.
// To do that, we first of all make empty lists above with all the categories (they're singletons so we can easily iterate over them).
// Next, we add the empty subcategory lists if they're not present. At this point, the tree would look like "Combat" -> "Melee" -> empty list
// After that's done, if our skill is not present, add it to the empty list of the subcategory.
for(var/singleton/skill/skill in GET_SINGLETON_SUBTYPE_LIST(/singleton/skill))
var/singleton/skill_category/skill_category = GET_SINGLETON(skill.category)
if(!(skill.subcategory in skill_tree[skill_category]))
skill_tree[skill_category] |= skill.subcategory
skill_tree[skill_category][skill.subcategory] = list()

if(!(skill in skill_tree[skill_category][skill.subcategory]))
skill_tree[skill_category][skill.subcategory] |= skill
return SS_INIT_SUCCESS
29 changes: 29 additions & 0 deletions code/datums/skills/_skill_categories.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/singleton/skill_category
/// The name of the skill category.
var/name
/// The description and purpose of the skill category, displayed in the info tab.
var/desc
/// The hex colour of the skill category. Shows as background on the skills tab.
var/color
/// The number of base points a character gets in this category.
var/base_skill_points

/singleton/skill_category/proc/calculate_skill_points(datum/species/species, age, singleton/origin_item/culture, singleton/origin_item/origin)
var/list/species_modifiers = species.modify_skill_points(src, age)
return base_skill_points * species_modifiers[name]

/singleton/skill_category/everyday
name = SKILL_CATEGORY_EVERYDAY
desc = "An everyday skill is a skill that can be picked up normally. Think like mixing a drink, growing a plant, cooking, and so on."
base_skill_points = BASE_SKILL_POINTS_EVERYDAY

/singleton/skill_category/occupational
name = SKILL_CATEGORY_OCCUPATIONAL
desc = "Occupational skills are the skills necessary for you to do your job. They typically lock certain aspects of your department if you aren't proficient enough."
base_skill_points = BASE_SKILL_POINTS_OCCUPATIONAL

/singleton/skill_category/combat
name = SKILL_CATEGORY_COMBAT
desc = "A combat skill is a skill that has a direct effect in combat. These have an increased cost."
base_skill_points = BASE_SKILL_POINTS_COMBAT

40 changes: 40 additions & 0 deletions code/datums/skills/_skills.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/singleton/skill
/// The displayed name of the skill.
var/name
/// A description of this skill's effects.
var/description
/// The maximum level someone with no education can reach in this skill. Typically, this should be FAMILIAR on occupational skills.
/// If null, then there is no cap.
var/uneducated_skill_cap
/// The maximum level this skill can reach.
var/maximum_level = SKILL_LEVEL_TRAINED
/// The category of this skill. Used for sorting, typically.
var/category
/// The sub-category of this skill. Used to better sort skills.
var/subcategory
/// The modifier for how difficult the skill is. Each level costs this much * the level.
var/skill_difficulty_modifier = SKILL_MODIFIER_MEDIUM

/**
* Returns the maximum level a character can have in this skill depending on education.
*/
/singleton/skill/proc/get_maximum_level(var/singleton/education/education)
if(!istype(education))
crash_with("SKILL: Invalid [education] fed to get_maximum_level!")

// If there is no uneducated skill cap, it means we can always pick the maximum level.
if(!uneducated_skill_cap)
return maximum_level

// Otherwise, we need to check the education...
if(type in education.skills)
return education.skills[type]


return uneducated_skill_cap

/**
* Returns the cost of this skill, modified by its difficulty modifier.
*/
/singleton/skill/proc/get_cost(level)
return skill_difficulty_modifier * level
17 changes: 17 additions & 0 deletions code/datums/skills/combat/combat.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/singleton/skill/unarmed_combat
name = "Unarmed Combat"
description = "punching things"
category = /singleton/skill_category/combat
subcategory = SKILL_SUBCATEGORY_MELEE

/singleton/skill/armed_combat
name = "Armed Combat"
description = "zomboid time"
category = /singleton/skill_category/combat
subcategory = SKILL_SUBCATEGORY_MELEE

/singleton/skill/firearms
name = "Firearms"
description = "using guns. split this into close arms/longarms/special arms?"
category = /singleton/skill_category/combat
subcategory = SKILL_SUBCATEGORY_RANGED
17 changes: 17 additions & 0 deletions code/datums/skills/everyday/service.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/singleton/skill/mixing
name = "Mixing"
description = "valhalla skill"
category = /singleton/skill_category/everyday
subcategory = SKILL_SUBCATEGORY_SERVICE

/singleton/skill/cooking
name = "Cooking"
description = "Cooking Mama"
category = /singleton/skill_category/everyday
subcategory = SKILL_SUBCATEGORY_SERVICE

/singleton/skill/gardening
name = "Gardening"
description = "this is boring as shit"
category = /singleton/skill_category/everyday
subcategory = SKILL_SUBCATEGORY_SERVICE
31 changes: 31 additions & 0 deletions code/datums/skills/occupational/engineering.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/singleton/skill/electrical_engineering
name = "Electrical Engineering"
description = "Electrical engineering has to do with anything that involves wires and electricity. This includes things such as hacking doors, machines, but also \
laying down wires, or repairing wiring damage in prosthetics."
uneducated_skill_cap = SKILL_LEVEL_FAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_ENGINEERING

/singleton/skill/mechanical_engineering
name = "Mechanical Engineering"
description = "Mechanical engineering has to do with general construction of objects, walls, windows, and so on. It is also necessary for the usage of heavy machinery \
such as emitters."
uneducated_skill_cap = SKILL_LEVEL_FAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_ENGINEERING

/singleton/skill/atmospherics_systems
name = "Atmospherics Systems"
description = "Atmospherics systems involves the usage of atmospherics tooling and machinery, such as powered pumps, certain settings on air alarms, pipe wrenches, \
pipe layers, and pipe construction."
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_ENGINEERING

/singleton/skill/reactor_systems
name = "Reactor Systems"
description = "Reactor systems envelops anything used for reactors, such as the computers and gyrotrons for the INDRA. It is also necessary to correctly interpret information \
from reactor monitoring programs."
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_ENGINEERING
36 changes: 36 additions & 0 deletions code/datums/skills/occupational/medical.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/singleton/skill/medicine
name = "Medicine"
description ="how to use health analyzers, ATKs, syringes"
uneducated_skill_cap = SKILL_LEVEL_FAMILIAR
maximum_level = SKILL_LEVEL_PROFESSIONAL
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_MEDICAL

/singleton/skill/surgery
name = "Surgery"
description = "the one everyone wants to do in medical to be the protag"
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
maximum_level = SKILL_LEVEL_PROFESSIONAL
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_MEDICAL

/singleton/skill/pharmacology
name = "Pharmacology"
description = "why are you playing pharma LOL"
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_MEDICAL

/singleton/skill/anatomy
name = "Anatomy"
description = "this one lets you know what's wrong with people"
uneducated_skill_cap = SKILL_LEVEL_FAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_MEDICAL

/singleton/skill/forensics
name = "Forensics"
description = "forensics shit i guess"
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_MEDICAL
36 changes: 36 additions & 0 deletions code/datums/skills/occupational/science.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/singleton/skill/research
name = "Research"
description = "it's generic research shit, using the protolathe, destructive analyzers, etc"
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_SCIENCE

/singleton/skill/robotics
name = "Robotics"
description = "Robotics is well you know what the fuck it is man"
uneducated_skill_cap = SKILL_LEVEL_FAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_SCIENCE

/singleton/skill/xenobotany
name = "Xenobotany"
description = "Xenobotany is the creation and study of new or alien genomes of plants. It is necessary to be able to properly splice and process them."
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_SCIENCE

/singleton/skill/archaeology
name = "Xenoarchaeology"
description = "Xenoarchaeology is the study of alien civilizations, artifacts, architecture, and so on. It is necessary for the unearthing and cataloguing of \
alien artifacts."
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_SCIENCE

/singleton/skill/xenobiology
name = "Xenobiology"
description = "Xenobiology is the study of the research and cataloguing of alien lifeforms. It is necessary not only for the proper detailing of \
alien creatures, but also for their processing, such as with slimes."
uneducated_skill_cap = SKILL_LEVEL_UNFAMILIAR
category = /singleton/skill_category/occupational
subcategory = SKILL_SUBCATEGORY_SCIENCE
18 changes: 18 additions & 0 deletions code/modules/background/education/_education.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/singleton/education
/// The name of this education type.
var/name
/// The description of this education type. It should ideally match what's on the Aurora wiki, but from an IC point of view.
var/description
/// Age requirement for this education. Should match the job this is intended for. This doesn't need to be here per se, but it helps to filter results.
var/list/minimum_character_age
/// The jobs this education type allows you to access.
var/list/jobs
/// The given skills for this education type. Linked list of skill type to level.
var/list/skills
/// Species that CANNOT take this education, if necessary. This is a list of names, must match what's in the species pref variable.
/// Empty list means no restrictions.
var/list/species_restriction

/singleton/education/high_school
name = "High School Diploma"
description = "Your character has a high school diploma."
Loading
Loading