mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-13 08:56:49 +01:00
13f87e4a26
This PR fixes a bunch of skills related bugs, the biggest of which were the result of the system being overly trusting of the database, when in reality due to a bunch of unpredictable edge cases, the database is not guaranteed to always have what I think it has. To fix these bugs, I've had to slightly refactor how skills are generated on player characters and antagonists, such that the burden of proof for skills is with the Skills Subsystem rather than the Database. Skills generated for a fresh character that has NO preferences saved (Worst case scenario): <img width="1491" height="849" alt="image" src="https://github.com/user-attachments/assets/683fb538-106a-4679-8e2a-30dd45f456a1" /> Promoting that same character to Antagonist now increases certain skills to a minimum baseline: <img width="1315" height="830" alt="image" src="https://github.com/user-attachments/assets/94bcc69e-cbbe-45fa-956e-f53b7f5d2779" /> By Mel's request, Bluespace Technicians spawn with all skills fully maxed out for debugging purposes: <img width="1909" height="985" alt="image" src="https://github.com/user-attachments/assets/db4f3f65-3d87-47fc-907e-c68eae6d4cdb" />
48 lines
2.1 KiB
Plaintext
48 lines
2.1 KiB
Plaintext
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()
|
|
|
|
/**
|
|
* The set of all known skill singletons.
|
|
* These are always typed as /singleton/skill and as such are safe to for(var/singleton/skill/skill as anything in SSskills.all_skills)
|
|
*/
|
|
var/list/all_skills = list()
|
|
|
|
/**
|
|
* The set of all skills that are "forced" in order to guarantee necessary components are applied.
|
|
* These are always typed as /singleton/skill and as such are safe to for(var/singleton/skill/skill as anything in SSskills.required_skills)
|
|
*/
|
|
var/list/required_skills = list()
|
|
|
|
/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 as anything 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 as anything in GET_SINGLETON_SUBTYPE_LIST(/singleton/skill))
|
|
all_skills += skill
|
|
if (skill.required && skill.component_type)
|
|
required_skills += 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
|
|
|
|
/datum/controller/subsystem/skills/Destroy()
|
|
all_skills.Cut()
|
|
required_skills.Cut()
|
|
return ..()
|